interrupts.cc revision 5649
15647Sgblack@eecs.umich.edu/* 25647Sgblack@eecs.umich.edu * Copyright (c) 2008 The Hewlett-Packard Development Company 35647Sgblack@eecs.umich.edu * All rights reserved. 45647Sgblack@eecs.umich.edu * 55647Sgblack@eecs.umich.edu * Redistribution and use of this software in source and binary forms, 65647Sgblack@eecs.umich.edu * with or without modification, are permitted provided that the 75647Sgblack@eecs.umich.edu * following conditions are met: 85647Sgblack@eecs.umich.edu * 95647Sgblack@eecs.umich.edu * The software must be used only for Non-Commercial Use which means any 105647Sgblack@eecs.umich.edu * use which is NOT directed to receiving any direct monetary 115647Sgblack@eecs.umich.edu * compensation for, or commercial advantage from such use. Illustrative 125647Sgblack@eecs.umich.edu * examples of non-commercial use are academic research, personal study, 135647Sgblack@eecs.umich.edu * teaching, education and corporate research & development. 145647Sgblack@eecs.umich.edu * Illustrative examples of commercial use are distributing products for 155647Sgblack@eecs.umich.edu * commercial advantage and providing services using the software for 165647Sgblack@eecs.umich.edu * commercial advantage. 175647Sgblack@eecs.umich.edu * 185647Sgblack@eecs.umich.edu * If you wish to use this software or functionality therein that may be 195647Sgblack@eecs.umich.edu * covered by patents for commercial use, please contact: 205647Sgblack@eecs.umich.edu * Director of Intellectual Property Licensing 215647Sgblack@eecs.umich.edu * Office of Strategy and Technology 225647Sgblack@eecs.umich.edu * Hewlett-Packard Company 235647Sgblack@eecs.umich.edu * 1501 Page Mill Road 245647Sgblack@eecs.umich.edu * Palo Alto, California 94304 255647Sgblack@eecs.umich.edu * 265647Sgblack@eecs.umich.edu * Redistributions of source code must retain the above copyright notice, 275647Sgblack@eecs.umich.edu * this list of conditions and the following disclaimer. Redistributions 285647Sgblack@eecs.umich.edu * in binary form must reproduce the above copyright notice, this list of 295647Sgblack@eecs.umich.edu * conditions and the following disclaimer in the documentation and/or 305647Sgblack@eecs.umich.edu * other materials provided with the distribution. Neither the name of 315647Sgblack@eecs.umich.edu * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its 325647Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 335647Sgblack@eecs.umich.edu * this software without specific prior written permission. No right of 345647Sgblack@eecs.umich.edu * sublicense is granted herewith. Derivatives of the software and 355647Sgblack@eecs.umich.edu * output created using the software may be prepared, but only for 365647Sgblack@eecs.umich.edu * Non-Commercial Uses. Derivatives of the software may be shared with 375647Sgblack@eecs.umich.edu * others provided: (i) the others agree to abide by the list of 385647Sgblack@eecs.umich.edu * conditions herein which includes the Non-Commercial Use restrictions; 395647Sgblack@eecs.umich.edu * and (ii) such Derivatives of the software include the above copyright 405647Sgblack@eecs.umich.edu * notice to acknowledge the contribution from this software where 415647Sgblack@eecs.umich.edu * applicable, this list of conditions and the disclaimer below. 425647Sgblack@eecs.umich.edu * 435647Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 445647Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 455647Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 465647Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 475647Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 485647Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 495647Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 505647Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 515647Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 525647Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 535647Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 545647Sgblack@eecs.umich.edu * 555647Sgblack@eecs.umich.edu * Authors: Gabe Black 565647Sgblack@eecs.umich.edu */ 575647Sgblack@eecs.umich.edu 585648Sgblack@eecs.umich.edu#include "arch/x86/apicregs.hh" 595647Sgblack@eecs.umich.edu#include "arch/x86/interrupts.hh" 605647Sgblack@eecs.umich.edu#include "cpu/base.hh" 615647Sgblack@eecs.umich.edu 625648Sgblack@eecs.umich.eduint 635648Sgblack@eecs.umich.edudivideFromConf(uint32_t conf) 645647Sgblack@eecs.umich.edu{ 655647Sgblack@eecs.umich.edu // This figures out what division we want from the division configuration 665647Sgblack@eecs.umich.edu // register in the local APIC. The encoding is a little odd but it can 675647Sgblack@eecs.umich.edu // be deciphered fairly easily. 685647Sgblack@eecs.umich.edu int shift = ((conf & 0x8) >> 1) | (conf & 0x3); 695647Sgblack@eecs.umich.edu shift = (shift + 1) % 8; 705647Sgblack@eecs.umich.edu return 1 << shift; 715647Sgblack@eecs.umich.edu} 725647Sgblack@eecs.umich.edu 735648Sgblack@eecs.umich.edunamespace X86ISA 745647Sgblack@eecs.umich.edu{ 755648Sgblack@eecs.umich.edu 765648Sgblack@eecs.umich.eduApicRegIndex 775648Sgblack@eecs.umich.edudecodeAddr(Addr paddr) 785648Sgblack@eecs.umich.edu{ 795648Sgblack@eecs.umich.edu ApicRegIndex regNum; 805648Sgblack@eecs.umich.edu paddr &= ~mask(3); 815648Sgblack@eecs.umich.edu switch (paddr) 825648Sgblack@eecs.umich.edu { 835648Sgblack@eecs.umich.edu case 0x20: 845648Sgblack@eecs.umich.edu regNum = APIC_ID; 855648Sgblack@eecs.umich.edu break; 865648Sgblack@eecs.umich.edu case 0x30: 875648Sgblack@eecs.umich.edu regNum = APIC_VERSION; 885648Sgblack@eecs.umich.edu break; 895648Sgblack@eecs.umich.edu case 0x80: 905648Sgblack@eecs.umich.edu regNum = APIC_TASK_PRIORITY; 915648Sgblack@eecs.umich.edu break; 925648Sgblack@eecs.umich.edu case 0x90: 935648Sgblack@eecs.umich.edu regNum = APIC_ARBITRATION_PRIORITY; 945648Sgblack@eecs.umich.edu break; 955648Sgblack@eecs.umich.edu case 0xA0: 965648Sgblack@eecs.umich.edu regNum = APIC_PROCESSOR_PRIORITY; 975648Sgblack@eecs.umich.edu break; 985648Sgblack@eecs.umich.edu case 0xB0: 995648Sgblack@eecs.umich.edu regNum = APIC_EOI; 1005648Sgblack@eecs.umich.edu break; 1015648Sgblack@eecs.umich.edu case 0xD0: 1025648Sgblack@eecs.umich.edu regNum = APIC_LOGICAL_DESTINATION; 1035648Sgblack@eecs.umich.edu break; 1045648Sgblack@eecs.umich.edu case 0xE0: 1055648Sgblack@eecs.umich.edu regNum = APIC_DESTINATION_FORMAT; 1065648Sgblack@eecs.umich.edu break; 1075648Sgblack@eecs.umich.edu case 0xF0: 1085648Sgblack@eecs.umich.edu regNum = APIC_SPURIOUS_INTERRUPT_VECTOR; 1095648Sgblack@eecs.umich.edu break; 1105648Sgblack@eecs.umich.edu case 0x100: 1115648Sgblack@eecs.umich.edu case 0x108: 1125648Sgblack@eecs.umich.edu case 0x110: 1135648Sgblack@eecs.umich.edu case 0x118: 1145648Sgblack@eecs.umich.edu case 0x120: 1155648Sgblack@eecs.umich.edu case 0x128: 1165648Sgblack@eecs.umich.edu case 0x130: 1175648Sgblack@eecs.umich.edu case 0x138: 1185648Sgblack@eecs.umich.edu case 0x140: 1195648Sgblack@eecs.umich.edu case 0x148: 1205648Sgblack@eecs.umich.edu case 0x150: 1215648Sgblack@eecs.umich.edu case 0x158: 1225648Sgblack@eecs.umich.edu case 0x160: 1235648Sgblack@eecs.umich.edu case 0x168: 1245648Sgblack@eecs.umich.edu case 0x170: 1255648Sgblack@eecs.umich.edu case 0x178: 1265648Sgblack@eecs.umich.edu regNum = APIC_IN_SERVICE((paddr - 0x100) / 0x8); 1275648Sgblack@eecs.umich.edu break; 1285648Sgblack@eecs.umich.edu case 0x180: 1295648Sgblack@eecs.umich.edu case 0x188: 1305648Sgblack@eecs.umich.edu case 0x190: 1315648Sgblack@eecs.umich.edu case 0x198: 1325648Sgblack@eecs.umich.edu case 0x1A0: 1335648Sgblack@eecs.umich.edu case 0x1A8: 1345648Sgblack@eecs.umich.edu case 0x1B0: 1355648Sgblack@eecs.umich.edu case 0x1B8: 1365648Sgblack@eecs.umich.edu case 0x1C0: 1375648Sgblack@eecs.umich.edu case 0x1C8: 1385648Sgblack@eecs.umich.edu case 0x1D0: 1395648Sgblack@eecs.umich.edu case 0x1D8: 1405648Sgblack@eecs.umich.edu case 0x1E0: 1415648Sgblack@eecs.umich.edu case 0x1E8: 1425648Sgblack@eecs.umich.edu case 0x1F0: 1435648Sgblack@eecs.umich.edu case 0x1F8: 1445648Sgblack@eecs.umich.edu regNum = APIC_TRIGGER_MODE((paddr - 0x180) / 0x8); 1455648Sgblack@eecs.umich.edu break; 1465648Sgblack@eecs.umich.edu case 0x200: 1475648Sgblack@eecs.umich.edu case 0x208: 1485648Sgblack@eecs.umich.edu case 0x210: 1495648Sgblack@eecs.umich.edu case 0x218: 1505648Sgblack@eecs.umich.edu case 0x220: 1515648Sgblack@eecs.umich.edu case 0x228: 1525648Sgblack@eecs.umich.edu case 0x230: 1535648Sgblack@eecs.umich.edu case 0x238: 1545648Sgblack@eecs.umich.edu case 0x240: 1555648Sgblack@eecs.umich.edu case 0x248: 1565648Sgblack@eecs.umich.edu case 0x250: 1575648Sgblack@eecs.umich.edu case 0x258: 1585648Sgblack@eecs.umich.edu case 0x260: 1595648Sgblack@eecs.umich.edu case 0x268: 1605648Sgblack@eecs.umich.edu case 0x270: 1615648Sgblack@eecs.umich.edu case 0x278: 1625648Sgblack@eecs.umich.edu regNum = APIC_INTERRUPT_REQUEST((paddr - 0x200) / 0x8); 1635648Sgblack@eecs.umich.edu break; 1645648Sgblack@eecs.umich.edu case 0x280: 1655648Sgblack@eecs.umich.edu regNum = APIC_ERROR_STATUS; 1665648Sgblack@eecs.umich.edu break; 1675648Sgblack@eecs.umich.edu case 0x300: 1685648Sgblack@eecs.umich.edu regNum = APIC_INTERRUPT_COMMAND_LOW; 1695648Sgblack@eecs.umich.edu break; 1705648Sgblack@eecs.umich.edu case 0x310: 1715648Sgblack@eecs.umich.edu regNum = APIC_INTERRUPT_COMMAND_HIGH; 1725648Sgblack@eecs.umich.edu break; 1735648Sgblack@eecs.umich.edu case 0x320: 1745648Sgblack@eecs.umich.edu regNum = APIC_LVT_TIMER; 1755648Sgblack@eecs.umich.edu break; 1765648Sgblack@eecs.umich.edu case 0x330: 1775648Sgblack@eecs.umich.edu regNum = APIC_LVT_THERMAL_SENSOR; 1785648Sgblack@eecs.umich.edu break; 1795648Sgblack@eecs.umich.edu case 0x340: 1805648Sgblack@eecs.umich.edu regNum = APIC_LVT_PERFORMANCE_MONITORING_COUNTERS; 1815648Sgblack@eecs.umich.edu break; 1825648Sgblack@eecs.umich.edu case 0x350: 1835648Sgblack@eecs.umich.edu regNum = APIC_LVT_LINT0; 1845648Sgblack@eecs.umich.edu break; 1855648Sgblack@eecs.umich.edu case 0x360: 1865648Sgblack@eecs.umich.edu regNum = APIC_LVT_LINT1; 1875648Sgblack@eecs.umich.edu break; 1885648Sgblack@eecs.umich.edu case 0x370: 1895648Sgblack@eecs.umich.edu regNum = APIC_LVT_ERROR; 1905648Sgblack@eecs.umich.edu break; 1915648Sgblack@eecs.umich.edu case 0x380: 1925648Sgblack@eecs.umich.edu regNum = APIC_INITIAL_COUNT; 1935648Sgblack@eecs.umich.edu break; 1945648Sgblack@eecs.umich.edu case 0x390: 1955648Sgblack@eecs.umich.edu regNum = APIC_CURRENT_COUNT; 1965648Sgblack@eecs.umich.edu break; 1975648Sgblack@eecs.umich.edu case 0x3E0: 1985648Sgblack@eecs.umich.edu regNum = APIC_DIVIDE_CONFIGURATION; 1995648Sgblack@eecs.umich.edu break; 2005648Sgblack@eecs.umich.edu default: 2015648Sgblack@eecs.umich.edu // A reserved register field. 2025648Sgblack@eecs.umich.edu panic("Accessed reserved register field %#x.\n", paddr); 2035648Sgblack@eecs.umich.edu break; 2045648Sgblack@eecs.umich.edu } 2055648Sgblack@eecs.umich.edu return regNum; 2065648Sgblack@eecs.umich.edu} 2075648Sgblack@eecs.umich.edu} 2085648Sgblack@eecs.umich.edu 2095648Sgblack@eecs.umich.eduTick 2105648Sgblack@eecs.umich.eduX86ISA::Interrupts::read(PacketPtr pkt) 2115648Sgblack@eecs.umich.edu{ 2125648Sgblack@eecs.umich.edu Addr offset = pkt->getAddr() - pioAddr; 2135648Sgblack@eecs.umich.edu //Make sure we're at least only accessing one register. 2145648Sgblack@eecs.umich.edu if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3))) 2155648Sgblack@eecs.umich.edu panic("Accessed more than one register at a time in the APIC!\n"); 2165648Sgblack@eecs.umich.edu ApicRegIndex reg = decodeAddr(offset); 2175648Sgblack@eecs.umich.edu uint32_t val = htog(readReg(reg)); 2185649Sgblack@eecs.umich.edu DPRINTF(LocalApic, 2195649Sgblack@eecs.umich.edu "Reading Local APIC register %d at offset %#x as %#x.\n", 2205649Sgblack@eecs.umich.edu reg, offset, val); 2215648Sgblack@eecs.umich.edu pkt->setData(((uint8_t *)&val) + (offset & mask(3))); 2225648Sgblack@eecs.umich.edu return latency; 2235648Sgblack@eecs.umich.edu} 2245648Sgblack@eecs.umich.edu 2255648Sgblack@eecs.umich.eduTick 2265648Sgblack@eecs.umich.eduX86ISA::Interrupts::write(PacketPtr pkt) 2275648Sgblack@eecs.umich.edu{ 2285648Sgblack@eecs.umich.edu Addr offset = pkt->getAddr() - pioAddr; 2295648Sgblack@eecs.umich.edu //Make sure we're at least only accessing one register. 2305648Sgblack@eecs.umich.edu if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3))) 2315648Sgblack@eecs.umich.edu panic("Accessed more than one register at a time in the APIC!\n"); 2325648Sgblack@eecs.umich.edu ApicRegIndex reg = decodeAddr(offset); 2335648Sgblack@eecs.umich.edu uint32_t val = regs[reg]; 2345648Sgblack@eecs.umich.edu pkt->writeData(((uint8_t *)&val) + (offset & mask(3))); 2355649Sgblack@eecs.umich.edu DPRINTF(LocalApic, 2365649Sgblack@eecs.umich.edu "Writing Local APIC register %d at offset %#x as %#x.\n", 2375649Sgblack@eecs.umich.edu reg, offset, gtoh(val)); 2385648Sgblack@eecs.umich.edu setReg(reg, gtoh(val)); 2395648Sgblack@eecs.umich.edu return latency; 2405647Sgblack@eecs.umich.edu} 2415647Sgblack@eecs.umich.edu 2425647Sgblack@eecs.umich.eduuint32_t 2435648Sgblack@eecs.umich.eduX86ISA::Interrupts::readReg(ApicRegIndex reg) 2445647Sgblack@eecs.umich.edu{ 2455647Sgblack@eecs.umich.edu if (reg >= APIC_TRIGGER_MODE(0) && 2465647Sgblack@eecs.umich.edu reg <= APIC_TRIGGER_MODE(15)) { 2475647Sgblack@eecs.umich.edu panic("Local APIC Trigger Mode registers are unimplemented.\n"); 2485647Sgblack@eecs.umich.edu } 2495647Sgblack@eecs.umich.edu switch (reg) { 2505647Sgblack@eecs.umich.edu case APIC_ARBITRATION_PRIORITY: 2515647Sgblack@eecs.umich.edu panic("Local APIC Arbitration Priority register unimplemented.\n"); 2525647Sgblack@eecs.umich.edu break; 2535647Sgblack@eecs.umich.edu case APIC_PROCESSOR_PRIORITY: 2545647Sgblack@eecs.umich.edu panic("Local APIC Processor Priority register unimplemented.\n"); 2555647Sgblack@eecs.umich.edu break; 2565647Sgblack@eecs.umich.edu case APIC_EOI: 2575647Sgblack@eecs.umich.edu panic("Local APIC EOI register unimplemented.\n"); 2585647Sgblack@eecs.umich.edu break; 2595647Sgblack@eecs.umich.edu case APIC_ERROR_STATUS: 2605647Sgblack@eecs.umich.edu regs[APIC_INTERNAL_STATE] &= ~ULL(0x1); 2615647Sgblack@eecs.umich.edu break; 2625647Sgblack@eecs.umich.edu case APIC_INTERRUPT_COMMAND_LOW: 2635647Sgblack@eecs.umich.edu panic("Local APIC Interrupt Command low" 2645647Sgblack@eecs.umich.edu " register unimplemented.\n"); 2655647Sgblack@eecs.umich.edu break; 2665647Sgblack@eecs.umich.edu case APIC_INTERRUPT_COMMAND_HIGH: 2675647Sgblack@eecs.umich.edu panic("Local APIC Interrupt Command high" 2685647Sgblack@eecs.umich.edu " register unimplemented.\n"); 2695647Sgblack@eecs.umich.edu break; 2705647Sgblack@eecs.umich.edu case APIC_CURRENT_COUNT: 2715647Sgblack@eecs.umich.edu { 2725648Sgblack@eecs.umich.edu assert(clock); 2735648Sgblack@eecs.umich.edu uint32_t val = regs[reg] - curTick / clock; 2745647Sgblack@eecs.umich.edu val /= (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])); 2755647Sgblack@eecs.umich.edu return val; 2765647Sgblack@eecs.umich.edu } 2775647Sgblack@eecs.umich.edu default: 2785647Sgblack@eecs.umich.edu break; 2795647Sgblack@eecs.umich.edu } 2805648Sgblack@eecs.umich.edu return regs[reg]; 2815647Sgblack@eecs.umich.edu} 2825647Sgblack@eecs.umich.edu 2835647Sgblack@eecs.umich.eduvoid 2845648Sgblack@eecs.umich.eduX86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) 2855647Sgblack@eecs.umich.edu{ 2865647Sgblack@eecs.umich.edu uint32_t newVal = val; 2875647Sgblack@eecs.umich.edu if (reg >= APIC_IN_SERVICE(0) && 2885647Sgblack@eecs.umich.edu reg <= APIC_IN_SERVICE(15)) { 2895647Sgblack@eecs.umich.edu panic("Local APIC In-Service registers are unimplemented.\n"); 2905647Sgblack@eecs.umich.edu } 2915647Sgblack@eecs.umich.edu if (reg >= APIC_TRIGGER_MODE(0) && 2925647Sgblack@eecs.umich.edu reg <= APIC_TRIGGER_MODE(15)) { 2935647Sgblack@eecs.umich.edu panic("Local APIC Trigger Mode registers are unimplemented.\n"); 2945647Sgblack@eecs.umich.edu } 2955647Sgblack@eecs.umich.edu if (reg >= APIC_INTERRUPT_REQUEST(0) && 2965647Sgblack@eecs.umich.edu reg <= APIC_INTERRUPT_REQUEST(15)) { 2975647Sgblack@eecs.umich.edu panic("Local APIC Interrupt Request registers " 2985647Sgblack@eecs.umich.edu "are unimplemented.\n"); 2995647Sgblack@eecs.umich.edu } 3005647Sgblack@eecs.umich.edu switch (reg) { 3015647Sgblack@eecs.umich.edu case APIC_ID: 3025647Sgblack@eecs.umich.edu newVal = val & 0xFF; 3035647Sgblack@eecs.umich.edu break; 3045647Sgblack@eecs.umich.edu case APIC_VERSION: 3055647Sgblack@eecs.umich.edu // The Local APIC Version register is read only. 3065647Sgblack@eecs.umich.edu return; 3075647Sgblack@eecs.umich.edu case APIC_TASK_PRIORITY: 3085647Sgblack@eecs.umich.edu newVal = val & 0xFF; 3095647Sgblack@eecs.umich.edu break; 3105647Sgblack@eecs.umich.edu case APIC_ARBITRATION_PRIORITY: 3115647Sgblack@eecs.umich.edu panic("Local APIC Arbitration Priority register unimplemented.\n"); 3125647Sgblack@eecs.umich.edu break; 3135647Sgblack@eecs.umich.edu case APIC_PROCESSOR_PRIORITY: 3145647Sgblack@eecs.umich.edu panic("Local APIC Processor Priority register unimplemented.\n"); 3155647Sgblack@eecs.umich.edu break; 3165647Sgblack@eecs.umich.edu case APIC_EOI: 3175647Sgblack@eecs.umich.edu panic("Local APIC EOI register unimplemented.\n"); 3185647Sgblack@eecs.umich.edu break; 3195647Sgblack@eecs.umich.edu case APIC_LOGICAL_DESTINATION: 3205647Sgblack@eecs.umich.edu newVal = val & 0xFF000000; 3215647Sgblack@eecs.umich.edu break; 3225647Sgblack@eecs.umich.edu case APIC_DESTINATION_FORMAT: 3235647Sgblack@eecs.umich.edu newVal = val | 0x0FFFFFFF; 3245647Sgblack@eecs.umich.edu break; 3255647Sgblack@eecs.umich.edu case APIC_SPURIOUS_INTERRUPT_VECTOR: 3265647Sgblack@eecs.umich.edu regs[APIC_INTERNAL_STATE] &= ~ULL(1 << 1); 3275647Sgblack@eecs.umich.edu regs[APIC_INTERNAL_STATE] |= val & (1 << 8); 3285647Sgblack@eecs.umich.edu if (val & (1 << 9)) 3295647Sgblack@eecs.umich.edu warn("Focus processor checking not implemented.\n"); 3305647Sgblack@eecs.umich.edu break; 3315647Sgblack@eecs.umich.edu case APIC_ERROR_STATUS: 3325647Sgblack@eecs.umich.edu { 3335647Sgblack@eecs.umich.edu if (regs[APIC_INTERNAL_STATE] & 0x1) { 3345647Sgblack@eecs.umich.edu regs[APIC_INTERNAL_STATE] &= ~ULL(0x1); 3355647Sgblack@eecs.umich.edu newVal = 0; 3365647Sgblack@eecs.umich.edu } else { 3375647Sgblack@eecs.umich.edu regs[APIC_INTERNAL_STATE] |= ULL(0x1); 3385647Sgblack@eecs.umich.edu return; 3395647Sgblack@eecs.umich.edu } 3405647Sgblack@eecs.umich.edu 3415647Sgblack@eecs.umich.edu } 3425647Sgblack@eecs.umich.edu break; 3435647Sgblack@eecs.umich.edu case APIC_INTERRUPT_COMMAND_LOW: 3445647Sgblack@eecs.umich.edu panic("Local APIC Interrupt Command low" 3455647Sgblack@eecs.umich.edu " register unimplemented.\n"); 3465647Sgblack@eecs.umich.edu break; 3475647Sgblack@eecs.umich.edu case APIC_INTERRUPT_COMMAND_HIGH: 3485647Sgblack@eecs.umich.edu panic("Local APIC Interrupt Command high" 3495647Sgblack@eecs.umich.edu " register unimplemented.\n"); 3505647Sgblack@eecs.umich.edu break; 3515647Sgblack@eecs.umich.edu case APIC_LVT_TIMER: 3525647Sgblack@eecs.umich.edu case APIC_LVT_THERMAL_SENSOR: 3535647Sgblack@eecs.umich.edu case APIC_LVT_PERFORMANCE_MONITORING_COUNTERS: 3545647Sgblack@eecs.umich.edu case APIC_LVT_LINT0: 3555647Sgblack@eecs.umich.edu case APIC_LVT_LINT1: 3565647Sgblack@eecs.umich.edu case APIC_LVT_ERROR: 3575647Sgblack@eecs.umich.edu { 3585647Sgblack@eecs.umich.edu uint64_t readOnlyMask = (1 << 12) | (1 << 14); 3595647Sgblack@eecs.umich.edu newVal = (val & ~readOnlyMask) | 3605647Sgblack@eecs.umich.edu (regs[reg] & readOnlyMask); 3615647Sgblack@eecs.umich.edu } 3625647Sgblack@eecs.umich.edu break; 3635647Sgblack@eecs.umich.edu case APIC_INITIAL_COUNT: 3645648Sgblack@eecs.umich.edu { 3655648Sgblack@eecs.umich.edu assert(clock); 3665648Sgblack@eecs.umich.edu newVal = bits(val, 31, 0); 3675648Sgblack@eecs.umich.edu uint32_t newCount = newVal * 3685648Sgblack@eecs.umich.edu (divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]) * 16); 3695648Sgblack@eecs.umich.edu regs[APIC_CURRENT_COUNT] = newCount + curTick / clock; 3705648Sgblack@eecs.umich.edu // Find out how long a "tick" of the timer should take. 3715648Sgblack@eecs.umich.edu Tick timerTick = 16 * clock; 3725648Sgblack@eecs.umich.edu // Schedule on the edge of the next tick plus the new count. 3735648Sgblack@eecs.umich.edu Tick offset = curTick % timerTick; 3745648Sgblack@eecs.umich.edu if (offset) { 3755648Sgblack@eecs.umich.edu reschedule(apicTimerEvent, 3765648Sgblack@eecs.umich.edu curTick + (newCount + 1) * timerTick - offset, true); 3775648Sgblack@eecs.umich.edu } else { 3785648Sgblack@eecs.umich.edu reschedule(apicTimerEvent, 3795648Sgblack@eecs.umich.edu curTick + newCount * timerTick, true); 3805648Sgblack@eecs.umich.edu } 3815648Sgblack@eecs.umich.edu } 3825647Sgblack@eecs.umich.edu break; 3835647Sgblack@eecs.umich.edu case APIC_CURRENT_COUNT: 3845647Sgblack@eecs.umich.edu //Local APIC Current Count register is read only. 3855647Sgblack@eecs.umich.edu return; 3865647Sgblack@eecs.umich.edu case APIC_DIVIDE_CONFIGURATION: 3875647Sgblack@eecs.umich.edu newVal = val & 0xB; 3885647Sgblack@eecs.umich.edu break; 3895647Sgblack@eecs.umich.edu default: 3905647Sgblack@eecs.umich.edu break; 3915647Sgblack@eecs.umich.edu } 3925648Sgblack@eecs.umich.edu regs[reg] = newVal; 3935647Sgblack@eecs.umich.edu return; 3945647Sgblack@eecs.umich.edu} 3955647Sgblack@eecs.umich.edu 3965647Sgblack@eecs.umich.eduX86ISA::Interrupts * 3975647Sgblack@eecs.umich.eduX86LocalApicParams::create() 3985647Sgblack@eecs.umich.edu{ 3995647Sgblack@eecs.umich.edu return new X86ISA::Interrupts(this); 4005647Sgblack@eecs.umich.edu} 401