interrupts.hh revision 7087
14120Sgblack@eecs.umich.edu/* 24120Sgblack@eecs.umich.edu * Copyright (c) 2007 The Hewlett-Packard Development Company 34120Sgblack@eecs.umich.edu * All rights reserved. 44120Sgblack@eecs.umich.edu * 57087Snate@binkert.org * The license below extends only to copyright in the software and shall 67087Snate@binkert.org * not be construed as granting a license to any other intellectual 77087Snate@binkert.org * property including but not limited to intellectual property relating 87087Snate@binkert.org * to a hardware implementation of the functionality of the software 97087Snate@binkert.org * licensed hereunder. You may use the software subject to the license 107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated 117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software, 127087Snate@binkert.org * modified or unmodified, in source code or in binary form. 134120Sgblack@eecs.umich.edu * 147087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 157087Snate@binkert.org * modification, are permitted provided that the following conditions are 167087Snate@binkert.org * met: redistributions of source code must retain the above copyright 177087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 187087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 197087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 207087Snate@binkert.org * documentation and/or other materials provided with the distribution; 217087Snate@binkert.org * neither the name of the copyright holders nor the names of its 224120Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 237087Snate@binkert.org * this software without specific prior written permission. 244120Sgblack@eecs.umich.edu * 254120Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 264120Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 274120Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 284120Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 294120Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 304120Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 314120Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 324120Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 334120Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 344120Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 354120Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 364120Sgblack@eecs.umich.edu * 374120Sgblack@eecs.umich.edu * Authors: Gabe Black 384120Sgblack@eecs.umich.edu */ 394120Sgblack@eecs.umich.edu 404120Sgblack@eecs.umich.edu#ifndef __ARCH_X86_INTERRUPTS_HH__ 414120Sgblack@eecs.umich.edu#define __ARCH_X86_INTERRUPTS_HH__ 424120Sgblack@eecs.umich.edu 435647Sgblack@eecs.umich.edu#include "arch/x86/apicregs.hh" 445086Sgblack@eecs.umich.edu#include "arch/x86/faults.hh" 455655Sgblack@eecs.umich.edu#include "arch/x86/intmessage.hh" 465654Sgblack@eecs.umich.edu#include "base/bitfield.hh" 475086Sgblack@eecs.umich.edu#include "cpu/thread_context.hh" 485648Sgblack@eecs.umich.edu#include "dev/io_device.hh" 495651Sgblack@eecs.umich.edu#include "dev/x86/intdev.hh" 505647Sgblack@eecs.umich.edu#include "params/X86LocalApic.hh" 515647Sgblack@eecs.umich.edu#include "sim/eventq.hh" 525647Sgblack@eecs.umich.edu 535647Sgblack@eecs.umich.educlass ThreadContext; 545810Sgblack@eecs.umich.educlass BaseCPU; 554120Sgblack@eecs.umich.edu 565704Snate@binkert.orgnamespace X86ISA { 575086Sgblack@eecs.umich.edu 585651Sgblack@eecs.umich.educlass Interrupts : public BasicPioDevice, IntDev 595086Sgblack@eecs.umich.edu{ 605647Sgblack@eecs.umich.edu protected: 615654Sgblack@eecs.umich.edu // Storage for the APIC registers 625647Sgblack@eecs.umich.edu uint32_t regs[NUM_APIC_REGS]; 635654Sgblack@eecs.umich.edu 645691Sgblack@eecs.umich.edu BitUnion32(LVTEntry) 655691Sgblack@eecs.umich.edu Bitfield<7, 0> vector; 665691Sgblack@eecs.umich.edu Bitfield<10, 8> deliveryMode; 675691Sgblack@eecs.umich.edu Bitfield<12> status; 685691Sgblack@eecs.umich.edu Bitfield<13> polarity; 695691Sgblack@eecs.umich.edu Bitfield<14> remoteIRR; 705691Sgblack@eecs.umich.edu Bitfield<15> trigger; 715691Sgblack@eecs.umich.edu Bitfield<16> masked; 725691Sgblack@eecs.umich.edu Bitfield<17> periodic; 735691Sgblack@eecs.umich.edu EndBitUnion(LVTEntry) 745691Sgblack@eecs.umich.edu 755654Sgblack@eecs.umich.edu /* 765654Sgblack@eecs.umich.edu * Timing related stuff. 775654Sgblack@eecs.umich.edu */ 785648Sgblack@eecs.umich.edu Tick latency; 795648Sgblack@eecs.umich.edu Tick clock; 805647Sgblack@eecs.umich.edu 815647Sgblack@eecs.umich.edu class ApicTimerEvent : public Event 825647Sgblack@eecs.umich.edu { 835691Sgblack@eecs.umich.edu private: 845691Sgblack@eecs.umich.edu Interrupts *localApic; 855647Sgblack@eecs.umich.edu public: 865691Sgblack@eecs.umich.edu ApicTimerEvent(Interrupts *_localApic) : 875691Sgblack@eecs.umich.edu Event(), localApic(_localApic) 885647Sgblack@eecs.umich.edu {} 895647Sgblack@eecs.umich.edu 905647Sgblack@eecs.umich.edu void process() 915647Sgblack@eecs.umich.edu { 925691Sgblack@eecs.umich.edu assert(localApic); 935691Sgblack@eecs.umich.edu if (localApic->triggerTimerInterrupt()) { 945691Sgblack@eecs.umich.edu localApic->setReg(APIC_INITIAL_COUNT, 955691Sgblack@eecs.umich.edu localApic->readReg(APIC_INITIAL_COUNT)); 965691Sgblack@eecs.umich.edu } 975647Sgblack@eecs.umich.edu } 985647Sgblack@eecs.umich.edu }; 995647Sgblack@eecs.umich.edu 1005647Sgblack@eecs.umich.edu ApicTimerEvent apicTimerEvent; 1015647Sgblack@eecs.umich.edu 1025654Sgblack@eecs.umich.edu /* 1035655Sgblack@eecs.umich.edu * A set of variables to keep track of interrupts that don't go through 1045655Sgblack@eecs.umich.edu * the IRR. 1055655Sgblack@eecs.umich.edu */ 1065655Sgblack@eecs.umich.edu bool pendingSmi; 1075691Sgblack@eecs.umich.edu uint8_t smiVector; 1085655Sgblack@eecs.umich.edu bool pendingNmi; 1095691Sgblack@eecs.umich.edu uint8_t nmiVector; 1105655Sgblack@eecs.umich.edu bool pendingExtInt; 1115691Sgblack@eecs.umich.edu uint8_t extIntVector; 1125655Sgblack@eecs.umich.edu bool pendingInit; 1135691Sgblack@eecs.umich.edu uint8_t initVector; 1146050Sgblack@eecs.umich.edu bool pendingStartup; 1156050Sgblack@eecs.umich.edu uint8_t startupVector; 1166066Sgblack@eecs.umich.edu bool startedUp; 1175655Sgblack@eecs.umich.edu 1185655Sgblack@eecs.umich.edu // This is a quick check whether any of the above (except ExtInt) are set. 1195655Sgblack@eecs.umich.edu bool pendingUnmaskableInt; 1205655Sgblack@eecs.umich.edu 1216069Sgblack@eecs.umich.edu // A count of how many IPIs are in flight. 1226069Sgblack@eecs.umich.edu int pendingIPIs; 1236069Sgblack@eecs.umich.edu 1245655Sgblack@eecs.umich.edu /* 1255654Sgblack@eecs.umich.edu * IRR and ISR maintenance. 1265654Sgblack@eecs.umich.edu */ 1275654Sgblack@eecs.umich.edu uint8_t IRRV; 1285654Sgblack@eecs.umich.edu uint8_t ISRV; 1295654Sgblack@eecs.umich.edu 1305654Sgblack@eecs.umich.edu int 1315654Sgblack@eecs.umich.edu findRegArrayMSB(ApicRegIndex base) 1325654Sgblack@eecs.umich.edu { 1335654Sgblack@eecs.umich.edu int offset = 7; 1345654Sgblack@eecs.umich.edu do { 1355654Sgblack@eecs.umich.edu if (regs[base + offset] != 0) { 1365654Sgblack@eecs.umich.edu return offset * 32 + findMsbSet(regs[base + offset]); 1375654Sgblack@eecs.umich.edu } 1385654Sgblack@eecs.umich.edu } while (offset--); 1395654Sgblack@eecs.umich.edu return 0; 1405654Sgblack@eecs.umich.edu } 1415654Sgblack@eecs.umich.edu 1425654Sgblack@eecs.umich.edu void 1435654Sgblack@eecs.umich.edu updateIRRV() 1445654Sgblack@eecs.umich.edu { 1455654Sgblack@eecs.umich.edu IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE); 1465654Sgblack@eecs.umich.edu } 1475654Sgblack@eecs.umich.edu 1485654Sgblack@eecs.umich.edu void 1495654Sgblack@eecs.umich.edu updateISRV() 1505654Sgblack@eecs.umich.edu { 1515654Sgblack@eecs.umich.edu ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE); 1525654Sgblack@eecs.umich.edu } 1535654Sgblack@eecs.umich.edu 1545654Sgblack@eecs.umich.edu void 1555654Sgblack@eecs.umich.edu setRegArrayBit(ApicRegIndex base, uint8_t vector) 1565654Sgblack@eecs.umich.edu { 1576101Sgblack@eecs.umich.edu regs[base + (vector / 32)] |= (1 << (vector % 32)); 1585654Sgblack@eecs.umich.edu } 1595654Sgblack@eecs.umich.edu 1605654Sgblack@eecs.umich.edu void 1615654Sgblack@eecs.umich.edu clearRegArrayBit(ApicRegIndex base, uint8_t vector) 1625654Sgblack@eecs.umich.edu { 1636101Sgblack@eecs.umich.edu regs[base + (vector / 32)] &= ~(1 << (vector % 32)); 1645654Sgblack@eecs.umich.edu } 1655654Sgblack@eecs.umich.edu 1665654Sgblack@eecs.umich.edu bool 1675654Sgblack@eecs.umich.edu getRegArrayBit(ApicRegIndex base, uint8_t vector) 1685654Sgblack@eecs.umich.edu { 1696101Sgblack@eecs.umich.edu return bits(regs[base + (vector / 32)], vector % 5); 1705654Sgblack@eecs.umich.edu } 1715654Sgblack@eecs.umich.edu 1725691Sgblack@eecs.umich.edu void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level); 1735691Sgblack@eecs.umich.edu 1745810Sgblack@eecs.umich.edu BaseCPU *cpu; 1755810Sgblack@eecs.umich.edu 1766136Sgblack@eecs.umich.edu int initialApicId; 1776136Sgblack@eecs.umich.edu 1785086Sgblack@eecs.umich.edu public: 1795654Sgblack@eecs.umich.edu /* 1805654Sgblack@eecs.umich.edu * Params stuff. 1815654Sgblack@eecs.umich.edu */ 1825647Sgblack@eecs.umich.edu typedef X86LocalApicParams Params; 1835647Sgblack@eecs.umich.edu 1846041Sgblack@eecs.umich.edu void setCPU(BaseCPU * newCPU); 1855810Sgblack@eecs.umich.edu 1865810Sgblack@eecs.umich.edu void 1875704Snate@binkert.org setClock(Tick newClock) 1885648Sgblack@eecs.umich.edu { 1895648Sgblack@eecs.umich.edu clock = newClock; 1905648Sgblack@eecs.umich.edu } 1915648Sgblack@eecs.umich.edu 1925647Sgblack@eecs.umich.edu const Params * 1935647Sgblack@eecs.umich.edu params() const 1945086Sgblack@eecs.umich.edu { 1955647Sgblack@eecs.umich.edu return dynamic_cast<const Params *>(_params); 1965647Sgblack@eecs.umich.edu } 1975647Sgblack@eecs.umich.edu 1985654Sgblack@eecs.umich.edu /* 1996137Sgblack@eecs.umich.edu * Initialize this object by registering it with the IO APIC. 2006137Sgblack@eecs.umich.edu */ 2016137Sgblack@eecs.umich.edu void init(); 2026137Sgblack@eecs.umich.edu 2036137Sgblack@eecs.umich.edu /* 2045654Sgblack@eecs.umich.edu * Functions to interact with the interrupt port from IntDev. 2055654Sgblack@eecs.umich.edu */ 2065648Sgblack@eecs.umich.edu Tick read(PacketPtr pkt); 2075648Sgblack@eecs.umich.edu Tick write(PacketPtr pkt); 2085651Sgblack@eecs.umich.edu Tick recvMessage(PacketPtr pkt); 2096064Sgblack@eecs.umich.edu Tick recvResponse(PacketPtr pkt); 2105647Sgblack@eecs.umich.edu 2115691Sgblack@eecs.umich.edu bool 2125691Sgblack@eecs.umich.edu triggerTimerInterrupt() 2135691Sgblack@eecs.umich.edu { 2145691Sgblack@eecs.umich.edu LVTEntry entry = regs[APIC_LVT_TIMER]; 2155691Sgblack@eecs.umich.edu if (!entry.masked) 2165691Sgblack@eecs.umich.edu requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger); 2175691Sgblack@eecs.umich.edu return entry.periodic; 2185691Sgblack@eecs.umich.edu } 2195691Sgblack@eecs.umich.edu 2206041Sgblack@eecs.umich.edu void addressRanges(AddrRangeList &range_list); 2216041Sgblack@eecs.umich.edu void getIntAddrRange(AddrRangeList &range_list); 2225651Sgblack@eecs.umich.edu 2235654Sgblack@eecs.umich.edu Port *getPort(const std::string &if_name, int idx = -1) 2245654Sgblack@eecs.umich.edu { 2255654Sgblack@eecs.umich.edu if (if_name == "int_port") 2265654Sgblack@eecs.umich.edu return intPort; 2275654Sgblack@eecs.umich.edu return BasicPioDevice::getPort(if_name, idx); 2285654Sgblack@eecs.umich.edu } 2295654Sgblack@eecs.umich.edu 2305654Sgblack@eecs.umich.edu /* 2315654Sgblack@eecs.umich.edu * Functions to access and manipulate the APIC's registers. 2325654Sgblack@eecs.umich.edu */ 2335654Sgblack@eecs.umich.edu 2345648Sgblack@eecs.umich.edu uint32_t readReg(ApicRegIndex miscReg); 2355648Sgblack@eecs.umich.edu void setReg(ApicRegIndex reg, uint32_t val); 2365704Snate@binkert.org void 2375704Snate@binkert.org setRegNoEffect(ApicRegIndex reg, uint32_t val) 2385647Sgblack@eecs.umich.edu { 2395648Sgblack@eecs.umich.edu regs[reg] = val; 2405648Sgblack@eecs.umich.edu } 2415648Sgblack@eecs.umich.edu 2425654Sgblack@eecs.umich.edu /* 2435654Sgblack@eecs.umich.edu * Constructor. 2445654Sgblack@eecs.umich.edu */ 2455654Sgblack@eecs.umich.edu 2466041Sgblack@eecs.umich.edu Interrupts(Params * p); 2475086Sgblack@eecs.umich.edu 2485654Sgblack@eecs.umich.edu /* 2495654Sgblack@eecs.umich.edu * Functions for retrieving interrupts for the CPU to handle. 2505654Sgblack@eecs.umich.edu */ 2515651Sgblack@eecs.umich.edu 2525704Snate@binkert.org bool checkInterrupts(ThreadContext *tc) const; 2535704Snate@binkert.org Fault getInterrupt(ThreadContext *tc); 2545704Snate@binkert.org void updateIntrInfo(ThreadContext *tc); 2555086Sgblack@eecs.umich.edu 2565654Sgblack@eecs.umich.edu /* 2575654Sgblack@eecs.umich.edu * Serialization. 2585654Sgblack@eecs.umich.edu */ 2595086Sgblack@eecs.umich.edu 2605704Snate@binkert.org void 2615704Snate@binkert.org serialize(std::ostream &os) 2625086Sgblack@eecs.umich.edu { 2635133Sgblack@eecs.umich.edu panic("Interrupts::serialize unimplemented!\n"); 2645086Sgblack@eecs.umich.edu } 2655086Sgblack@eecs.umich.edu 2665704Snate@binkert.org void 2675704Snate@binkert.org unserialize(Checkpoint *cp, const std::string §ion) 2685086Sgblack@eecs.umich.edu { 2695133Sgblack@eecs.umich.edu panic("Interrupts::unserialize unimplemented!\n"); 2705086Sgblack@eecs.umich.edu } 2715654Sgblack@eecs.umich.edu 2725654Sgblack@eecs.umich.edu /* 2735654Sgblack@eecs.umich.edu * Old functions needed for compatability but which will be phased out 2745654Sgblack@eecs.umich.edu * eventually. 2755654Sgblack@eecs.umich.edu */ 2765704Snate@binkert.org void 2775704Snate@binkert.org post(int int_num, int index) 2785654Sgblack@eecs.umich.edu { 2795654Sgblack@eecs.umich.edu panic("Interrupts::post unimplemented!\n"); 2805654Sgblack@eecs.umich.edu } 2815654Sgblack@eecs.umich.edu 2825704Snate@binkert.org void 2835704Snate@binkert.org clear(int int_num, int index) 2845654Sgblack@eecs.umich.edu { 2855654Sgblack@eecs.umich.edu panic("Interrupts::clear unimplemented!\n"); 2865654Sgblack@eecs.umich.edu } 2875654Sgblack@eecs.umich.edu 2885704Snate@binkert.org void 2895704Snate@binkert.org clearAll() 2905654Sgblack@eecs.umich.edu { 2915704Snate@binkert.org panic("Interrupts::clearAll unimplemented!\n"); 2925654Sgblack@eecs.umich.edu } 2935086Sgblack@eecs.umich.edu}; 2945086Sgblack@eecs.umich.edu 2955704Snate@binkert.org} // namespace X86ISA 2964120Sgblack@eecs.umich.edu 2974120Sgblack@eecs.umich.edu#endif // __ARCH_X86_INTERRUPTS_HH__ 298