i82094aa.cc revision 9524
15659Sgblack@eecs.umich.edu/* 25659Sgblack@eecs.umich.edu * Copyright (c) 2008 The Regents of The University of Michigan 35659Sgblack@eecs.umich.edu * All rights reserved. 45659Sgblack@eecs.umich.edu * 55659Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 65659Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 75659Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 85659Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 95659Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 105659Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 115659Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 125659Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 135659Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 145659Sgblack@eecs.umich.edu * this software without specific prior written permission. 155659Sgblack@eecs.umich.edu * 165659Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175659Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185659Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195659Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205659Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215659Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225659Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235659Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245659Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255659Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265659Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275659Sgblack@eecs.umich.edu * 285659Sgblack@eecs.umich.edu * Authors: Gabe Black 295659Sgblack@eecs.umich.edu */ 305659Sgblack@eecs.umich.edu 315659Sgblack@eecs.umich.edu#include "arch/x86/interrupts.hh" 325659Sgblack@eecs.umich.edu#include "arch/x86/intmessage.hh" 335659Sgblack@eecs.umich.edu#include "cpu/base.hh" 345659Sgblack@eecs.umich.edu#include "debug/I82094AA.hh" 355659Sgblack@eecs.umich.edu#include "dev/x86/i82094aa.hh" 365659Sgblack@eecs.umich.edu#include "dev/x86/i8259.hh" 375659Sgblack@eecs.umich.edu#include "mem/packet.hh" 385659Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 395659Sgblack@eecs.umich.edu#include "sim/system.hh" 405659Sgblack@eecs.umich.edu 415659Sgblack@eecs.umich.eduX86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), 425659Sgblack@eecs.umich.edu IntDev(this, p->int_latency), 435659Sgblack@eecs.umich.edu latency(p->pio_latency), pioAddr(p->pio_addr), 445659Sgblack@eecs.umich.edu extIntPic(p->external_int_pic), lowestPriorityOffset(0) 455659Sgblack@eecs.umich.edu{ 465659Sgblack@eecs.umich.edu // This assumes there's only one I/O APIC in the system and since the apic 475659Sgblack@eecs.umich.edu // id is stored in a 8-bit field with 0xff meaning broadcast, the id must 485659Sgblack@eecs.umich.edu // be less than 0xff 495659Sgblack@eecs.umich.edu 505659Sgblack@eecs.umich.edu assert(p->apic_id < 0xff); 5110439Smajiuyue@ncic.ac.cn initialApicId = id = p->apic_id; 525659Sgblack@eecs.umich.edu arbId = id; 535659Sgblack@eecs.umich.edu regSel = 0; 545659Sgblack@eecs.umich.edu RedirTableEntry entry = 0; 555659Sgblack@eecs.umich.edu entry.mask = 1; 5610439Smajiuyue@ncic.ac.cn for (int i = 0; i < TableSize; i++) { 575659Sgblack@eecs.umich.edu redirTable[i] = entry; 585659Sgblack@eecs.umich.edu pinStates[i] = false; 595659Sgblack@eecs.umich.edu } 605659Sgblack@eecs.umich.edu} 615659Sgblack@eecs.umich.edu 625659Sgblack@eecs.umich.eduvoid 635659Sgblack@eecs.umich.eduX86ISA::I82094AA::init() 645659Sgblack@eecs.umich.edu{ 655659Sgblack@eecs.umich.edu // The io apic must register its address ranges on both its pio port 666040Sgblack@eecs.umich.edu // via the piodevice init() function and its int port that it inherited 675659Sgblack@eecs.umich.edu // from IntDev. Note IntDev is not a SimObject itself. 685659Sgblack@eecs.umich.edu 695659Sgblack@eecs.umich.edu PioDevice::init(); 705659Sgblack@eecs.umich.edu IntDev::init(); 715659Sgblack@eecs.umich.edu} 725659Sgblack@eecs.umich.edu 735659Sgblack@eecs.umich.eduTick 745659Sgblack@eecs.umich.eduX86ISA::I82094AA::read(PacketPtr pkt) 755659Sgblack@eecs.umich.edu{ 765659Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 775659Sgblack@eecs.umich.edu Addr offset = pkt->getAddr() - pioAddr; 785659Sgblack@eecs.umich.edu switch(offset) { 795659Sgblack@eecs.umich.edu case 0: 805659Sgblack@eecs.umich.edu pkt->set<uint32_t>(regSel); 815659Sgblack@eecs.umich.edu break; 827072Sgblack@eecs.umich.edu case 16: 837072Sgblack@eecs.umich.edu pkt->set<uint32_t>(readReg(regSel)); 845659Sgblack@eecs.umich.edu break; 855659Sgblack@eecs.umich.edu default: 865659Sgblack@eecs.umich.edu panic("Illegal read from I/O APIC.\n"); 875659Sgblack@eecs.umich.edu } 885659Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 895659Sgblack@eecs.umich.edu return latency; 905659Sgblack@eecs.umich.edu} 915659Sgblack@eecs.umich.edu 925659Sgblack@eecs.umich.eduTick 936052Sgblack@eecs.umich.eduX86ISA::I82094AA::write(PacketPtr pkt) 945659Sgblack@eecs.umich.edu{ 955659Sgblack@eecs.umich.edu assert(pkt->getSize() == 4); 965659Sgblack@eecs.umich.edu Addr offset = pkt->getAddr() - pioAddr; 975659Sgblack@eecs.umich.edu switch(offset) { 985659Sgblack@eecs.umich.edu case 0: 995659Sgblack@eecs.umich.edu regSel = pkt->get<uint32_t>(); 10010637Sgabeblack@google.com break; 1015659Sgblack@eecs.umich.edu case 16: 1025659Sgblack@eecs.umich.edu writeReg(regSel, pkt->get<uint32_t>()); 1035659Sgblack@eecs.umich.edu break; 1045659Sgblack@eecs.umich.edu default: 1055659Sgblack@eecs.umich.edu panic("Illegal write to I/O APIC.\n"); 1065659Sgblack@eecs.umich.edu } 1075659Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 1085659Sgblack@eecs.umich.edu return latency; 1095659Sgblack@eecs.umich.edu} 1105659Sgblack@eecs.umich.edu 1115659Sgblack@eecs.umich.eduvoid 1125659Sgblack@eecs.umich.eduX86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value) 1135659Sgblack@eecs.umich.edu{ 1145659Sgblack@eecs.umich.edu if (offset == 0x0) { 1155659Sgblack@eecs.umich.edu id = bits(value, 31, 24); 1165659Sgblack@eecs.umich.edu } else if (offset == 0x1) { 1176068Sgblack@eecs.umich.edu // The IOAPICVER register is read only. 1186068Sgblack@eecs.umich.edu } else if (offset == 0x2) { 1195659Sgblack@eecs.umich.edu arbId = bits(value, 31, 24); 1205659Sgblack@eecs.umich.edu } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 1215659Sgblack@eecs.umich.edu int index = (offset - 0x10) / 2; 1225659Sgblack@eecs.umich.edu if (offset % 2) { 1235659Sgblack@eecs.umich.edu redirTable[index].topDW = value; 1245659Sgblack@eecs.umich.edu redirTable[index].topReserved = 0; 1255659Sgblack@eecs.umich.edu } else { 1265659Sgblack@eecs.umich.edu redirTable[index].bottomDW = value; 1275659Sgblack@eecs.umich.edu redirTable[index].bottomReserved = 0; 1285659Sgblack@eecs.umich.edu } 1295659Sgblack@eecs.umich.edu } else { 1305659Sgblack@eecs.umich.edu warn("Access to undefined I/O APIC register %#x.\n", offset); 1315659Sgblack@eecs.umich.edu } 1325659Sgblack@eecs.umich.edu DPRINTF(I82094AA, 13310439Smajiuyue@ncic.ac.cn "Wrote %#x to I/O APIC register %#x .\n", value, offset); 13410539Sgabeblack@google.com} 13510439Smajiuyue@ncic.ac.cn 13610439Smajiuyue@ncic.ac.cnuint32_t 13710439Smajiuyue@ncic.ac.cnX86ISA::I82094AA::readReg(uint8_t offset) 1385659Sgblack@eecs.umich.edu{ 1395659Sgblack@eecs.umich.edu uint32_t result = 0; 1405659Sgblack@eecs.umich.edu if (offset == 0x0) { 14111217Sbaz21@cam.ac.uk result = id << 24; 14211217Sbaz21@cam.ac.uk } else if (offset == 0x1) { 1435659Sgblack@eecs.umich.edu result = ((TableSize - 1) << 16) | APICVersion; 1445659Sgblack@eecs.umich.edu } else if (offset == 0x2) { 1455659Sgblack@eecs.umich.edu result = arbId << 24; 1465659Sgblack@eecs.umich.edu } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 1475659Sgblack@eecs.umich.edu int index = (offset - 0x10) / 2; 1485659Sgblack@eecs.umich.edu if (offset % 2) { 1495659Sgblack@eecs.umich.edu result = redirTable[index].topDW; 1505659Sgblack@eecs.umich.edu } else { 1515659Sgblack@eecs.umich.edu result = redirTable[index].bottomDW; 1525659Sgblack@eecs.umich.edu } 1535659Sgblack@eecs.umich.edu } else { 1545659Sgblack@eecs.umich.edu warn("Access to undefined I/O APIC register %#x.\n", offset); 1555659Sgblack@eecs.umich.edu } 1565659Sgblack@eecs.umich.edu DPRINTF(I82094AA, 1579473Snilay@cs.wisc.edu "Read %#x from I/O APIC register %#x.\n", result, offset); 15810638Sgabeblack@google.com return result; 1595659Sgblack@eecs.umich.edu} 1605659Sgblack@eecs.umich.edu 16111217Sbaz21@cam.ac.ukvoid 16211217Sbaz21@cam.ac.ukX86ISA::I82094AA::signalInterrupt(int line) 1635659Sgblack@eecs.umich.edu{ 1645659Sgblack@eecs.umich.edu DPRINTF(I82094AA, "Received interrupt %d.\n", line); 1659124Snilay@cs.wisc.edu assert(line < TableSize); 1669124Snilay@cs.wisc.edu RedirTableEntry entry = redirTable[line]; 1679124Snilay@cs.wisc.edu if (entry.mask) { 1685659Sgblack@eecs.umich.edu DPRINTF(I82094AA, "Entry was masked.\n"); 1699124Snilay@cs.wisc.edu return; 1705659Sgblack@eecs.umich.edu } else { 1715659Sgblack@eecs.umich.edu TriggerIntMessage message = 0; 1727811Ssteve.reinhardt@amd.com message.destination = entry.dest; 173 if (entry.deliveryMode == DeliveryMode::ExtInt) { 174 assert(extIntPic); 175 message.vector = extIntPic->getVector(); 176 } else { 177 message.vector = entry.vector; 178 } 179 message.deliveryMode = entry.deliveryMode; 180 message.destMode = entry.destMode; 181 message.level = entry.polarity; 182 message.trigger = entry.trigger; 183 ApicList apics; 184 int numContexts = sys->numContexts(); 185 if (message.destMode == 0) { 186 if (message.deliveryMode == DeliveryMode::LowestPriority) { 187 panic("Lowest priority delivery mode from the " 188 "IO APIC aren't supported in physical " 189 "destination mode.\n"); 190 } 191 if (message.destination == 0xFF) { 192 for (int i = 0; i < numContexts; i++) { 193 apics.push_back(i); 194 } 195 } else { 196 apics.push_back(message.destination); 197 } 198 } else { 199 for (int i = 0; i < numContexts; i++) { 200 Interrupts *localApic = sys->getThreadContext(i)-> 201 getCpuPtr()->getInterruptController(); 202 if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) & 203 message.destination) { 204 apics.push_back(localApic->getInitialApicId()); 205 } 206 } 207 if (message.deliveryMode == DeliveryMode::LowestPriority && 208 apics.size()) { 209 // The manual seems to suggest that the chipset just does 210 // something reasonable for these instead of actually using 211 // state from the local APIC. We'll just rotate an offset 212 // through the set of APICs selected above. 213 uint64_t modOffset = lowestPriorityOffset % apics.size(); 214 lowestPriorityOffset++; 215 ApicList::iterator apicIt = apics.begin(); 216 while (modOffset--) { 217 apicIt++; 218 assert(apicIt != apics.end()); 219 } 220 int selected = *apicIt; 221 apics.clear(); 222 apics.push_back(selected); 223 } 224 } 225 intMasterPort.sendMessage(apics, message, sys->isTimingMode()); 226 } 227} 228 229void 230X86ISA::I82094AA::raiseInterruptPin(int number) 231{ 232 assert(number < TableSize); 233 if (!pinStates[number]) 234 signalInterrupt(number); 235 pinStates[number] = true; 236} 237 238void 239X86ISA::I82094AA::lowerInterruptPin(int number) 240{ 241 assert(number < TableSize); 242 pinStates[number] = false; 243} 244 245void 246X86ISA::I82094AA::serialize(std::ostream &os) 247{ 248 uint64_t* redirTableArray = (uint64_t*)redirTable; 249 SERIALIZE_SCALAR(regSel); 250 SERIALIZE_SCALAR(initialApicId); 251 SERIALIZE_SCALAR(id); 252 SERIALIZE_SCALAR(arbId); 253 SERIALIZE_SCALAR(lowestPriorityOffset); 254 SERIALIZE_ARRAY(redirTableArray, TableSize); 255 SERIALIZE_ARRAY(pinStates, TableSize); 256} 257 258void 259X86ISA::I82094AA::unserialize(Checkpoint *cp, const std::string §ion) 260{ 261 uint64_t redirTableArray[TableSize]; 262 UNSERIALIZE_SCALAR(regSel); 263 UNSERIALIZE_SCALAR(initialApicId); 264 UNSERIALIZE_SCALAR(id); 265 UNSERIALIZE_SCALAR(arbId); 266 UNSERIALIZE_SCALAR(lowestPriorityOffset); 267 UNSERIALIZE_ARRAY(redirTableArray, TableSize); 268 UNSERIALIZE_ARRAY(pinStates, TableSize); 269 for (int i = 0; i < TableSize; i++) { 270 redirTable[i] = (RedirTableEntry)redirTableArray[i]; 271 } 272} 273 274X86ISA::I82094AA * 275I82094AAParams::create() 276{ 277 return new X86ISA::I82094AA(this); 278} 279