i82094aa.cc revision 13784
12SN/A/* 21762SN/A * Copyright (c) 2008 The Regents of The University of Michigan 35502Snate@binkert.org * All rights reserved. 49983Sstever@gmail.com * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272SN/A * 282SN/A * Authors: Gabe Black 292665Ssaidi@eecs.umich.edu */ 302665Ssaidi@eecs.umich.edu 312665Ssaidi@eecs.umich.edu#include "dev/x86/i82094aa.hh" 322665Ssaidi@eecs.umich.edu 332SN/A#include "arch/x86/interrupts.hh" 342SN/A#include "arch/x86/intmessage.hh" 355501Snate@binkert.org#include "cpu/base.hh" 362SN/A#include "debug/I82094AA.hh" 372SN/A#include "dev/x86/i8259.hh" 382SN/A#include "mem/packet.hh" 392SN/A#include "mem/packet_access.hh" 405502Snate@binkert.org#include "sim/system.hh" 415501Snate@binkert.org 425501Snate@binkert.orgX86ISA::I82094AA::I82094AA(Params *p) 431717SN/A : BasicPioDevice(p, 20), IntDevice(this, p->int_latency), 4410906Sandreas.sandberg@arm.com extIntPic(p->external_int_pic), lowestPriorityOffset(0) 455501Snate@binkert.org{ 469356Snilay@cs.wisc.edu // This assumes there's only one I/O APIC in the system and since the apic 472SN/A // id is stored in a 8-bit field with 0xff meaning broadcast, the id must 482SN/A // be less than 0xff 492SN/A 509983Sstever@gmail.com assert(p->apic_id < 0xff); 519983Sstever@gmail.com initialApicId = id = p->apic_id; 522SN/A arbId = id; 539983Sstever@gmail.com regSel = 0; 542SN/A RedirTableEntry entry = 0; 559983Sstever@gmail.com entry.mask = 1; 562SN/A for (int i = 0; i < TableSize; i++) { 572SN/A redirTable[i] = entry; 589983Sstever@gmail.com pinStates[i] = false; 599983Sstever@gmail.com } 609983Sstever@gmail.com} 619983Sstever@gmail.com 629983Sstever@gmail.comvoid 639983Sstever@gmail.comX86ISA::I82094AA::init() 649983Sstever@gmail.com{ 659983Sstever@gmail.com // The io apic must register its address ranges on both its pio port 669983Sstever@gmail.com // via the piodevice init() function and its int port that it inherited 679983Sstever@gmail.com // from IntDevice. Note IntDevice is not a SimObject itself. 689983Sstever@gmail.com 699983Sstever@gmail.com BasicPioDevice::init(); 709983Sstever@gmail.com IntDevice::init(); 719983Sstever@gmail.com} 729983Sstever@gmail.com 739983Sstever@gmail.comPort & 742SN/AX86ISA::I82094AA::getPort(const std::string &if_name, PortID idx) 754017Sstever@eecs.umich.edu{ 764016Sstever@eecs.umich.edu if (if_name == "int_master") 774017Sstever@eecs.umich.edu return intMasterPort; 784016Sstever@eecs.umich.edu return BasicPioDevice::getPort(if_name, idx); 795768Snate@binkert.org} 805768Snate@binkert.org 815774Snate@binkert.orgAddrRangeList 827059Snate@binkert.orgX86ISA::I82094AA::getIntAddrRange() const 835768Snate@binkert.org{ 845768Snate@binkert.org AddrRangeList ranges; 855768Snate@binkert.org ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0), 865768Snate@binkert.org x86InterruptAddress(initialApicId, 0) + 875768Snate@binkert.org PhysAddrAPICRangeSize)); 885768Snate@binkert.org return ranges; 895768Snate@binkert.org} 905768Snate@binkert.org 915768Snate@binkert.orgTick 925768Snate@binkert.orgX86ISA::I82094AA::recvResponse(PacketPtr pkt) 935768Snate@binkert.org{ 945768Snate@binkert.org // Packet instantiated calling sendMessage() in signalInterrupt() 955768Snate@binkert.org delete pkt; 965602Snate@binkert.org return 0; 975602Snate@binkert.org} 985502Snate@binkert.org 995503Snate@binkert.orgTick 1005502Snate@binkert.orgX86ISA::I82094AA::read(PacketPtr pkt) 1015502Snate@binkert.org{ 1025502Snate@binkert.org assert(pkt->getSize() == 4); 1035502Snate@binkert.org Addr offset = pkt->getAddr() - pioAddr; 1045502Snate@binkert.org switch(offset) { 1055503Snate@binkert.org case 0: 1065502Snate@binkert.org pkt->setLE<uint32_t>(regSel); 1075502Snate@binkert.org break; 1085502Snate@binkert.org case 16: 1095502Snate@binkert.org pkt->setLE<uint32_t>(readReg(regSel)); 1105503Snate@binkert.org break; 1115503Snate@binkert.org default: 1125503Snate@binkert.org panic("Illegal read from I/O APIC.\n"); 1135502Snate@binkert.org } 1145503Snate@binkert.org pkt->makeAtomicResponse(); 1155502Snate@binkert.org return pioDelay; 1165502Snate@binkert.org} 1172SN/A 1182SN/ATick 1192SN/AX86ISA::I82094AA::write(PacketPtr pkt) 1205502Snate@binkert.org{ 1215502Snate@binkert.org assert(pkt->getSize() == 4); 1225602Snate@binkert.org Addr offset = pkt->getAddr() - pioAddr; 1235502Snate@binkert.org switch(offset) { 1245502Snate@binkert.org case 0: 1252SN/A regSel = pkt->getLE<uint32_t>(); 1265502Snate@binkert.org break; 1275502Snate@binkert.org case 16: 1285503Snate@binkert.org writeReg(regSel, pkt->getLE<uint32_t>()); 1295503Snate@binkert.org break; 1305503Snate@binkert.org default: 1315503Snate@binkert.org panic("Illegal write to I/O APIC.\n"); 1325503Snate@binkert.org } 1335502Snate@binkert.org pkt->makeAtomicResponse(); 1342SN/A return pioDelay; 1355503Snate@binkert.org} 1365503Snate@binkert.org 1375602Snate@binkert.orgvoid 1385502Snate@binkert.orgX86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value) 1392SN/A{ 1405602Snate@binkert.org if (offset == 0x0) { 1415602Snate@binkert.org id = bits(value, 31, 24); 1425502Snate@binkert.org } else if (offset == 0x1) { 1435503Snate@binkert.org // The IOAPICVER register is read only. 1445503Snate@binkert.org } else if (offset == 0x2) { 1455502Snate@binkert.org arbId = bits(value, 31, 24); 1465503Snate@binkert.org } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 1475503Snate@binkert.org int index = (offset - 0x10) / 2; 1485503Snate@binkert.org if (offset % 2) { 1495503Snate@binkert.org redirTable[index].topDW = value; 1505503Snate@binkert.org redirTable[index].topReserved = 0; 1515503Snate@binkert.org } else { 1525503Snate@binkert.org redirTable[index].bottomDW = value; 1535503Snate@binkert.org redirTable[index].bottomReserved = 0; 1545503Snate@binkert.org } 1555503Snate@binkert.org } else { 1565503Snate@binkert.org warn("Access to undefined I/O APIC register %#x.\n", offset); 1575503Snate@binkert.org } 1585503Snate@binkert.org DPRINTF(I82094AA, 1595503Snate@binkert.org "Wrote %#x to I/O APIC register %#x .\n", value, offset); 1605502Snate@binkert.org} 1615502Snate@binkert.org 1625503Snate@binkert.orguint32_t 1635503Snate@binkert.orgX86ISA::I82094AA::readReg(uint8_t offset) 1642SN/A{ 1655502Snate@binkert.org uint32_t result = 0; 1665503Snate@binkert.org if (offset == 0x0) { 1675503Snate@binkert.org result = id << 24; 1685503Snate@binkert.org } else if (offset == 0x1) { 1692SN/A result = ((TableSize - 1) << 16) | APICVersion; 1702SN/A } else if (offset == 0x2) { 1712SN/A result = arbId << 24; 1722SN/A } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 1732SN/A int index = (offset - 0x10) / 2; 1742SN/A if (offset % 2) { 1755502Snate@binkert.org result = redirTable[index].topDW; 1762SN/A } else { 1779983Sstever@gmail.com result = redirTable[index].bottomDW; 1789983Sstever@gmail.com } 1795502Snate@binkert.org } else { 1805502Snate@binkert.org warn("Access to undefined I/O APIC register %#x.\n", offset); 1815502Snate@binkert.org } 1825602Snate@binkert.org DPRINTF(I82094AA, 1832SN/A "Read %#x from I/O APIC register %#x.\n", result, offset); 1842SN/A return result; 1852SN/A} 1865502Snate@binkert.org 1872SN/Avoid 1885502Snate@binkert.orgX86ISA::I82094AA::signalInterrupt(int line) 1895502Snate@binkert.org{ 1902SN/A DPRINTF(I82094AA, "Received interrupt %d.\n", line); 1915502Snate@binkert.org assert(line < TableSize); 1922SN/A RedirTableEntry entry = redirTable[line]; 1932SN/A if (entry.mask) { 1945502Snate@binkert.org DPRINTF(I82094AA, "Entry was masked.\n"); 1955502Snate@binkert.org return; 1965502Snate@binkert.org } else { 1975503Snate@binkert.org TriggerIntMessage message = 0; 1985503Snate@binkert.org message.destination = entry.dest; 1995502Snate@binkert.org if (entry.deliveryMode == DeliveryMode::ExtInt) { 2005602Snate@binkert.org assert(extIntPic); 2012SN/A message.vector = extIntPic->getVector(); 2022SN/A } else { 2032667Sstever@eecs.umich.edu message.vector = entry.vector; 2042SN/A } 2052SN/A message.deliveryMode = entry.deliveryMode; 20610153Sandreas@sandberg.pp.se message.destMode = entry.destMode; 2075503Snate@binkert.org message.level = entry.polarity; 2085503Snate@binkert.org message.trigger = entry.trigger; 2095769Snate@binkert.org ApicList apics; 2105502Snate@binkert.org int numContexts = sys->numContexts(); 2115503Snate@binkert.org if (message.destMode == 0) { 2125503Snate@binkert.org if (message.deliveryMode == DeliveryMode::LowestPriority) { 2135503Snate@binkert.org panic("Lowest priority delivery mode from the " 2145503Snate@binkert.org "IO APIC aren't supported in physical " 2155503Snate@binkert.org "destination mode.\n"); 2165503Snate@binkert.org } 2175503Snate@binkert.org if (message.destination == 0xFF) { 2185502Snate@binkert.org for (int i = 0; i < numContexts; i++) { 2195502Snate@binkert.org apics.push_back(i); 2205503Snate@binkert.org } 2215502Snate@binkert.org } else { 2222SN/A apics.push_back(message.destination); 2232SN/A } 2242667Sstever@eecs.umich.edu } else { 2259356Snilay@cs.wisc.edu for (int i = 0; i < numContexts; i++) { 2269356Snilay@cs.wisc.edu Interrupts *localApic = sys->getThreadContext(i)-> 2279356Snilay@cs.wisc.edu getCpuPtr()->getInterruptController(0); 2282SN/A if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) & 2292667Sstever@eecs.umich.edu message.destination) { 2309328SAli.Saidi@ARM.com apics.push_back(localApic->getInitialApicId()); 2319328SAli.Saidi@ARM.com } 2322667Sstever@eecs.umich.edu } 2332667Sstever@eecs.umich.edu if (message.deliveryMode == DeliveryMode::LowestPriority && 2342667Sstever@eecs.umich.edu apics.size()) { 2355769Snate@binkert.org // The manual seems to suggest that the chipset just does 2362667Sstever@eecs.umich.edu // something reasonable for these instead of actually using 2372SN/A // state from the local APIC. We'll just rotate an offset 2385769Snate@binkert.org // through the set of APICs selected above. 2392SN/A uint64_t modOffset = lowestPriorityOffset % apics.size(); 2402667Sstever@eecs.umich.edu lowestPriorityOffset++; 2412667Sstever@eecs.umich.edu ApicList::iterator apicIt = apics.begin(); 2422SN/A while (modOffset--) { 2432SN/A apicIt++; 244224SN/A assert(apicIt != apics.end()); 24510905Sandreas.sandberg@arm.com } 246224SN/A int selected = *apicIt; 247224SN/A apics.clear(); 248224SN/A apics.push_back(selected); 2495769Snate@binkert.org } 2505769Snate@binkert.org } 251224SN/A intMasterPort.sendMessage(apics, message, sys->isTimingMode()); 252224SN/A } 253224SN/A} 25410905Sandreas.sandberg@arm.com 255224SN/Avoid 25610906Sandreas.sandberg@arm.comX86ISA::I82094AA::raiseInterruptPin(int number) 257224SN/A{ 258224SN/A assert(number < TableSize); 259224SN/A if (!pinStates[number]) 260224SN/A signalInterrupt(number); 26110906Sandreas.sandberg@arm.com pinStates[number] = true; 2625769Snate@binkert.org} 2637452SLisa.Hsu@amd.com 2647452SLisa.Hsu@amd.comvoid 2657452SLisa.Hsu@amd.comX86ISA::I82094AA::lowerInterruptPin(int number) 2667452SLisa.Hsu@amd.com{ 2677452SLisa.Hsu@amd.com assert(number < TableSize); 2687452SLisa.Hsu@amd.com pinStates[number] = false; 2697452SLisa.Hsu@amd.com} 2707451SLisa.Hsu@amd.com 2715769Snate@binkert.orgvoid 2727451SLisa.Hsu@amd.comX86ISA::I82094AA::serialize(CheckpointOut &cp) const 2735769Snate@binkert.org{ 2747452SLisa.Hsu@amd.com uint64_t* redirTableArray = (uint64_t*)redirTable; 2757452SLisa.Hsu@amd.com SERIALIZE_SCALAR(regSel); 2767452SLisa.Hsu@amd.com SERIALIZE_SCALAR(initialApicId); 27710906Sandreas.sandberg@arm.com SERIALIZE_SCALAR(id); 27810906Sandreas.sandberg@arm.com SERIALIZE_SCALAR(arbId); 27910906Sandreas.sandberg@arm.com SERIALIZE_SCALAR(lowestPriorityOffset); 28010906Sandreas.sandberg@arm.com SERIALIZE_ARRAY(redirTableArray, TableSize); 28110906Sandreas.sandberg@arm.com SERIALIZE_ARRAY(pinStates, TableSize); 282224SN/A} 283224SN/A 284224SN/Avoid 2852SN/AX86ISA::I82094AA::unserialize(CheckpointIn &cp) 28610905Sandreas.sandberg@arm.com{ 2872SN/A uint64_t redirTableArray[TableSize]; 288265SN/A UNSERIALIZE_SCALAR(regSel); 289237SN/A UNSERIALIZE_SCALAR(initialApicId); 290237SN/A UNSERIALIZE_SCALAR(id); 2915502Snate@binkert.org UNSERIALIZE_SCALAR(arbId); 2925502Snate@binkert.org UNSERIALIZE_SCALAR(lowestPriorityOffset); 2935503Snate@binkert.org UNSERIALIZE_ARRAY(redirTableArray, TableSize); 2945502Snate@binkert.org UNSERIALIZE_ARRAY(pinStates, TableSize); 2955503Snate@binkert.org for (int i = 0; i < TableSize; i++) { 2965769Snate@binkert.org redirTable[i] = (RedirTableEntry)redirTableArray[i]; 2975502Snate@binkert.org } 29810905Sandreas.sandberg@arm.com} 2995502Snate@binkert.org 3005502Snate@binkert.orgX86ISA::I82094AA * 3015502Snate@binkert.orgI82094AAParams::create() 3025503Snate@binkert.org{ 3035502Snate@binkert.org return new X86ISA::I82094AA(this); 3045502Snate@binkert.org} 3052SN/A