interrupts.hh revision 6066
19883Sandreas@sandberg.pp.se/* 29883Sandreas@sandberg.pp.se * Copyright (c) 2007 The Hewlett-Packard Development Company 39883Sandreas@sandberg.pp.se * All rights reserved. 49883Sandreas@sandberg.pp.se * 59883Sandreas@sandberg.pp.se * Redistribution and use of this software in source and binary forms, 69883Sandreas@sandberg.pp.se * with or without modification, are permitted provided that the 79883Sandreas@sandberg.pp.se * following conditions are met: 89883Sandreas@sandberg.pp.se * 99883Sandreas@sandberg.pp.se * The software must be used only for Non-Commercial Use which means any 109883Sandreas@sandberg.pp.se * use which is NOT directed to receiving any direct monetary 119883Sandreas@sandberg.pp.se * compensation for, or commercial advantage from such use. Illustrative 129883Sandreas@sandberg.pp.se * examples of non-commercial use are academic research, personal study, 139883Sandreas@sandberg.pp.se * teaching, education and corporate research & development. 149883Sandreas@sandberg.pp.se * Illustrative examples of commercial use are distributing products for 159883Sandreas@sandberg.pp.se * commercial advantage and providing services using the software for 169883Sandreas@sandberg.pp.se * commercial advantage. 179883Sandreas@sandberg.pp.se * 189883Sandreas@sandberg.pp.se * If you wish to use this software or functionality therein that may be 199883Sandreas@sandberg.pp.se * covered by patents for commercial use, please contact: 209883Sandreas@sandberg.pp.se * Director of Intellectual Property Licensing 219883Sandreas@sandberg.pp.se * Office of Strategy and Technology 229883Sandreas@sandberg.pp.se * Hewlett-Packard Company 239883Sandreas@sandberg.pp.se * 1501 Page Mill Road 249883Sandreas@sandberg.pp.se * Palo Alto, California 94304 259883Sandreas@sandberg.pp.se * 269883Sandreas@sandberg.pp.se * Redistributions of source code must retain the above copyright notice, 279883Sandreas@sandberg.pp.se * this list of conditions and the following disclaimer. Redistributions 289883Sandreas@sandberg.pp.se * in binary form must reproduce the above copyright notice, this list of 299883Sandreas@sandberg.pp.se * conditions and the following disclaimer in the documentation and/or 309883Sandreas@sandberg.pp.se * other materials provided with the distribution. Neither the name of 3111793Sbrandon.potter@amd.com * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its 3211793Sbrandon.potter@amd.com * contributors may be used to endorse or promote products derived from 339883Sandreas@sandberg.pp.se * this software without specific prior written permission. No right of 349883Sandreas@sandberg.pp.se * sublicense is granted herewith. Derivatives of the software and 359883Sandreas@sandberg.pp.se * output created using the software may be prepared, but only for 369883Sandreas@sandberg.pp.se * Non-Commercial Uses. Derivatives of the software may be shared with 379883Sandreas@sandberg.pp.se * others provided: (i) the others agree to abide by the list of 389883Sandreas@sandberg.pp.se * conditions herein which includes the Non-Commercial Use restrictions; 3911793Sbrandon.potter@amd.com * and (ii) such Derivatives of the software include the above copyright 4011793Sbrandon.potter@amd.com * notice to acknowledge the contribution from this software where 419883Sandreas@sandberg.pp.se * applicable, this list of conditions and the disclaimer below. 429883Sandreas@sandberg.pp.se * 439883Sandreas@sandberg.pp.se * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 449883Sandreas@sandberg.pp.se * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 459883Sandreas@sandberg.pp.se * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 469883Sandreas@sandberg.pp.se * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 479883Sandreas@sandberg.pp.se * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 489883Sandreas@sandberg.pp.se * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 499883Sandreas@sandberg.pp.se * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 509883Sandreas@sandberg.pp.se * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 519883Sandreas@sandberg.pp.se * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 529883Sandreas@sandberg.pp.se * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 539883Sandreas@sandberg.pp.se * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 549883Sandreas@sandberg.pp.se * 559883Sandreas@sandberg.pp.se * Authors: Gabe Black 569883Sandreas@sandberg.pp.se */ 579886Sandreas@sandberg.pp.se 589886Sandreas@sandberg.pp.se#ifndef __ARCH_X86_INTERRUPTS_HH__ 599886Sandreas@sandberg.pp.se#define __ARCH_X86_INTERRUPTS_HH__ 609886Sandreas@sandberg.pp.se 619886Sandreas@sandberg.pp.se#include "arch/x86/apicregs.hh" 629886Sandreas@sandberg.pp.se#include "arch/x86/faults.hh" 639886Sandreas@sandberg.pp.se#include "arch/x86/intmessage.hh" 649886Sandreas@sandberg.pp.se#include "base/bitfield.hh" 659886Sandreas@sandberg.pp.se#include "cpu/thread_context.hh" 669886Sandreas@sandberg.pp.se#include "dev/io_device.hh" 679886Sandreas@sandberg.pp.se#include "dev/x86/intdev.hh" 689886Sandreas@sandberg.pp.se#include "params/X86LocalApic.hh" 699886Sandreas@sandberg.pp.se#include "sim/eventq.hh" 709886Sandreas@sandberg.pp.se 719890Sandreas@sandberg.pp.seclass ThreadContext; 729890Sandreas@sandberg.pp.seclass BaseCPU; 739890Sandreas@sandberg.pp.se 749890Sandreas@sandberg.pp.senamespace X86ISA { 759890Sandreas@sandberg.pp.se 769890Sandreas@sandberg.pp.seclass Interrupts : public BasicPioDevice, IntDev 779890Sandreas@sandberg.pp.se{ 789890Sandreas@sandberg.pp.se protected: 799890Sandreas@sandberg.pp.se // Storage for the APIC registers 809890Sandreas@sandberg.pp.se uint32_t regs[NUM_APIC_REGS]; 819890Sandreas@sandberg.pp.se 829890Sandreas@sandberg.pp.se BitUnion32(LVTEntry) 839890Sandreas@sandberg.pp.se Bitfield<7, 0> vector; 849890Sandreas@sandberg.pp.se Bitfield<10, 8> deliveryMode; 859890Sandreas@sandberg.pp.se Bitfield<12> status; 869890Sandreas@sandberg.pp.se Bitfield<13> polarity; 879890Sandreas@sandberg.pp.se Bitfield<14> remoteIRR; 889890Sandreas@sandberg.pp.se Bitfield<15> trigger; 899890Sandreas@sandberg.pp.se Bitfield<16> masked; 909890Sandreas@sandberg.pp.se Bitfield<17> periodic; 919890Sandreas@sandberg.pp.se EndBitUnion(LVTEntry) 929890Sandreas@sandberg.pp.se 939890Sandreas@sandberg.pp.se /* 949890Sandreas@sandberg.pp.se * Timing related stuff. 959890Sandreas@sandberg.pp.se */ 969890Sandreas@sandberg.pp.se Tick latency; 979890Sandreas@sandberg.pp.se Tick clock; 989890Sandreas@sandberg.pp.se 999890Sandreas@sandberg.pp.se class ApicTimerEvent : public Event 1009890Sandreas@sandberg.pp.se { 1019890Sandreas@sandberg.pp.se private: 1029890Sandreas@sandberg.pp.se Interrupts *localApic; 1039886Sandreas@sandberg.pp.se public: 1049883Sandreas@sandberg.pp.se ApicTimerEvent(Interrupts *_localApic) : 1059883Sandreas@sandberg.pp.se Event(), localApic(_localApic) 1069883Sandreas@sandberg.pp.se {} 1079883Sandreas@sandberg.pp.se 1089883Sandreas@sandberg.pp.se void process() 1099883Sandreas@sandberg.pp.se { 1109883Sandreas@sandberg.pp.se assert(localApic); 1119883Sandreas@sandberg.pp.se if (localApic->triggerTimerInterrupt()) { 1129883Sandreas@sandberg.pp.se localApic->setReg(APIC_INITIAL_COUNT, 1139883Sandreas@sandberg.pp.se localApic->readReg(APIC_INITIAL_COUNT)); 1149883Sandreas@sandberg.pp.se } 1159883Sandreas@sandberg.pp.se } 1169883Sandreas@sandberg.pp.se }; 1179883Sandreas@sandberg.pp.se 1189883Sandreas@sandberg.pp.se ApicTimerEvent apicTimerEvent; 1199883Sandreas@sandberg.pp.se 1209883Sandreas@sandberg.pp.se /* 1219883Sandreas@sandberg.pp.se * A set of variables to keep track of interrupts that don't go through 12211321Ssteve.reinhardt@amd.com * the IRR. 1239883Sandreas@sandberg.pp.se */ 1249883Sandreas@sandberg.pp.se bool pendingSmi; 1259883Sandreas@sandberg.pp.se uint8_t smiVector; 1269883Sandreas@sandberg.pp.se bool pendingNmi; 1279883Sandreas@sandberg.pp.se uint8_t nmiVector; 1289883Sandreas@sandberg.pp.se bool pendingExtInt; 1299883Sandreas@sandberg.pp.se uint8_t extIntVector; 1309883Sandreas@sandberg.pp.se bool pendingInit; 1319883Sandreas@sandberg.pp.se uint8_t initVector; 1329883Sandreas@sandberg.pp.se bool pendingStartup; 13311321Ssteve.reinhardt@amd.com uint8_t startupVector; 1349883Sandreas@sandberg.pp.se bool startedUp; 1359883Sandreas@sandberg.pp.se 1369883Sandreas@sandberg.pp.se // This is a quick check whether any of the above (except ExtInt) are set. 1379883Sandreas@sandberg.pp.se bool pendingUnmaskableInt; 1389883Sandreas@sandberg.pp.se 1399883Sandreas@sandberg.pp.se /* 1409883Sandreas@sandberg.pp.se * IRR and ISR maintenance. 1419883Sandreas@sandberg.pp.se */ 1429883Sandreas@sandberg.pp.se uint8_t IRRV; 14311321Ssteve.reinhardt@amd.com uint8_t ISRV; 1449883Sandreas@sandberg.pp.se 1459883Sandreas@sandberg.pp.se int 1469883Sandreas@sandberg.pp.se findRegArrayMSB(ApicRegIndex base) 1479883Sandreas@sandberg.pp.se { 1489883Sandreas@sandberg.pp.se int offset = 7; 1499883Sandreas@sandberg.pp.se do { 1509883Sandreas@sandberg.pp.se if (regs[base + offset] != 0) { 1519883Sandreas@sandberg.pp.se return offset * 32 + findMsbSet(regs[base + offset]); 1529883Sandreas@sandberg.pp.se } 1539883Sandreas@sandberg.pp.se } while (offset--); 1549883Sandreas@sandberg.pp.se return 0; 15511321Ssteve.reinhardt@amd.com } 1569883Sandreas@sandberg.pp.se 1579883Sandreas@sandberg.pp.se void 1589883Sandreas@sandberg.pp.se updateIRRV() 1599883Sandreas@sandberg.pp.se { 1609883Sandreas@sandberg.pp.se IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE); 16111321Ssteve.reinhardt@amd.com } 1629883Sandreas@sandberg.pp.se 1639883Sandreas@sandberg.pp.se void 1649883Sandreas@sandberg.pp.se updateISRV() 1659883Sandreas@sandberg.pp.se { 1669883Sandreas@sandberg.pp.se ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE); 1679883Sandreas@sandberg.pp.se } 1689883Sandreas@sandberg.pp.se 1699883Sandreas@sandberg.pp.se void 1709883Sandreas@sandberg.pp.se setRegArrayBit(ApicRegIndex base, uint8_t vector) 1719883Sandreas@sandberg.pp.se { 1729883Sandreas@sandberg.pp.se regs[base + (vector % 32)] |= (1 << (vector >> 5)); 1739883Sandreas@sandberg.pp.se } 1749883Sandreas@sandberg.pp.se 1759883Sandreas@sandberg.pp.se void 1769883Sandreas@sandberg.pp.se clearRegArrayBit(ApicRegIndex base, uint8_t vector) 1779883Sandreas@sandberg.pp.se { 1789883Sandreas@sandberg.pp.se regs[base + (vector % 32)] &= ~(1 << (vector >> 5)); 1799883Sandreas@sandberg.pp.se } 1809883Sandreas@sandberg.pp.se 1819883Sandreas@sandberg.pp.se bool 1829883Sandreas@sandberg.pp.se getRegArrayBit(ApicRegIndex base, uint8_t vector) 1839883Sandreas@sandberg.pp.se { 1849883Sandreas@sandberg.pp.se return bits(regs[base + (vector % 32)], vector >> 5); 1859883Sandreas@sandberg.pp.se } 1869883Sandreas@sandberg.pp.se 1879883Sandreas@sandberg.pp.se void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level); 1889883Sandreas@sandberg.pp.se 1899883Sandreas@sandberg.pp.se BaseCPU *cpu; 1909883Sandreas@sandberg.pp.se 1919883Sandreas@sandberg.pp.se public: 1929883Sandreas@sandberg.pp.se /* 1939883Sandreas@sandberg.pp.se * Params stuff. 1949883Sandreas@sandberg.pp.se */ 1959883Sandreas@sandberg.pp.se typedef X86LocalApicParams Params; 1969883Sandreas@sandberg.pp.se 1979883Sandreas@sandberg.pp.se void setCPU(BaseCPU * newCPU); 1989883Sandreas@sandberg.pp.se 1999883Sandreas@sandberg.pp.se void 2009883Sandreas@sandberg.pp.se setClock(Tick newClock) 2019883Sandreas@sandberg.pp.se { 2029883Sandreas@sandberg.pp.se clock = newClock; 2039883Sandreas@sandberg.pp.se } 2049883Sandreas@sandberg.pp.se 2059883Sandreas@sandberg.pp.se const Params * 2069883Sandreas@sandberg.pp.se params() const 2079883Sandreas@sandberg.pp.se { 2089883Sandreas@sandberg.pp.se return dynamic_cast<const Params *>(_params); 2099883Sandreas@sandberg.pp.se } 2109883Sandreas@sandberg.pp.se 2119883Sandreas@sandberg.pp.se /* 2129883Sandreas@sandberg.pp.se * Functions to interact with the interrupt port from IntDev. 2139883Sandreas@sandberg.pp.se */ 2149883Sandreas@sandberg.pp.se Tick read(PacketPtr pkt); 2159883Sandreas@sandberg.pp.se Tick write(PacketPtr pkt); 2169883Sandreas@sandberg.pp.se Tick recvMessage(PacketPtr pkt); 2179883Sandreas@sandberg.pp.se Tick recvResponse(PacketPtr pkt); 2189883Sandreas@sandberg.pp.se 2199883Sandreas@sandberg.pp.se bool 2209883Sandreas@sandberg.pp.se triggerTimerInterrupt() 2219883Sandreas@sandberg.pp.se { 2229883Sandreas@sandberg.pp.se LVTEntry entry = regs[APIC_LVT_TIMER]; 2239883Sandreas@sandberg.pp.se if (!entry.masked) 2249883Sandreas@sandberg.pp.se requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger); 2259883Sandreas@sandberg.pp.se return entry.periodic; 2269883Sandreas@sandberg.pp.se } 2279883Sandreas@sandberg.pp.se 2289883Sandreas@sandberg.pp.se void addressRanges(AddrRangeList &range_list); 2299883Sandreas@sandberg.pp.se void getIntAddrRange(AddrRangeList &range_list); 2309883Sandreas@sandberg.pp.se 2319883Sandreas@sandberg.pp.se Port *getPort(const std::string &if_name, int idx = -1) 2329883Sandreas@sandberg.pp.se { 2339883Sandreas@sandberg.pp.se if (if_name == "int_port") 2349883Sandreas@sandberg.pp.se return intPort; 2359883Sandreas@sandberg.pp.se return BasicPioDevice::getPort(if_name, idx); 2369883Sandreas@sandberg.pp.se } 2379883Sandreas@sandberg.pp.se 2389883Sandreas@sandberg.pp.se /* 2399883Sandreas@sandberg.pp.se * Functions to access and manipulate the APIC's registers. 2409883Sandreas@sandberg.pp.se */ 2419883Sandreas@sandberg.pp.se 2429883Sandreas@sandberg.pp.se uint32_t readReg(ApicRegIndex miscReg); 2439883Sandreas@sandberg.pp.se void setReg(ApicRegIndex reg, uint32_t val); 2449890Sandreas@sandberg.pp.se void 2459883Sandreas@sandberg.pp.se setRegNoEffect(ApicRegIndex reg, uint32_t val) 2469890Sandreas@sandberg.pp.se { 2479890Sandreas@sandberg.pp.se regs[reg] = val; 2489890Sandreas@sandberg.pp.se } 2499890Sandreas@sandberg.pp.se 2509890Sandreas@sandberg.pp.se /* 2519890Sandreas@sandberg.pp.se * Constructor. 2529890Sandreas@sandberg.pp.se */ 2539890Sandreas@sandberg.pp.se 2549890Sandreas@sandberg.pp.se Interrupts(Params * p); 2559890Sandreas@sandberg.pp.se 2569890Sandreas@sandberg.pp.se /* 2579890Sandreas@sandberg.pp.se * Functions for retrieving interrupts for the CPU to handle. 2589890Sandreas@sandberg.pp.se */ 2599890Sandreas@sandberg.pp.se 2609890Sandreas@sandberg.pp.se bool checkInterrupts(ThreadContext *tc) const; 2619890Sandreas@sandberg.pp.se Fault getInterrupt(ThreadContext *tc); 2629890Sandreas@sandberg.pp.se void updateIntrInfo(ThreadContext *tc); 2639883Sandreas@sandberg.pp.se 2649890Sandreas@sandberg.pp.se /* 2659890Sandreas@sandberg.pp.se * Serialization. 2669890Sandreas@sandberg.pp.se */ 2679890Sandreas@sandberg.pp.se 2689890Sandreas@sandberg.pp.se void 2699890Sandreas@sandberg.pp.se serialize(std::ostream &os) 2709890Sandreas@sandberg.pp.se { 2719890Sandreas@sandberg.pp.se panic("Interrupts::serialize unimplemented!\n"); 2729890Sandreas@sandberg.pp.se } 2739890Sandreas@sandberg.pp.se 2749890Sandreas@sandberg.pp.se void 2759890Sandreas@sandberg.pp.se unserialize(Checkpoint *cp, const std::string §ion) 2769890Sandreas@sandberg.pp.se { 2779890Sandreas@sandberg.pp.se panic("Interrupts::unserialize unimplemented!\n"); 2789890Sandreas@sandberg.pp.se } 2799890Sandreas@sandberg.pp.se 2809890Sandreas@sandberg.pp.se /* 2819890Sandreas@sandberg.pp.se * Old functions needed for compatability but which will be phased out 2829890Sandreas@sandberg.pp.se * eventually. 2839890Sandreas@sandberg.pp.se */ 2849890Sandreas@sandberg.pp.se void 2859883Sandreas@sandberg.pp.se post(int int_num, int index) 2869883Sandreas@sandberg.pp.se { 2879890Sandreas@sandberg.pp.se panic("Interrupts::post unimplemented!\n"); 2889883Sandreas@sandberg.pp.se } 2899883Sandreas@sandberg.pp.se 2909883Sandreas@sandberg.pp.se void 2919890Sandreas@sandberg.pp.se clear(int int_num, int index) 2929890Sandreas@sandberg.pp.se { 2939890Sandreas@sandberg.pp.se panic("Interrupts::clear unimplemented!\n"); 2949883Sandreas@sandberg.pp.se } 2959890Sandreas@sandberg.pp.se 2969883Sandreas@sandberg.pp.se void 2979890Sandreas@sandberg.pp.se clearAll() 2989890Sandreas@sandberg.pp.se { 2999883Sandreas@sandberg.pp.se panic("Interrupts::clearAll unimplemented!\n"); 3009883Sandreas@sandberg.pp.se } 3019883Sandreas@sandberg.pp.se}; 3029883Sandreas@sandberg.pp.se 3039883Sandreas@sandberg.pp.se} // namespace X86ISA 3049883Sandreas@sandberg.pp.se 3059883Sandreas@sandberg.pp.se#endif // __ARCH_X86_INTERRUPTS_HH__ 3069883Sandreas@sandberg.pp.se