i82094aa.cc revision 9807:63d7362bbdf2
14825Sgblack@eecs.umich.edu/* 24825Sgblack@eecs.umich.edu * Copyright (c) 2008 The Regents of The University of Michigan 34825Sgblack@eecs.umich.edu * All rights reserved. 44825Sgblack@eecs.umich.edu * 54825Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 64825Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 74825Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 84825Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 94825Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 104825Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 114825Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 124825Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 134825Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 144825Sgblack@eecs.umich.edu * this software without specific prior written permission. 154825Sgblack@eecs.umich.edu * 164825Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174825Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184825Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194825Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204825Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214825Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224825Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234825Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244825Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254825Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264825Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274825Sgblack@eecs.umich.edu * 284825Sgblack@eecs.umich.edu * Authors: Gabe Black 294825Sgblack@eecs.umich.edu */ 304825Sgblack@eecs.umich.edu 314825Sgblack@eecs.umich.edu#include "arch/x86/interrupts.hh" 324825Sgblack@eecs.umich.edu#include "arch/x86/intmessage.hh" 334825Sgblack@eecs.umich.edu#include "cpu/base.hh" 344825Sgblack@eecs.umich.edu#include "debug/I82094AA.hh" 354825Sgblack@eecs.umich.edu#include "dev/x86/i82094aa.hh" 364825Sgblack@eecs.umich.edu#include "dev/x86/i8259.hh" 374825Sgblack@eecs.umich.edu#include "mem/packet.hh" 384825Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 394825Sgblack@eecs.umich.edu#include "sim/system.hh" 404825Sgblack@eecs.umich.edu 414825Sgblack@eecs.umich.eduX86ISA::I82094AA::I82094AA(Params *p) 424825Sgblack@eecs.umich.edu : BasicPioDevice(p), IntDevice(this, p->int_latency), 434825Sgblack@eecs.umich.edu extIntPic(p->external_int_pic), lowestPriorityOffset(0) 444825Sgblack@eecs.umich.edu{ 454825Sgblack@eecs.umich.edu // This assumes there's only one I/O APIC in the system and since the apic 464825Sgblack@eecs.umich.edu // id is stored in a 8-bit field with 0xff meaning broadcast, the id must 474825Sgblack@eecs.umich.edu // be less than 0xff 484825Sgblack@eecs.umich.edu 494825Sgblack@eecs.umich.edu assert(p->apic_id < 0xff); 504825Sgblack@eecs.umich.edu initialApicId = id = p->apic_id; 514825Sgblack@eecs.umich.edu arbId = id; 524825Sgblack@eecs.umich.edu regSel = 0; 534825Sgblack@eecs.umich.edu RedirTableEntry entry = 0; 544825Sgblack@eecs.umich.edu entry.mask = 1; 554825Sgblack@eecs.umich.edu for (int i = 0; i < TableSize; i++) { 565162Sgblack@eecs.umich.edu redirTable[i] = entry; 575162Sgblack@eecs.umich.edu pinStates[i] = false; 585162Sgblack@eecs.umich.edu } 595162Sgblack@eecs.umich.edu 605162Sgblack@eecs.umich.edu pioSize = 20; 615162Sgblack@eecs.umich.edu} 625162Sgblack@eecs.umich.edu 635162Sgblack@eecs.umich.eduvoid 645162Sgblack@eecs.umich.eduX86ISA::I82094AA::init() 655162Sgblack@eecs.umich.edu{ 665162Sgblack@eecs.umich.edu // The io apic must register its address ranges on both its pio port 675162Sgblack@eecs.umich.edu // via the piodevice init() function and its int port that it inherited 684825Sgblack@eecs.umich.edu // from IntDevice. Note IntDevice is not a SimObject itself. 695162Sgblack@eecs.umich.edu 705162Sgblack@eecs.umich.edu BasicPioDevice::init(); 715162Sgblack@eecs.umich.edu IntDevice::init(); 725162Sgblack@eecs.umich.edu} 735162Sgblack@eecs.umich.edu 744825Sgblack@eecs.umich.eduBaseMasterPort & 754825Sgblack@eecs.umich.eduX86ISA::I82094AA::getMasterPort(const std::string &if_name, PortID idx) 765162Sgblack@eecs.umich.edu{ 775162Sgblack@eecs.umich.edu if (if_name == "int_master") 785162Sgblack@eecs.umich.edu return intMasterPort; 795162Sgblack@eecs.umich.edu return BasicPioDevice::getMasterPort(if_name, idx); 805162Sgblack@eecs.umich.edu} 815162Sgblack@eecs.umich.edu 825162Sgblack@eecs.umich.eduAddrRangeList 835162Sgblack@eecs.umich.eduX86ISA::I82094AA::getIntAddrRange() const 845162Sgblack@eecs.umich.edu{ 855162Sgblack@eecs.umich.edu AddrRangeList ranges; 865162Sgblack@eecs.umich.edu ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0), 875162Sgblack@eecs.umich.edu x86InterruptAddress(initialApicId, 0) + 885162Sgblack@eecs.umich.edu PhysAddrAPICRangeSize)); 895162Sgblack@eecs.umich.edu return ranges; 905162Sgblack@eecs.umich.edu} 915162Sgblack@eecs.umich.edu 925162Sgblack@eecs.umich.eduTick 935162Sgblack@eecs.umich.eduX86ISA::I82094AA::read(PacketPtr pkt) 945162Sgblack@eecs.umich.edu{ 955162Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 965162Sgblack@eecs.umich.edu Addr offset = pkt->getAddr() - pioAddr; 975162Sgblack@eecs.umich.edu switch(offset) { 985162Sgblack@eecs.umich.edu case 0: 995162Sgblack@eecs.umich.edu pkt->set<uint32_t>(regSel); 1005162Sgblack@eecs.umich.edu break; 1015162Sgblack@eecs.umich.edu case 16: 1025162Sgblack@eecs.umich.edu pkt->set<uint32_t>(readReg(regSel)); 1035162Sgblack@eecs.umich.edu break; 1045162Sgblack@eecs.umich.edu default: 1055162Sgblack@eecs.umich.edu panic("Illegal read from I/O APIC.\n"); 1065162Sgblack@eecs.umich.edu } 1075162Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1085162Sgblack@eecs.umich.edu return pioDelay; 1095162Sgblack@eecs.umich.edu} 1105162Sgblack@eecs.umich.edu 1115162Sgblack@eecs.umich.eduTick 1125162Sgblack@eecs.umich.eduX86ISA::I82094AA::write(PacketPtr pkt) 1135162Sgblack@eecs.umich.edu{ 1145162Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 1155162Sgblack@eecs.umich.edu Addr offset = pkt->getAddr() - pioAddr; 1165162Sgblack@eecs.umich.edu switch(offset) { 1175162Sgblack@eecs.umich.edu case 0: 1185162Sgblack@eecs.umich.edu regSel = pkt->get<uint32_t>(); 1195162Sgblack@eecs.umich.edu break; 1205162Sgblack@eecs.umich.edu case 16: 1215162Sgblack@eecs.umich.edu writeReg(regSel, pkt->get<uint32_t>()); 1225162Sgblack@eecs.umich.edu break; 1235162Sgblack@eecs.umich.edu default: 1245162Sgblack@eecs.umich.edu panic("Illegal write to I/O APIC.\n"); 1255162Sgblack@eecs.umich.edu } 1265162Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1275162Sgblack@eecs.umich.edu return pioDelay; 1285162Sgblack@eecs.umich.edu} 1295162Sgblack@eecs.umich.edu 1305162Sgblack@eecs.umich.eduvoid 1315162Sgblack@eecs.umich.eduX86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value) 1325162Sgblack@eecs.umich.edu{ 1335162Sgblack@eecs.umich.edu if (offset == 0x0) { 1345162Sgblack@eecs.umich.edu id = bits(value, 31, 24); 1354825Sgblack@eecs.umich.edu } else if (offset == 0x1) { 1365162Sgblack@eecs.umich.edu // The IOAPICVER register is read only. 1375162Sgblack@eecs.umich.edu } else if (offset == 0x2) { 1385162Sgblack@eecs.umich.edu arbId = bits(value, 31, 24); 1395162Sgblack@eecs.umich.edu } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 1405162Sgblack@eecs.umich.edu int index = (offset - 0x10) / 2; 1415162Sgblack@eecs.umich.edu if (offset % 2) { 1425162Sgblack@eecs.umich.edu redirTable[index].topDW = value; 1435162Sgblack@eecs.umich.edu redirTable[index].topReserved = 0; 1445162Sgblack@eecs.umich.edu } else { 1455162Sgblack@eecs.umich.edu redirTable[index].bottomDW = value; 1465162Sgblack@eecs.umich.edu redirTable[index].bottomReserved = 0; 1475162Sgblack@eecs.umich.edu } 1485162Sgblack@eecs.umich.edu } else { 1495162Sgblack@eecs.umich.edu warn("Access to undefined I/O APIC register %#x.\n", offset); 1505162Sgblack@eecs.umich.edu } 1515162Sgblack@eecs.umich.edu DPRINTF(I82094AA, 1525162Sgblack@eecs.umich.edu "Wrote %#x to I/O APIC register %#x .\n", value, offset); 1535162Sgblack@eecs.umich.edu} 1545162Sgblack@eecs.umich.edu 1555162Sgblack@eecs.umich.eduuint32_t 1565162Sgblack@eecs.umich.eduX86ISA::I82094AA::readReg(uint8_t offset) 1575162Sgblack@eecs.umich.edu{ 1585162Sgblack@eecs.umich.edu uint32_t result = 0; 1595162Sgblack@eecs.umich.edu if (offset == 0x0) { 1605162Sgblack@eecs.umich.edu result = id << 24; 1615162Sgblack@eecs.umich.edu } else if (offset == 0x1) { 1625162Sgblack@eecs.umich.edu result = ((TableSize - 1) << 16) | APICVersion; 1635162Sgblack@eecs.umich.edu } else if (offset == 0x2) { 1645162Sgblack@eecs.umich.edu result = arbId << 24; 1655162Sgblack@eecs.umich.edu } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 1665162Sgblack@eecs.umich.edu int index = (offset - 0x10) / 2; 1675162Sgblack@eecs.umich.edu if (offset % 2) { 1685162Sgblack@eecs.umich.edu result = redirTable[index].topDW; 1695162Sgblack@eecs.umich.edu } else { 1705162Sgblack@eecs.umich.edu result = redirTable[index].bottomDW; 1715162Sgblack@eecs.umich.edu } 1725162Sgblack@eecs.umich.edu } else { 1734825Sgblack@eecs.umich.edu warn("Access to undefined I/O APIC register %#x.\n", offset); 1745162Sgblack@eecs.umich.edu } 1755162Sgblack@eecs.umich.edu DPRINTF(I82094AA, 1765162Sgblack@eecs.umich.edu "Read %#x from I/O APIC register %#x.\n", result, offset); 1775162Sgblack@eecs.umich.edu return result; 1785162Sgblack@eecs.umich.edu} 1795162Sgblack@eecs.umich.edu 1805162Sgblack@eecs.umich.eduvoid 1815162Sgblack@eecs.umich.eduX86ISA::I82094AA::signalInterrupt(int line) 1825162Sgblack@eecs.umich.edu{ 1835162Sgblack@eecs.umich.edu DPRINTF(I82094AA, "Received interrupt %d.\n", line); 1845162Sgblack@eecs.umich.edu assert(line < TableSize); 1855162Sgblack@eecs.umich.edu RedirTableEntry entry = redirTable[line]; 1865162Sgblack@eecs.umich.edu if (entry.mask) { 1875162Sgblack@eecs.umich.edu DPRINTF(I82094AA, "Entry was masked.\n"); 1885162Sgblack@eecs.umich.edu return; 1895162Sgblack@eecs.umich.edu } else { 1905162Sgblack@eecs.umich.edu TriggerIntMessage message = 0; 1915162Sgblack@eecs.umich.edu message.destination = entry.dest; 1925162Sgblack@eecs.umich.edu if (entry.deliveryMode == DeliveryMode::ExtInt) { 1935162Sgblack@eecs.umich.edu assert(extIntPic); 1945162Sgblack@eecs.umich.edu message.vector = extIntPic->getVector(); 1955162Sgblack@eecs.umich.edu } else { 1965162Sgblack@eecs.umich.edu message.vector = entry.vector; 1975162Sgblack@eecs.umich.edu } 1984825Sgblack@eecs.umich.edu message.deliveryMode = entry.deliveryMode; 1994825Sgblack@eecs.umich.edu message.destMode = entry.destMode; 2005162Sgblack@eecs.umich.edu message.level = entry.polarity; 2015162Sgblack@eecs.umich.edu message.trigger = entry.trigger; 2025162Sgblack@eecs.umich.edu ApicList apics; 2034825Sgblack@eecs.umich.edu int numContexts = sys->numContexts(); 2045162Sgblack@eecs.umich.edu if (message.destMode == 0) { 2055162Sgblack@eecs.umich.edu if (message.deliveryMode == DeliveryMode::LowestPriority) { 2064825Sgblack@eecs.umich.edu panic("Lowest priority delivery mode from the " 2074825Sgblack@eecs.umich.edu "IO APIC aren't supported in physical " 2085162Sgblack@eecs.umich.edu "destination mode.\n"); 2095162Sgblack@eecs.umich.edu } 2105162Sgblack@eecs.umich.edu if (message.destination == 0xFF) { 2115162Sgblack@eecs.umich.edu for (int i = 0; i < numContexts; i++) { 2124825Sgblack@eecs.umich.edu apics.push_back(i); 2135162Sgblack@eecs.umich.edu } 2145162Sgblack@eecs.umich.edu } else { 2155162Sgblack@eecs.umich.edu apics.push_back(message.destination); 2165162Sgblack@eecs.umich.edu } 2175162Sgblack@eecs.umich.edu } else { 2185162Sgblack@eecs.umich.edu for (int i = 0; i < numContexts; i++) { 2195162Sgblack@eecs.umich.edu Interrupts *localApic = sys->getThreadContext(i)-> 2205162Sgblack@eecs.umich.edu getCpuPtr()->getInterruptController(); 2215162Sgblack@eecs.umich.edu if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) & 2225162Sgblack@eecs.umich.edu message.destination) { 2235162Sgblack@eecs.umich.edu apics.push_back(localApic->getInitialApicId()); 2245162Sgblack@eecs.umich.edu } 2255162Sgblack@eecs.umich.edu } 2265162Sgblack@eecs.umich.edu if (message.deliveryMode == DeliveryMode::LowestPriority && 2275162Sgblack@eecs.umich.edu apics.size()) { 2285162Sgblack@eecs.umich.edu // The manual seems to suggest that the chipset just does 2295162Sgblack@eecs.umich.edu // something reasonable for these instead of actually using 2305162Sgblack@eecs.umich.edu // state from the local APIC. We'll just rotate an offset 2315162Sgblack@eecs.umich.edu // through the set of APICs selected above. 2325162Sgblack@eecs.umich.edu uint64_t modOffset = lowestPriorityOffset % apics.size(); 2335162Sgblack@eecs.umich.edu lowestPriorityOffset++; 2345162Sgblack@eecs.umich.edu ApicList::iterator apicIt = apics.begin(); 2355162Sgblack@eecs.umich.edu while (modOffset--) { 2365162Sgblack@eecs.umich.edu apicIt++; 2375162Sgblack@eecs.umich.edu assert(apicIt != apics.end()); 2385162Sgblack@eecs.umich.edu } 2395162Sgblack@eecs.umich.edu int selected = *apicIt; 2405162Sgblack@eecs.umich.edu apics.clear(); 2414825Sgblack@eecs.umich.edu apics.push_back(selected); 2425162Sgblack@eecs.umich.edu } 2435162Sgblack@eecs.umich.edu } 2445162Sgblack@eecs.umich.edu intMasterPort.sendMessage(apics, message, sys->isTimingMode()); 2455162Sgblack@eecs.umich.edu } 2465162Sgblack@eecs.umich.edu} 2475162Sgblack@eecs.umich.edu 2485162Sgblack@eecs.umich.eduvoid 2495162Sgblack@eecs.umich.eduX86ISA::I82094AA::raiseInterruptPin(int number) 2505162Sgblack@eecs.umich.edu{ 2515162Sgblack@eecs.umich.edu assert(number < TableSize); 2525162Sgblack@eecs.umich.edu if (!pinStates[number]) 2535162Sgblack@eecs.umich.edu signalInterrupt(number); 2545162Sgblack@eecs.umich.edu pinStates[number] = true; 2555162Sgblack@eecs.umich.edu} 2565162Sgblack@eecs.umich.edu 2575162Sgblack@eecs.umich.eduvoid 2585162Sgblack@eecs.umich.eduX86ISA::I82094AA::lowerInterruptPin(int number) 2595162Sgblack@eecs.umich.edu{ 2604825Sgblack@eecs.umich.edu assert(number < TableSize); 2614825Sgblack@eecs.umich.edu pinStates[number] = false; 2625162Sgblack@eecs.umich.edu} 2635162Sgblack@eecs.umich.edu 2645162Sgblack@eecs.umich.eduvoid 2655162Sgblack@eecs.umich.eduX86ISA::I82094AA::serialize(std::ostream &os) 2665162Sgblack@eecs.umich.edu{ 2675162Sgblack@eecs.umich.edu uint64_t* redirTableArray = (uint64_t*)redirTable; 2685162Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regSel); 2695162Sgblack@eecs.umich.edu SERIALIZE_SCALAR(initialApicId); 2704825Sgblack@eecs.umich.edu SERIALIZE_SCALAR(id); 2715162Sgblack@eecs.umich.edu SERIALIZE_SCALAR(arbId); 2725162Sgblack@eecs.umich.edu SERIALIZE_SCALAR(lowestPriorityOffset); 2735162Sgblack@eecs.umich.edu SERIALIZE_ARRAY(redirTableArray, TableSize); 2745162Sgblack@eecs.umich.edu SERIALIZE_ARRAY(pinStates, TableSize); 2755162Sgblack@eecs.umich.edu} 2765162Sgblack@eecs.umich.edu 2775162Sgblack@eecs.umich.eduvoid 2785162Sgblack@eecs.umich.eduX86ISA::I82094AA::unserialize(Checkpoint *cp, const std::string §ion) 2795162Sgblack@eecs.umich.edu{ 2805162Sgblack@eecs.umich.edu uint64_t redirTableArray[TableSize]; 2815162Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(regSel); 2825162Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(initialApicId); 2835162Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(id); 2845162Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(arbId); 2855162Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(lowestPriorityOffset); 2865162Sgblack@eecs.umich.edu UNSERIALIZE_ARRAY(redirTableArray, TableSize); 2875162Sgblack@eecs.umich.edu UNSERIALIZE_ARRAY(pinStates, TableSize); 2885162Sgblack@eecs.umich.edu for (int i = 0; i < TableSize; i++) { 2895162Sgblack@eecs.umich.edu redirTable[i] = (RedirTableEntry)redirTableArray[i]; 2905162Sgblack@eecs.umich.edu } 2915162Sgblack@eecs.umich.edu} 2925162Sgblack@eecs.umich.edu 2935162Sgblack@eecs.umich.eduX86ISA::I82094AA * 2945162Sgblack@eecs.umich.eduI82094AAParams::create() 2955162Sgblack@eecs.umich.edu{ 2965162Sgblack@eecs.umich.edu return new X86ISA::I82094AA(this); 2975162Sgblack@eecs.umich.edu} 2985162Sgblack@eecs.umich.edu