interrupts.cc revision 5654
1955SN/A/* 2955SN/A * Copyright (c) 2008 The Hewlett-Packard Development Company 31762SN/A * All rights reserved. 4955SN/A * 5955SN/A * Redistribution and use of this software in source and binary forms, 6955SN/A * with or without modification, are permitted provided that the 7955SN/A * following conditions are met: 8955SN/A * 9955SN/A * The software must be used only for Non-Commercial Use which means any 10955SN/A * use which is NOT directed to receiving any direct monetary 11955SN/A * compensation for, or commercial advantage from such use. Illustrative 12955SN/A * examples of non-commercial use are academic research, personal study, 13955SN/A * teaching, education and corporate research & development. 14955SN/A * Illustrative examples of commercial use are distributing products for 15955SN/A * commercial advantage and providing services using the software for 16955SN/A * commercial advantage. 17955SN/A * 18955SN/A * If you wish to use this software or functionality therein that may be 19955SN/A * covered by patents for commercial use, please contact: 20955SN/A * Director of Intellectual Property Licensing 21955SN/A * Office of Strategy and Technology 22955SN/A * Hewlett-Packard Company 23955SN/A * 1501 Page Mill Road 24955SN/A * Palo Alto, California 94304 25955SN/A * 26955SN/A * Redistributions of source code must retain the above copyright notice, 27955SN/A * this list of conditions and the following disclaimer. Redistributions 282665Ssaidi@eecs.umich.edu * in binary form must reproduce the above copyright notice, this list of 294762Snate@binkert.org * conditions and the following disclaimer in the documentation and/or 30955SN/A * other materials provided with the distribution. Neither the name of 315522Snate@binkert.org * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its 326143Snate@binkert.org * contributors may be used to endorse or promote products derived from 334762Snate@binkert.org * this software without specific prior written permission. No right of 345522Snate@binkert.org * sublicense is granted herewith. Derivatives of the software and 35955SN/A * output created using the software may be prepared, but only for 365522Snate@binkert.org * Non-Commercial Uses. Derivatives of the software may be shared with 3711974Sgabeblack@google.com * others provided: (i) the others agree to abide by the list of 38955SN/A * conditions herein which includes the Non-Commercial Use restrictions; 395522Snate@binkert.org * and (ii) such Derivatives of the software include the above copyright 404202Sbinkertn@umich.edu * notice to acknowledge the contribution from this software where 415742Snate@binkert.org * applicable, this list of conditions and the disclaimer below. 42955SN/A * 434381Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 444381Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 458334Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 46955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 47955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 484202Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 49955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 504382Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 514382Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 524382Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 536654Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 545517Snate@binkert.org * 558614Sgblack@eecs.umich.edu * Authors: Gabe Black 567674Snate@binkert.org */ 576143Snate@binkert.org 586143Snate@binkert.org#include "arch/x86/apicregs.hh" 596143Snate@binkert.org#include "arch/x86/interrupts.hh" 608233Snate@binkert.org#include "arch/x86/intmessage.hh" 618233Snate@binkert.org#include "cpu/base.hh" 628233Snate@binkert.org#include "mem/packet_access.hh" 638233Snate@binkert.org 648233Snate@binkert.orgint 658334Snate@binkert.orgdivideFromConf(uint32_t conf) 668334Snate@binkert.org{ 6710453SAndrew.Bardsley@arm.com // This figures out what division we want from the division configuration 6810453SAndrew.Bardsley@arm.com // register in the local APIC. The encoding is a little odd but it can 698233Snate@binkert.org // be deciphered fairly easily. 708233Snate@binkert.org int shift = ((conf & 0x8) >> 1) | (conf & 0x3); 718233Snate@binkert.org shift = (shift + 1) % 8; 728233Snate@binkert.org return 1 << shift; 738233Snate@binkert.org} 748233Snate@binkert.org 7511983Sgabeblack@google.comnamespace X86ISA 7611983Sgabeblack@google.com{ 7711983Sgabeblack@google.com 7811983Sgabeblack@google.comApicRegIndex 7911983Sgabeblack@google.comdecodeAddr(Addr paddr) 8011983Sgabeblack@google.com{ 8111983Sgabeblack@google.com ApicRegIndex regNum; 8211983Sgabeblack@google.com paddr &= ~mask(3); 8311983Sgabeblack@google.com switch (paddr) 8411983Sgabeblack@google.com { 8511983Sgabeblack@google.com case 0x20: 866143Snate@binkert.org regNum = APIC_ID; 878233Snate@binkert.org break; 888233Snate@binkert.org case 0x30: 898233Snate@binkert.org regNum = APIC_VERSION; 906143Snate@binkert.org break; 916143Snate@binkert.org case 0x80: 926143Snate@binkert.org regNum = APIC_TASK_PRIORITY; 9311308Santhony.gutierrez@amd.com break; 948233Snate@binkert.org case 0x90: 958233Snate@binkert.org regNum = APIC_ARBITRATION_PRIORITY; 968233Snate@binkert.org break; 9711983Sgabeblack@google.com case 0xA0: 9811983Sgabeblack@google.com regNum = APIC_PROCESSOR_PRIORITY; 994762Snate@binkert.org break; 1006143Snate@binkert.org case 0xB0: 1018233Snate@binkert.org regNum = APIC_EOI; 1028233Snate@binkert.org break; 1038233Snate@binkert.org case 0xD0: 1048233Snate@binkert.org regNum = APIC_LOGICAL_DESTINATION; 1058233Snate@binkert.org break; 1066143Snate@binkert.org case 0xE0: 1078233Snate@binkert.org regNum = APIC_DESTINATION_FORMAT; 1088233Snate@binkert.org break; 1098233Snate@binkert.org case 0xF0: 1108233Snate@binkert.org regNum = APIC_SPURIOUS_INTERRUPT_VECTOR; 1116143Snate@binkert.org break; 1126143Snate@binkert.org case 0x100: 1136143Snate@binkert.org case 0x108: 1146143Snate@binkert.org case 0x110: 1156143Snate@binkert.org case 0x118: 1166143Snate@binkert.org case 0x120: 1176143Snate@binkert.org case 0x128: 1186143Snate@binkert.org case 0x130: 1196143Snate@binkert.org case 0x138: 1207065Snate@binkert.org case 0x140: 1216143Snate@binkert.org case 0x148: 1228233Snate@binkert.org case 0x150: 1238233Snate@binkert.org case 0x158: 1248233Snate@binkert.org case 0x160: 1258233Snate@binkert.org case 0x168: 1268233Snate@binkert.org case 0x170: 1278233Snate@binkert.org case 0x178: 1288233Snate@binkert.org regNum = APIC_IN_SERVICE((paddr - 0x100) / 0x8); 1298233Snate@binkert.org break; 1308233Snate@binkert.org case 0x180: 1318233Snate@binkert.org case 0x188: 1328233Snate@binkert.org case 0x190: 1338233Snate@binkert.org case 0x198: 1348233Snate@binkert.org case 0x1A0: 1358233Snate@binkert.org case 0x1A8: 1368233Snate@binkert.org case 0x1B0: 1378233Snate@binkert.org case 0x1B8: 1388233Snate@binkert.org case 0x1C0: 1398233Snate@binkert.org case 0x1C8: 1408233Snate@binkert.org case 0x1D0: 1418233Snate@binkert.org case 0x1D8: 1428233Snate@binkert.org case 0x1E0: 1438233Snate@binkert.org case 0x1E8: 1448233Snate@binkert.org case 0x1F0: 1458233Snate@binkert.org case 0x1F8: 1468233Snate@binkert.org regNum = APIC_TRIGGER_MODE((paddr - 0x180) / 0x8); 1478233Snate@binkert.org break; 1488233Snate@binkert.org case 0x200: 1498233Snate@binkert.org case 0x208: 1508233Snate@binkert.org case 0x210: 1518233Snate@binkert.org case 0x218: 1528233Snate@binkert.org case 0x220: 1536143Snate@binkert.org case 0x228: 1546143Snate@binkert.org case 0x230: 1556143Snate@binkert.org case 0x238: 1566143Snate@binkert.org case 0x240: 1576143Snate@binkert.org case 0x248: 1586143Snate@binkert.org case 0x250: 1599982Satgutier@umich.edu case 0x258: 16010196SCurtis.Dunham@arm.com case 0x260: 16110196SCurtis.Dunham@arm.com case 0x268: 16210196SCurtis.Dunham@arm.com case 0x270: 16310196SCurtis.Dunham@arm.com case 0x278: 16410196SCurtis.Dunham@arm.com regNum = APIC_INTERRUPT_REQUEST((paddr - 0x200) / 0x8); 16510196SCurtis.Dunham@arm.com break; 16610196SCurtis.Dunham@arm.com case 0x280: 16710196SCurtis.Dunham@arm.com regNum = APIC_ERROR_STATUS; 1686143Snate@binkert.org break; 16911983Sgabeblack@google.com case 0x300: 17011983Sgabeblack@google.com regNum = APIC_INTERRUPT_COMMAND_LOW; 17111983Sgabeblack@google.com break; 17211983Sgabeblack@google.com case 0x310: 17311983Sgabeblack@google.com regNum = APIC_INTERRUPT_COMMAND_HIGH; 17411983Sgabeblack@google.com break; 17511983Sgabeblack@google.com case 0x320: 17611983Sgabeblack@google.com regNum = APIC_LVT_TIMER; 17711983Sgabeblack@google.com break; 1786143Snate@binkert.org case 0x330: 17911988Sandreas.sandberg@arm.com regNum = APIC_LVT_THERMAL_SENSOR; 1808233Snate@binkert.org break; 1818233Snate@binkert.org case 0x340: 1826143Snate@binkert.org regNum = APIC_LVT_PERFORMANCE_MONITORING_COUNTERS; 1838945Ssteve.reinhardt@amd.com break; 1846143Snate@binkert.org case 0x350: 18511983Sgabeblack@google.com regNum = APIC_LVT_LINT0; 18611983Sgabeblack@google.com break; 1876143Snate@binkert.org case 0x360: 1886143Snate@binkert.org regNum = APIC_LVT_LINT1; 1895522Snate@binkert.org break; 1906143Snate@binkert.org case 0x370: 1916143Snate@binkert.org regNum = APIC_LVT_ERROR; 1926143Snate@binkert.org break; 1939982Satgutier@umich.edu case 0x380: 1948233Snate@binkert.org regNum = APIC_INITIAL_COUNT; 1958233Snate@binkert.org break; 1968233Snate@binkert.org case 0x390: 1976143Snate@binkert.org regNum = APIC_CURRENT_COUNT; 1986143Snate@binkert.org break; 1996143Snate@binkert.org case 0x3E0: 2006143Snate@binkert.org regNum = APIC_DIVIDE_CONFIGURATION; 2015522Snate@binkert.org break; 2025522Snate@binkert.org default: 2035522Snate@binkert.org // A reserved register field. 2045522Snate@binkert.org panic("Accessed reserved register field %#x.\n", paddr); 2055604Snate@binkert.org break; 2065604Snate@binkert.org } 2076143Snate@binkert.org return regNum; 2086143Snate@binkert.org} 2094762Snate@binkert.org} 2104762Snate@binkert.org 2116143Snate@binkert.orgTick 2126727Ssteve.reinhardt@amd.comX86ISA::Interrupts::read(PacketPtr pkt) 2136727Ssteve.reinhardt@amd.com{ 2146727Ssteve.reinhardt@amd.com Addr offset = pkt->getAddr() - pioAddr; 2154762Snate@binkert.org //Make sure we're at least only accessing one register. 2166143Snate@binkert.org if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3))) 2176143Snate@binkert.org panic("Accessed more than one register at a time in the APIC!\n"); 2186143Snate@binkert.org ApicRegIndex reg = decodeAddr(offset); 2196143Snate@binkert.org uint32_t val = htog(readReg(reg)); 2206727Ssteve.reinhardt@amd.com DPRINTF(LocalApic, 2216143Snate@binkert.org "Reading Local APIC register %d at offset %#x as %#x.\n", 2227674Snate@binkert.org reg, offset, val); 2237674Snate@binkert.org pkt->setData(((uint8_t *)&val) + (offset & mask(3))); 2245604Snate@binkert.org return latency; 2256143Snate@binkert.org} 2266143Snate@binkert.org 2276143Snate@binkert.orgTick 2284762Snate@binkert.orgX86ISA::Interrupts::write(PacketPtr pkt) 2296143Snate@binkert.org{ 2304762Snate@binkert.org Addr offset = pkt->getAddr() - pioAddr; 2314762Snate@binkert.org //Make sure we're at least only accessing one register. 2324762Snate@binkert.org if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3))) 2336143Snate@binkert.org panic("Accessed more than one register at a time in the APIC!\n"); 2346143Snate@binkert.org ApicRegIndex reg = decodeAddr(offset); 2354762Snate@binkert.org uint32_t val = regs[reg]; 2368233Snate@binkert.org pkt->writeData(((uint8_t *)&val) + (offset & mask(3))); 2378233Snate@binkert.org DPRINTF(LocalApic, 2388233Snate@binkert.org "Writing Local APIC register %d at offset %#x as %#x.\n", 2398233Snate@binkert.org reg, offset, gtoh(val)); 2406143Snate@binkert.org setReg(reg, gtoh(val)); 2416143Snate@binkert.org return latency; 2424762Snate@binkert.org} 2436143Snate@binkert.org 2444762Snate@binkert.orgTick 2459396Sandreas.hansson@arm.comX86ISA::Interrupts::recvMessage(PacketPtr pkt) 2469396Sandreas.hansson@arm.com{ 2479396Sandreas.hansson@arm.com uint8_t id = 0; 2489396Sandreas.hansson@arm.com Addr offset = pkt->getAddr() - x86InterruptAddress(id, 0); 2499396Sandreas.hansson@arm.com assert(pkt->cmd == MemCmd::MessageReq); 2509396Sandreas.hansson@arm.com switch(offset) 2519396Sandreas.hansson@arm.com { 2529396Sandreas.hansson@arm.com case 0: 2539396Sandreas.hansson@arm.com { 2549396Sandreas.hansson@arm.com TriggerIntMessage message = pkt->get<TriggerIntMessage>(); 2559396Sandreas.hansson@arm.com uint8_t vector = message.vector; 2569396Sandreas.hansson@arm.com DPRINTF(LocalApic, 2579396Sandreas.hansson@arm.com "Got Trigger Interrupt message with vector %#x.\n", 2589930Sandreas.hansson@arm.com vector); 2599930Sandreas.hansson@arm.com // Make sure we're really supposed to get this. 2609396Sandreas.hansson@arm.com assert((message.destMode == 0 && message.destination == id) || 2618235Snate@binkert.org (bits((int)message.destination, id))); 2628235Snate@binkert.org if (DeliveryMode::isUnmaskable(message.deliveryMode)) { 2636143Snate@binkert.org DPRINTF(LocalApic, "Interrupt is an %s and unmaskable.\n", 2648235Snate@binkert.org DeliveryMode::names[message.deliveryMode]); 2659003SAli.Saidi@ARM.com panic("Unmaskable interrupts aren't implemented.\n"); 2668235Snate@binkert.org } else if (DeliveryMode::isMaskable(message.deliveryMode)) { 2678235Snate@binkert.org DPRINTF(LocalApic, "Interrupt is an %s and maskable.\n", 2688235Snate@binkert.org DeliveryMode::names[message.deliveryMode]); 2698235Snate@binkert.org // Queue up the interrupt in the IRR. 2708235Snate@binkert.org if (vector > IRRV) 2718235Snate@binkert.org IRRV = vector; 2728235Snate@binkert.org if (!getRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector)) { 2738235Snate@binkert.org setRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector); 2748235Snate@binkert.org if (message.trigger) { 2758235Snate@binkert.org // Level triggered. 2768235Snate@binkert.org setRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); 2778235Snate@binkert.org } else { 2788235Snate@binkert.org // Edge triggered. 2798235Snate@binkert.org clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); 2809003SAli.Saidi@ARM.com } 2818235Snate@binkert.org } 2825584Snate@binkert.org } 2834382Sbinkertn@umich.edu } 2844202Sbinkertn@umich.edu break; 2854382Sbinkertn@umich.edu default: 2864382Sbinkertn@umich.edu panic("Local apic got unknown interrupt message at offset %#x.\n", 2879396Sandreas.hansson@arm.com offset); 2885584Snate@binkert.org break; 2894382Sbinkertn@umich.edu } 2904382Sbinkertn@umich.edu delete pkt->req; 2914382Sbinkertn@umich.edu delete pkt; 2928232Snate@binkert.org return latency; 2935192Ssaidi@eecs.umich.edu} 2948232Snate@binkert.org 2958232Snate@binkert.org 2968232Snate@binkert.orguint32_t 2975192Ssaidi@eecs.umich.eduX86ISA::Interrupts::readReg(ApicRegIndex reg) 2988232Snate@binkert.org{ 2995192Ssaidi@eecs.umich.edu if (reg >= APIC_TRIGGER_MODE(0) && 3005799Snate@binkert.org reg <= APIC_TRIGGER_MODE(15)) { 3018232Snate@binkert.org panic("Local APIC Trigger Mode registers are unimplemented.\n"); 3025192Ssaidi@eecs.umich.edu } 3035192Ssaidi@eecs.umich.edu switch (reg) { 3045192Ssaidi@eecs.umich.edu case APIC_ARBITRATION_PRIORITY: 3058232Snate@binkert.org panic("Local APIC Arbitration Priority register unimplemented.\n"); 3065192Ssaidi@eecs.umich.edu break; 3078232Snate@binkert.org case APIC_PROCESSOR_PRIORITY: 3085192Ssaidi@eecs.umich.edu panic("Local APIC Processor Priority register unimplemented.\n"); 3095192Ssaidi@eecs.umich.edu break; 3105192Ssaidi@eecs.umich.edu case APIC_EOI: 3115192Ssaidi@eecs.umich.edu panic("Local APIC EOI register unimplemented.\n"); 3124382Sbinkertn@umich.edu break; 3134382Sbinkertn@umich.edu case APIC_ERROR_STATUS: 3144382Sbinkertn@umich.edu regs[APIC_INTERNAL_STATE] &= ~ULL(0x1); 3152667Sstever@eecs.umich.edu break; 3162667Sstever@eecs.umich.edu case APIC_INTERRUPT_COMMAND_LOW: 3172667Sstever@eecs.umich.edu panic("Local APIC Interrupt Command low" 3182667Sstever@eecs.umich.edu " register unimplemented.\n"); 3192667Sstever@eecs.umich.edu break; 3202667Sstever@eecs.umich.edu case APIC_INTERRUPT_COMMAND_HIGH: 3215742Snate@binkert.org panic("Local APIC Interrupt Command high" 3225742Snate@binkert.org " register unimplemented.\n"); 3235742Snate@binkert.org break; 3245793Snate@binkert.org case APIC_CURRENT_COUNT: 3258334Snate@binkert.org { 3265793Snate@binkert.org assert(clock); 3275793Snate@binkert.org uint32_t val = regs[reg] - curTick / clock; 3285793Snate@binkert.org val /= (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])); 3294382Sbinkertn@umich.edu return val; 3304762Snate@binkert.org } 3315344Sstever@gmail.com default: 3324382Sbinkertn@umich.edu break; 3335341Sstever@gmail.com } 3345742Snate@binkert.org return regs[reg]; 3355742Snate@binkert.org} 3365742Snate@binkert.org 3375742Snate@binkert.orgvoid 3385742Snate@binkert.orgX86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) 3394762Snate@binkert.org{ 3405742Snate@binkert.org uint32_t newVal = val; 3415742Snate@binkert.org if (reg >= APIC_IN_SERVICE(0) && 34211984Sgabeblack@google.com reg <= APIC_IN_SERVICE(15)) { 3437722Sgblack@eecs.umich.edu panic("Local APIC In-Service registers are unimplemented.\n"); 3445742Snate@binkert.org } 3455742Snate@binkert.org if (reg >= APIC_TRIGGER_MODE(0) && 3465742Snate@binkert.org reg <= APIC_TRIGGER_MODE(15)) { 3479930Sandreas.hansson@arm.com panic("Local APIC Trigger Mode registers are unimplemented.\n"); 3489930Sandreas.hansson@arm.com } 3499930Sandreas.hansson@arm.com if (reg >= APIC_INTERRUPT_REQUEST(0) && 3509930Sandreas.hansson@arm.com reg <= APIC_INTERRUPT_REQUEST(15)) { 3519930Sandreas.hansson@arm.com panic("Local APIC Interrupt Request registers " 3525742Snate@binkert.org "are unimplemented.\n"); 3538242Sbradley.danofsky@amd.com } 3548242Sbradley.danofsky@amd.com switch (reg) { 3558242Sbradley.danofsky@amd.com case APIC_ID: 3568242Sbradley.danofsky@amd.com newVal = val & 0xFF; 3575341Sstever@gmail.com break; 3585742Snate@binkert.org case APIC_VERSION: 3597722Sgblack@eecs.umich.edu // The Local APIC Version register is read only. 3604773Snate@binkert.org return; 3616108Snate@binkert.org case APIC_TASK_PRIORITY: 3621858SN/A newVal = val & 0xFF; 3631085SN/A break; 3646658Snate@binkert.org case APIC_ARBITRATION_PRIORITY: 3656658Snate@binkert.org panic("Local APIC Arbitration Priority register unimplemented.\n"); 3667673Snate@binkert.org break; 3676658Snate@binkert.org case APIC_PROCESSOR_PRIORITY: 3686658Snate@binkert.org panic("Local APIC Processor Priority register unimplemented.\n"); 36911308Santhony.gutierrez@amd.com break; 3706658Snate@binkert.org case APIC_EOI: 37111308Santhony.gutierrez@amd.com panic("Local APIC EOI register unimplemented.\n"); 3726658Snate@binkert.org break; 3736658Snate@binkert.org case APIC_LOGICAL_DESTINATION: 3747673Snate@binkert.org newVal = val & 0xFF000000; 3757673Snate@binkert.org break; 3767673Snate@binkert.org case APIC_DESTINATION_FORMAT: 3777673Snate@binkert.org newVal = val | 0x0FFFFFFF; 3787673Snate@binkert.org break; 3797673Snate@binkert.org case APIC_SPURIOUS_INTERRUPT_VECTOR: 3807673Snate@binkert.org regs[APIC_INTERNAL_STATE] &= ~ULL(1 << 1); 38110467Sandreas.hansson@arm.com regs[APIC_INTERNAL_STATE] |= val & (1 << 8); 3826658Snate@binkert.org if (val & (1 << 9)) 3837673Snate@binkert.org warn("Focus processor checking not implemented.\n"); 38410467Sandreas.hansson@arm.com break; 38510467Sandreas.hansson@arm.com case APIC_ERROR_STATUS: 38610467Sandreas.hansson@arm.com { 38710467Sandreas.hansson@arm.com if (regs[APIC_INTERNAL_STATE] & 0x1) { 38810467Sandreas.hansson@arm.com regs[APIC_INTERNAL_STATE] &= ~ULL(0x1); 38910467Sandreas.hansson@arm.com newVal = 0; 39010467Sandreas.hansson@arm.com } else { 39110467Sandreas.hansson@arm.com regs[APIC_INTERNAL_STATE] |= ULL(0x1); 39210467Sandreas.hansson@arm.com return; 39310467Sandreas.hansson@arm.com } 39410467Sandreas.hansson@arm.com 3957673Snate@binkert.org } 3967673Snate@binkert.org break; 3977673Snate@binkert.org case APIC_INTERRUPT_COMMAND_LOW: 3987673Snate@binkert.org panic("Local APIC Interrupt Command low" 3997673Snate@binkert.org " register unimplemented.\n"); 4009048SAli.Saidi@ARM.com break; 4017673Snate@binkert.org case APIC_INTERRUPT_COMMAND_HIGH: 4027673Snate@binkert.org panic("Local APIC Interrupt Command high" 4037673Snate@binkert.org " register unimplemented.\n"); 4047673Snate@binkert.org break; 4056658Snate@binkert.org case APIC_LVT_TIMER: 4067756SAli.Saidi@ARM.com case APIC_LVT_THERMAL_SENSOR: 4077816Ssteve.reinhardt@amd.com case APIC_LVT_PERFORMANCE_MONITORING_COUNTERS: 4086658Snate@binkert.org case APIC_LVT_LINT0: 40911308Santhony.gutierrez@amd.com case APIC_LVT_LINT1: 41011308Santhony.gutierrez@amd.com case APIC_LVT_ERROR: 41111308Santhony.gutierrez@amd.com { 41211308Santhony.gutierrez@amd.com uint64_t readOnlyMask = (1 << 12) | (1 << 14); 41311308Santhony.gutierrez@amd.com newVal = (val & ~readOnlyMask) | 41411308Santhony.gutierrez@amd.com (regs[reg] & readOnlyMask); 41511308Santhony.gutierrez@amd.com } 41611308Santhony.gutierrez@amd.com break; 41711308Santhony.gutierrez@amd.com case APIC_INITIAL_COUNT: 41811308Santhony.gutierrez@amd.com { 41911308Santhony.gutierrez@amd.com assert(clock); 42011308Santhony.gutierrez@amd.com newVal = bits(val, 31, 0); 42111308Santhony.gutierrez@amd.com uint32_t newCount = newVal * 42211308Santhony.gutierrez@amd.com (divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]) * 16); 42311308Santhony.gutierrez@amd.com regs[APIC_CURRENT_COUNT] = newCount + curTick / clock; 42411308Santhony.gutierrez@amd.com // Find out how long a "tick" of the timer should take. 42511308Santhony.gutierrez@amd.com Tick timerTick = 16 * clock; 42611308Santhony.gutierrez@amd.com // Schedule on the edge of the next tick plus the new count. 42711308Santhony.gutierrez@amd.com Tick offset = curTick % timerTick; 42811308Santhony.gutierrez@amd.com if (offset) { 42911308Santhony.gutierrez@amd.com reschedule(apicTimerEvent, 43011308Santhony.gutierrez@amd.com curTick + (newCount + 1) * timerTick - offset, true); 43111308Santhony.gutierrez@amd.com } else { 43211308Santhony.gutierrez@amd.com reschedule(apicTimerEvent, 43311308Santhony.gutierrez@amd.com curTick + newCount * timerTick, true); 43411308Santhony.gutierrez@amd.com } 43511308Santhony.gutierrez@amd.com } 43611308Santhony.gutierrez@amd.com break; 43711308Santhony.gutierrez@amd.com case APIC_CURRENT_COUNT: 43811308Santhony.gutierrez@amd.com //Local APIC Current Count register is read only. 43911308Santhony.gutierrez@amd.com return; 44011308Santhony.gutierrez@amd.com case APIC_DIVIDE_CONFIGURATION: 44111308Santhony.gutierrez@amd.com newVal = val & 0xB; 44211308Santhony.gutierrez@amd.com break; 44311308Santhony.gutierrez@amd.com default: 44411308Santhony.gutierrez@amd.com break; 44511308Santhony.gutierrez@amd.com } 44611308Santhony.gutierrez@amd.com regs[reg] = newVal; 44711308Santhony.gutierrez@amd.com return; 44811308Santhony.gutierrez@amd.com} 44911308Santhony.gutierrez@amd.com 45011308Santhony.gutierrez@amd.combool 45111308Santhony.gutierrez@amd.comX86ISA::Interrupts::check_interrupts(ThreadContext * tc) const 45211308Santhony.gutierrez@amd.com{ 45311308Santhony.gutierrez@amd.com RFLAGS rflags = tc->readMiscRegNoEffect(MISCREG_RFLAGS); 4544382Sbinkertn@umich.edu if (IRRV > ISRV && rflags.intf && 4554382Sbinkertn@umich.edu bits(IRRV, 7, 4) > bits(regs[APIC_TASK_PRIORITY], 7, 4)) { 4564762Snate@binkert.org return true; 4574762Snate@binkert.org } 4584762Snate@binkert.org return false; 4596654Snate@binkert.org} 4606654Snate@binkert.org 4615517Snate@binkert.orgFault 4625517Snate@binkert.orgX86ISA::Interrupts::getInterrupt(ThreadContext * tc) 4635517Snate@binkert.org{ 4645517Snate@binkert.org assert(check_interrupts(tc)); 4655517Snate@binkert.org return new ExternalInterrupt(IRRV); 4665517Snate@binkert.org} 4675517Snate@binkert.org 4685517Snate@binkert.orgvoid 4695517Snate@binkert.orgX86ISA::Interrupts::updateIntrInfo(ThreadContext * tc) 4705517Snate@binkert.org{ 4715517Snate@binkert.org assert(check_interrupts(tc)); 4725517Snate@binkert.org // Mark the interrupt as "in service". 4735517Snate@binkert.org ISRV = IRRV; 4745517Snate@binkert.org setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV); 4755517Snate@binkert.org // Clear it out of the IRR. 4765517Snate@binkert.org clearRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, IRRV); 4775517Snate@binkert.org updateIRRV(); 4786654Snate@binkert.org} 4795517Snate@binkert.org 4805517Snate@binkert.orgX86ISA::Interrupts * 4815517Snate@binkert.orgX86LocalApicParams::create() 4825517Snate@binkert.org{ 4835517Snate@binkert.org return new X86ISA::Interrupts(this); 48411802Sandreas.sandberg@arm.com} 4855517Snate@binkert.org