i82094aa.cc revision 8746
11689SN/A/* 28733Sgeoffrey.blake@arm.com * Copyright (c) 2008 The Regents of The University of Michigan 37783SGiacomo.Gabrielli@arm.com * All rights reserved. 47783SGiacomo.Gabrielli@arm.com * 57783SGiacomo.Gabrielli@arm.com * Redistribution and use in source and binary forms, with or without 67783SGiacomo.Gabrielli@arm.com * modification, are permitted provided that the following conditions are 77783SGiacomo.Gabrielli@arm.com * met: redistributions of source code must retain the above copyright 87783SGiacomo.Gabrielli@arm.com * notice, this list of conditions and the following disclaimer; 97783SGiacomo.Gabrielli@arm.com * redistributions in binary form must reproduce the above copyright 107783SGiacomo.Gabrielli@arm.com * notice, this list of conditions and the following disclaimer in the 117783SGiacomo.Gabrielli@arm.com * documentation and/or other materials provided with the distribution; 127783SGiacomo.Gabrielli@arm.com * neither the name of the copyright holders nor the names of its 137783SGiacomo.Gabrielli@arm.com * contributors may be used to endorse or promote products derived from 142316SN/A * this software without specific prior written permission. 151689SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271689SN/A * 281689SN/A * Authors: Gabe Black 291689SN/A */ 301689SN/A 311689SN/A#include "config/full_system.hh" 321689SN/A 331689SN/A#include "arch/x86/interrupts.hh" 341689SN/A#include "arch/x86/intmessage.hh" 351689SN/A#include "cpu/base.hh" 361689SN/A#include "debug/I82094AA.hh" 371689SN/A#include "dev/x86/i82094aa.hh" 381689SN/A#include "dev/x86/i8259.hh" 392665SN/A#include "mem/packet.hh" 402665SN/A#include "mem/packet_access.hh" 411689SN/A#include "sim/system.hh" 421061SN/A 439944Smatt.horsnell@ARM.comX86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), 449944Smatt.horsnell@ARM.com IntDev(this, p->int_latency), 459944Smatt.horsnell@ARM.com latency(p->pio_latency), pioAddr(p->pio_addr), 465953Ssaidi@eecs.umich.edu extIntPic(p->external_int_pic), lowestPriorityOffset(0) 475596Sgblack@eecs.umich.edu{ 488779Sgblack@eecs.umich.edu // This assumes there's only one I/O APIC in the system and since the apic 499252Sdjordje.kovacevic@arm.com // id is stored in a 8-bit field with 0xff meaning broadcast, the id must 501061SN/A // be less than 0xff 511061SN/A 5210417Sandreas.hansson@arm.com assert(p->apic_id < 0xff); 5310417Sandreas.hansson@arm.com initialApicId = id = p->apic_id; 547720Sgblack@eecs.umich.edu arbId = id; 555596Sgblack@eecs.umich.edu regSel = 0; 568502Sgblack@eecs.umich.edu RedirTableEntry entry = 0; 574637SN/A entry.mask = 1; 584637SN/A for (int i = 0; i < TableSize; i++) { 594637SN/A redirTable[i] = entry; 604637SN/A pinStates[i] = false; 614637SN/A } 6210417Sandreas.hansson@arm.com} 6310417Sandreas.hansson@arm.com 648502Sgblack@eecs.umich.eduvoid 651061SN/AX86ISA::I82094AA::init() 662292SN/A{ 672292SN/A // The io apic must register its address ranges on both its pio port 682292SN/A // via the piodevice init() function and its int port that it inherited 699252Sdjordje.kovacevic@arm.com // from IntDev. Note IntDev is not a SimObject itself. 709252Sdjordje.kovacevic@arm.com 719252Sdjordje.kovacevic@arm.com PioDevice::init(); 729527SMatt.Horsnell@arm.com IntDev::init(); 739527SMatt.Horsnell@arm.com} 749527SMatt.Horsnell@arm.com 759527SMatt.Horsnell@arm.comTick 769527SMatt.Horsnell@arm.comX86ISA::I82094AA::read(PacketPtr pkt) 779527SMatt.Horsnell@arm.com{ 789527SMatt.Horsnell@arm.com assert(pkt->getSize() == 4); 799527SMatt.Horsnell@arm.com Addr offset = pkt->getAddr() - pioAddr; 809527SMatt.Horsnell@arm.com switch(offset) { 819527SMatt.Horsnell@arm.com case 0: 829527SMatt.Horsnell@arm.com pkt->set<uint32_t>(regSel); 839527SMatt.Horsnell@arm.com break; 849527SMatt.Horsnell@arm.com case 16: 859527SMatt.Horsnell@arm.com pkt->set<uint32_t>(readReg(regSel)); 869527SMatt.Horsnell@arm.com break; 879527SMatt.Horsnell@arm.com default: 889527SMatt.Horsnell@arm.com panic("Illegal read from I/O APIC.\n"); 899527SMatt.Horsnell@arm.com } 909527SMatt.Horsnell@arm.com pkt->makeAtomicResponse(); 919527SMatt.Horsnell@arm.com return latency; 929527SMatt.Horsnell@arm.com} 939527SMatt.Horsnell@arm.com 949527SMatt.Horsnell@arm.comTick 959527SMatt.Horsnell@arm.comX86ISA::I82094AA::write(PacketPtr pkt) 969527SMatt.Horsnell@arm.com{ 979527SMatt.Horsnell@arm.com assert(pkt->getSize() == 4); 989527SMatt.Horsnell@arm.com Addr offset = pkt->getAddr() - pioAddr; 999527SMatt.Horsnell@arm.com switch(offset) { 1009527SMatt.Horsnell@arm.com case 0: 1019252Sdjordje.kovacevic@arm.com regSel = pkt->get<uint32_t>(); 1029252Sdjordje.kovacevic@arm.com break; 1039252Sdjordje.kovacevic@arm.com case 16: 1049252Sdjordje.kovacevic@arm.com writeReg(regSel, pkt->get<uint32_t>()); 1052292SN/A break; 1062292SN/A default: 1075596Sgblack@eecs.umich.edu panic("Illegal write to I/O APIC.\n"); 1082292SN/A } 1091464SN/A pkt->makeAtomicResponse(); 1101464SN/A return latency; 1111464SN/A} 1122292SN/A 1133782SN/Avoid 1141464SN/AX86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value) 1151464SN/A{ 1162292SN/A if (offset == 0x0) { 1173782SN/A id = bits(value, 31, 24); 1181464SN/A } else if (offset == 0x1) { 1197783SGiacomo.Gabrielli@arm.com // The IOAPICVER register is read only. 1209046SAli.Saidi@ARM.com } else if (offset == 0x2) { 1219046SAli.Saidi@ARM.com arbId = bits(value, 31, 24); 1227783SGiacomo.Gabrielli@arm.com } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 1238471SGiacomo.Gabrielli@arm.com int index = (offset - 0x10) / 2; 1248471SGiacomo.Gabrielli@arm.com if (offset % 2) { 1259252Sdjordje.kovacevic@arm.com redirTable[index].topDW = value; 1269252Sdjordje.kovacevic@arm.com redirTable[index].topReserved = 0; 1279252Sdjordje.kovacevic@arm.com } else { 1289252Sdjordje.kovacevic@arm.com redirTable[index].bottomDW = value; 1299252Sdjordje.kovacevic@arm.com redirTable[index].bottomReserved = 0; 1309252Sdjordje.kovacevic@arm.com } 1319252Sdjordje.kovacevic@arm.com } else { 1329252Sdjordje.kovacevic@arm.com warn("Access to undefined I/O APIC register %#x.\n", offset); 1339252Sdjordje.kovacevic@arm.com } 1349527SMatt.Horsnell@arm.com DPRINTF(I82094AA, 1358471SGiacomo.Gabrielli@arm.com "Wrote %#x to I/O APIC register %#x .\n", value, offset); 1361061SN/A} 1371061SN/A 1382292SN/Auint32_t 1392292SN/AX86ISA::I82094AA::readReg(uint8_t offset) 1405596Sgblack@eecs.umich.edu{ 1412292SN/A uint32_t result = 0; 1422348SN/A if (offset == 0x0) { 1432680SN/A result = id << 24; 1442348SN/A } else if (offset == 0x1) { 1452680SN/A result = ((TableSize - 1) << 16) | APICVersion; 1469382SAli.Saidi@ARM.com } else if (offset == 0x2) { 1479382SAli.Saidi@ARM.com result = arbId << 24; 1482292SN/A } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 1492292SN/A int index = (offset - 0x10) / 2; 1502292SN/A if (offset % 2) { 1519382SAli.Saidi@ARM.com result = redirTable[index].topDW; 1522292SN/A } else { 1532292SN/A result = redirTable[index].bottomDW; 1542292SN/A } 1552292SN/A } else { 1562292SN/A warn("Access to undefined I/O APIC register %#x.\n", offset); 1572292SN/A } 1585596Sgblack@eecs.umich.edu DPRINTF(I82094AA, 1592292SN/A "Read %#x from I/O APIC register %#x.\n", result, offset); 1602348SN/A return result; 1612680SN/A} 1622348SN/A 1632680SN/Avoid 1649382SAli.Saidi@ARM.comX86ISA::I82094AA::signalInterrupt(int line) 1659382SAli.Saidi@ARM.com{ 1662292SN/A DPRINTF(I82094AA, "Received interrupt %d.\n", line); 1672292SN/A assert(line < TableSize); 1682292SN/A RedirTableEntry entry = redirTable[line]; 1699382SAli.Saidi@ARM.com if (entry.mask) { 1702292SN/A DPRINTF(I82094AA, "Entry was masked.\n"); 1712292SN/A return; 1722292SN/A } else { 1732292SN/A TriggerIntMessage message = 0; 1742292SN/A message.destination = entry.dest; 1752292SN/A if (entry.deliveryMode == DeliveryMode::ExtInt) { 1765596Sgblack@eecs.umich.edu assert(extIntPic); 1772292SN/A message.vector = extIntPic->getVector(); 1787758Sminkyu.jeong@arm.com } else { 1797758Sminkyu.jeong@arm.com message.vector = entry.vector; 1807758Sminkyu.jeong@arm.com } 1817758Sminkyu.jeong@arm.com message.deliveryMode = entry.deliveryMode; 1829382SAli.Saidi@ARM.com message.destMode = entry.destMode; 1839382SAli.Saidi@ARM.com message.level = entry.polarity; 1847758Sminkyu.jeong@arm.com message.trigger = entry.trigger; 1858887Sgeoffrey.blake@arm.com ApicList apics; 1868887Sgeoffrey.blake@arm.com int numContexts = sys->numContexts(); 1878887Sgeoffrey.blake@arm.com if (message.destMode == 0) { 1888887Sgeoffrey.blake@arm.com if (message.deliveryMode == DeliveryMode::LowestPriority) { 1898733Sgeoffrey.blake@arm.com panic("Lowest priority delivery mode from the " 1908887Sgeoffrey.blake@arm.com "IO APIC aren't supported in physical " 1912790SN/A "destination mode.\n"); 1922292SN/A } 1939382SAli.Saidi@ARM.com if (message.destination == 0xFF) { 1947758Sminkyu.jeong@arm.com for (int i = 0; i < numContexts; i++) { 1952292SN/A apics.push_back(i); 1962292SN/A } 1972292SN/A } else { 1981061SN/A apics.push_back(message.destination); 1995702Ssaidi@eecs.umich.edu } 2005702Ssaidi@eecs.umich.edu } else { 2015702Ssaidi@eecs.umich.edu for (int i = 0; i < numContexts; i++) { 2025702Ssaidi@eecs.umich.edu Interrupts *localApic = sys->getThreadContext(i)-> 2035702Ssaidi@eecs.umich.edu getCpuPtr()->getInterruptController(); 2047720Sgblack@eecs.umich.edu if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) & 20510474Sandreas.hansson@arm.com message.destination) { 2065702Ssaidi@eecs.umich.edu apics.push_back(localApic->getInitialApicId()); 2075702Ssaidi@eecs.umich.edu } 2087720Sgblack@eecs.umich.edu } 2097720Sgblack@eecs.umich.edu if (message.deliveryMode == DeliveryMode::LowestPriority && 2107720Sgblack@eecs.umich.edu apics.size()) { 2117720Sgblack@eecs.umich.edu // The manual seems to suggest that the chipset just does 2125953Ssaidi@eecs.umich.edu // something reasonable for these instead of actually using 2135953Ssaidi@eecs.umich.edu // state from the local APIC. We'll just rotate an offset 2147720Sgblack@eecs.umich.edu // through the set of APICs selected above. 2155953Ssaidi@eecs.umich.edu uint64_t modOffset = lowestPriorityOffset % apics.size(); 2165702Ssaidi@eecs.umich.edu lowestPriorityOffset++; 2175702Ssaidi@eecs.umich.edu ApicList::iterator apicIt = apics.begin(); 2185702Ssaidi@eecs.umich.edu while (modOffset--) { 2195702Ssaidi@eecs.umich.edu apicIt++; 2205702Ssaidi@eecs.umich.edu assert(apicIt != apics.end()); 2215702Ssaidi@eecs.umich.edu } 2225702Ssaidi@eecs.umich.edu int selected = *apicIt; 2235702Ssaidi@eecs.umich.edu apics.clear(); 2245702Ssaidi@eecs.umich.edu apics.push_back(selected); 2255702Ssaidi@eecs.umich.edu } 2265702Ssaidi@eecs.umich.edu } 2271061SN/A intPort->sendMessage(apics, message, 22810379Sandreas.hansson@arm.com sys->getMemoryMode() == Enums::timing); 2291061SN/A } 2307684Sgblack@eecs.umich.edu} 2311061SN/A 2325702Ssaidi@eecs.umich.eduvoid 2335702Ssaidi@eecs.umich.eduX86ISA::I82094AA::raiseInterruptPin(int number) 2345702Ssaidi@eecs.umich.edu{ 2355702Ssaidi@eecs.umich.edu assert(number < TableSize); 2365702Ssaidi@eecs.umich.edu if (!pinStates[number]) 2375702Ssaidi@eecs.umich.edu signalInterrupt(number); 2385702Ssaidi@eecs.umich.edu pinStates[number] = true; 2395702Ssaidi@eecs.umich.edu} 2405702Ssaidi@eecs.umich.edu 2415702Ssaidi@eecs.umich.eduvoid 2428557Sgblack@eecs.umich.eduX86ISA::I82094AA::lowerInterruptPin(int number) 2431061SN/A{ 2441061SN/A assert(number < TableSize); 2455596Sgblack@eecs.umich.edu pinStates[number] = false; 2461061SN/A} 2478806Sgblack@eecs.umich.edu 2488779Sgblack@eecs.umich.eduvoid 2498806Sgblack@eecs.umich.eduX86ISA::I82094AA::serialize(std::ostream &os) 2505556SN/A{ 2515556SN/A uint64_t* redirTableArray = (uint64_t*)redirTable; 2525556SN/A SERIALIZE_SCALAR(regSel); 2537720Sgblack@eecs.umich.edu SERIALIZE_SCALAR(initialApicId); 2542669SN/A SERIALIZE_SCALAR(id); 2557720Sgblack@eecs.umich.edu SERIALIZE_SCALAR(arbId); 2567720Sgblack@eecs.umich.edu SERIALIZE_SCALAR(lowestPriorityOffset); 2577720Sgblack@eecs.umich.edu SERIALIZE_ARRAY(redirTableArray, TableSize); 2585556SN/A SERIALIZE_ARRAY(pinStates, TableSize); 2591061SN/A} 2601061SN/A 2619944Smatt.horsnell@ARM.comvoid 262X86ISA::I82094AA::unserialize(Checkpoint *cp, const std::string §ion) 263{ 264 uint64_t redirTableArray[TableSize]; 265 UNSERIALIZE_SCALAR(regSel); 266 UNSERIALIZE_SCALAR(initialApicId); 267 UNSERIALIZE_SCALAR(id); 268 UNSERIALIZE_SCALAR(arbId); 269 UNSERIALIZE_SCALAR(lowestPriorityOffset); 270 UNSERIALIZE_ARRAY(redirTableArray, TableSize); 271 UNSERIALIZE_ARRAY(pinStates, TableSize); 272 for (int i = 0; i < TableSize; i++) { 273 redirTable[i] = (RedirTableEntry)redirTableArray[i]; 274 } 275} 276 277X86ISA::I82094AA * 278I82094AAParams::create() 279{ 280 return new X86ISA::I82094AA(this); 281} 282