i82094aa.cc revision 11793
111723Sar4jc@virginia.edu/* 211723Sar4jc@virginia.edu * Copyright (c) 2008 The Regents of The University of Michigan 311723Sar4jc@virginia.edu * All rights reserved. 412808Srobert.scheffel1@tu-dresden.de * 511723Sar4jc@virginia.edu * Redistribution and use in source and binary forms, with or without 611723Sar4jc@virginia.edu * modification, are permitted provided that the following conditions are 711723Sar4jc@virginia.edu * met: redistributions of source code must retain the above copyright 811723Sar4jc@virginia.edu * notice, this list of conditions and the following disclaimer; 911723Sar4jc@virginia.edu * redistributions in binary form must reproduce the above copyright 1011723Sar4jc@virginia.edu * notice, this list of conditions and the following disclaimer in the 1111723Sar4jc@virginia.edu * documentation and/or other materials provided with the distribution; 1211723Sar4jc@virginia.edu * neither the name of the copyright holders nor the names of its 1311723Sar4jc@virginia.edu * contributors may be used to endorse or promote products derived from 1411723Sar4jc@virginia.edu * this software without specific prior written permission. 1511723Sar4jc@virginia.edu * 1611723Sar4jc@virginia.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1711723Sar4jc@virginia.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1811723Sar4jc@virginia.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1911723Sar4jc@virginia.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2011723Sar4jc@virginia.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2111723Sar4jc@virginia.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2211723Sar4jc@virginia.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2311723Sar4jc@virginia.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2411723Sar4jc@virginia.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2511723Sar4jc@virginia.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2611723Sar4jc@virginia.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2711723Sar4jc@virginia.edu * 2811723Sar4jc@virginia.edu * Authors: Gabe Black 2911723Sar4jc@virginia.edu */ 3011723Sar4jc@virginia.edu 3112808Srobert.scheffel1@tu-dresden.de#include "dev/x86/i82094aa.hh" 3211723Sar4jc@virginia.edu 3311723Sar4jc@virginia.edu#include "arch/x86/interrupts.hh" 3411723Sar4jc@virginia.edu#include "arch/x86/intmessage.hh" 3511723Sar4jc@virginia.edu#include "cpu/base.hh" 3611723Sar4jc@virginia.edu#include "debug/I82094AA.hh" 3711723Sar4jc@virginia.edu#include "dev/x86/i8259.hh" 3811723Sar4jc@virginia.edu#include "mem/packet.hh" 3912848Sar4jc@virginia.edu#include "mem/packet_access.hh" 4011723Sar4jc@virginia.edu#include "sim/system.hh" 4111723Sar4jc@virginia.edu 4211723Sar4jc@virginia.eduX86ISA::I82094AA::I82094AA(Params *p) 4311723Sar4jc@virginia.edu : BasicPioDevice(p, 20), IntDevice(this, p->int_latency), 4411723Sar4jc@virginia.edu extIntPic(p->external_int_pic), lowestPriorityOffset(0) 4511723Sar4jc@virginia.edu{ 4612848Sar4jc@virginia.edu // This assumes there's only one I/O APIC in the system and since the apic 4712848Sar4jc@virginia.edu // id is stored in a 8-bit field with 0xff meaning broadcast, the id must 4812848Sar4jc@virginia.edu // be less than 0xff 4912848Sar4jc@virginia.edu 5012848Sar4jc@virginia.edu assert(p->apic_id < 0xff); 5112848Sar4jc@virginia.edu initialApicId = id = p->apic_id; 5212848Sar4jc@virginia.edu arbId = id; 5311725Sar4jc@virginia.edu regSel = 0; 5412848Sar4jc@virginia.edu RedirTableEntry entry = 0; 5511723Sar4jc@virginia.edu entry.mask = 1; 5611723Sar4jc@virginia.edu for (int i = 0; i < TableSize; i++) { 5711723Sar4jc@virginia.edu redirTable[i] = entry; 5811723Sar4jc@virginia.edu pinStates[i] = false; 5911723Sar4jc@virginia.edu } 6011723Sar4jc@virginia.edu} 6111723Sar4jc@virginia.edu 6211723Sar4jc@virginia.eduvoid 6311723Sar4jc@virginia.eduX86ISA::I82094AA::init() 6411723Sar4jc@virginia.edu{ 6511723Sar4jc@virginia.edu // The io apic must register its address ranges on both its pio port 6611723Sar4jc@virginia.edu // via the piodevice init() function and its int port that it inherited 6712848Sar4jc@virginia.edu // from IntDevice. Note IntDevice is not a SimObject itself. 6812848Sar4jc@virginia.edu 6912848Sar4jc@virginia.edu BasicPioDevice::init(); 7012848Sar4jc@virginia.edu IntDevice::init(); 7112848Sar4jc@virginia.edu} 7211723Sar4jc@virginia.edu 7311723Sar4jc@virginia.eduBaseMasterPort & 7412848Sar4jc@virginia.eduX86ISA::I82094AA::getMasterPort(const std::string &if_name, PortID idx) 7512848Sar4jc@virginia.edu{ 7612848Sar4jc@virginia.edu if (if_name == "int_master") 7712848Sar4jc@virginia.edu return intMasterPort; 7812848Sar4jc@virginia.edu return BasicPioDevice::getMasterPort(if_name, idx); 7912848Sar4jc@virginia.edu} 8012848Sar4jc@virginia.edu 8112848Sar4jc@virginia.eduAddrRangeList 8212848Sar4jc@virginia.eduX86ISA::I82094AA::getIntAddrRange() const 8312848Sar4jc@virginia.edu{ 8412848Sar4jc@virginia.edu AddrRangeList ranges; 8512848Sar4jc@virginia.edu ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0), 8612848Sar4jc@virginia.edu x86InterruptAddress(initialApicId, 0) + 8712848Sar4jc@virginia.edu PhysAddrAPICRangeSize)); 8812848Sar4jc@virginia.edu return ranges; 8912848Sar4jc@virginia.edu} 9012848Sar4jc@virginia.edu 9112848Sar4jc@virginia.eduTick 9212848Sar4jc@virginia.eduX86ISA::I82094AA::recvResponse(PacketPtr pkt) 9312848Sar4jc@virginia.edu{ 9412848Sar4jc@virginia.edu // Packet instantiated calling sendMessage() in signalInterrupt() 9512848Sar4jc@virginia.edu delete pkt->req; 9612848Sar4jc@virginia.edu delete pkt; 9712848Sar4jc@virginia.edu return 0; 9812848Sar4jc@virginia.edu} 9912848Sar4jc@virginia.edu 10012848Sar4jc@virginia.eduTick 10112848Sar4jc@virginia.eduX86ISA::I82094AA::read(PacketPtr pkt) 10212848Sar4jc@virginia.edu{ 10312848Sar4jc@virginia.edu assert(pkt->getSize() == 4); 10412848Sar4jc@virginia.edu Addr offset = pkt->getAddr() - pioAddr; 10512848Sar4jc@virginia.edu switch(offset) { 10612848Sar4jc@virginia.edu case 0: 10712848Sar4jc@virginia.edu pkt->set<uint32_t>(regSel); 10812848Sar4jc@virginia.edu break; 10912848Sar4jc@virginia.edu case 16: 11012848Sar4jc@virginia.edu pkt->set<uint32_t>(readReg(regSel)); 11112848Sar4jc@virginia.edu break; 11212848Sar4jc@virginia.edu default: 11312848Sar4jc@virginia.edu panic("Illegal read from I/O APIC.\n"); 11412848Sar4jc@virginia.edu } 11512848Sar4jc@virginia.edu pkt->makeAtomicResponse(); 11612848Sar4jc@virginia.edu return pioDelay; 11712848Sar4jc@virginia.edu} 11812848Sar4jc@virginia.edu 11912848Sar4jc@virginia.eduTick 12011723Sar4jc@virginia.eduX86ISA::I82094AA::write(PacketPtr pkt) 12111723Sar4jc@virginia.edu{ 12211723Sar4jc@virginia.edu assert(pkt->getSize() == 4); 12311723Sar4jc@virginia.edu Addr offset = pkt->getAddr() - pioAddr; 12411723Sar4jc@virginia.edu switch(offset) { 12512848Sar4jc@virginia.edu case 0: 12611723Sar4jc@virginia.edu regSel = pkt->get<uint32_t>(); 12711723Sar4jc@virginia.edu break; 12812848Sar4jc@virginia.edu case 16: 12912848Sar4jc@virginia.edu writeReg(regSel, pkt->get<uint32_t>()); 13011723Sar4jc@virginia.edu break; 13111723Sar4jc@virginia.edu default: 13212849Sar4jc@virginia.edu panic("Illegal write to I/O APIC.\n"); 13312848Sar4jc@virginia.edu } 13412848Sar4jc@virginia.edu pkt->makeAtomicResponse(); 13512849Sar4jc@virginia.edu return pioDelay; 13611723Sar4jc@virginia.edu} 13712848Sar4jc@virginia.edu 13812848Sar4jc@virginia.eduvoid 13911723Sar4jc@virginia.eduX86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value) 14011723Sar4jc@virginia.edu{ 14112808Srobert.scheffel1@tu-dresden.de if (offset == 0x0) { 14212808Srobert.scheffel1@tu-dresden.de id = bits(value, 31, 24); 14312808Srobert.scheffel1@tu-dresden.de } else if (offset == 0x1) { 14412808Srobert.scheffel1@tu-dresden.de // The IOAPICVER register is read only. 14512808Srobert.scheffel1@tu-dresden.de } else if (offset == 0x2) { 14612808Srobert.scheffel1@tu-dresden.de arbId = bits(value, 31, 24); 14712808Srobert.scheffel1@tu-dresden.de } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 14812808Srobert.scheffel1@tu-dresden.de int index = (offset - 0x10) / 2; 14912808Srobert.scheffel1@tu-dresden.de if (offset % 2) { 15012808Srobert.scheffel1@tu-dresden.de redirTable[index].topDW = value; 15112808Srobert.scheffel1@tu-dresden.de redirTable[index].topReserved = 0; 15212808Srobert.scheffel1@tu-dresden.de } else { 15312808Srobert.scheffel1@tu-dresden.de redirTable[index].bottomDW = value; 15412808Srobert.scheffel1@tu-dresden.de redirTable[index].bottomReserved = 0; 15512808Srobert.scheffel1@tu-dresden.de } 15612808Srobert.scheffel1@tu-dresden.de } else { 15712808Srobert.scheffel1@tu-dresden.de warn("Access to undefined I/O APIC register %#x.\n", offset); 15812808Srobert.scheffel1@tu-dresden.de } 15912808Srobert.scheffel1@tu-dresden.de DPRINTF(I82094AA, 16012808Srobert.scheffel1@tu-dresden.de "Wrote %#x to I/O APIC register %#x .\n", value, offset); 16112808Srobert.scheffel1@tu-dresden.de} 16211723Sar4jc@virginia.edu 16312849Sar4jc@virginia.eduuint32_t 16412849Sar4jc@virginia.eduX86ISA::I82094AA::readReg(uint8_t offset) 16512849Sar4jc@virginia.edu{ 16612849Sar4jc@virginia.edu uint32_t result = 0; 16712849Sar4jc@virginia.edu if (offset == 0x0) { 16812849Sar4jc@virginia.edu result = id << 24; 16912849Sar4jc@virginia.edu } else if (offset == 0x1) { 17012849Sar4jc@virginia.edu result = ((TableSize - 1) << 16) | APICVersion; 17112849Sar4jc@virginia.edu } else if (offset == 0x2) { 17212849Sar4jc@virginia.edu result = arbId << 24; 17312849Sar4jc@virginia.edu } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 17412849Sar4jc@virginia.edu int index = (offset - 0x10) / 2; 17512849Sar4jc@virginia.edu if (offset % 2) { 17612849Sar4jc@virginia.edu result = redirTable[index].topDW; 17711723Sar4jc@virginia.edu } else { 17811723Sar4jc@virginia.edu result = redirTable[index].bottomDW; 17912849Sar4jc@virginia.edu } 18012849Sar4jc@virginia.edu } else { 18111723Sar4jc@virginia.edu warn("Access to undefined I/O APIC register %#x.\n", offset); 18211723Sar4jc@virginia.edu } 18312848Sar4jc@virginia.edu DPRINTF(I82094AA, 18411723Sar4jc@virginia.edu "Read %#x from I/O APIC register %#x.\n", result, offset); 18511723Sar4jc@virginia.edu return result; 18612849Sar4jc@virginia.edu} 18712136Sar4jc@virginia.edu 18812136Sar4jc@virginia.eduvoid 18912136Sar4jc@virginia.eduX86ISA::I82094AA::signalInterrupt(int line) 19012848Sar4jc@virginia.edu{ 19112136Sar4jc@virginia.edu DPRINTF(I82094AA, "Received interrupt %d.\n", line); 19212849Sar4jc@virginia.edu assert(line < TableSize); 19312849Sar4jc@virginia.edu RedirTableEntry entry = redirTable[line]; 19412136Sar4jc@virginia.edu if (entry.mask) { 19512136Sar4jc@virginia.edu DPRINTF(I82094AA, "Entry was masked.\n"); 19612848Sar4jc@virginia.edu return; 19712136Sar4jc@virginia.edu } else { 19812136Sar4jc@virginia.edu TriggerIntMessage message = 0; 19912849Sar4jc@virginia.edu message.destination = entry.dest; 20011723Sar4jc@virginia.edu if (entry.deliveryMode == DeliveryMode::ExtInt) { 20111723Sar4jc@virginia.edu assert(extIntPic); 20211723Sar4jc@virginia.edu message.vector = extIntPic->getVector(); 20312848Sar4jc@virginia.edu } else { 20411723Sar4jc@virginia.edu message.vector = entry.vector; 20512849Sar4jc@virginia.edu } 20612849Sar4jc@virginia.edu message.deliveryMode = entry.deliveryMode; 20712848Sar4jc@virginia.edu message.destMode = entry.destMode; 20811723Sar4jc@virginia.edu message.level = entry.polarity; 20911723Sar4jc@virginia.edu message.trigger = entry.trigger; 21012848Sar4jc@virginia.edu ApicList apics; 21111723Sar4jc@virginia.edu int numContexts = sys->numContexts(); 21211723Sar4jc@virginia.edu if (message.destMode == 0) { 21312849Sar4jc@virginia.edu if (message.deliveryMode == DeliveryMode::LowestPriority) { 21411725Sar4jc@virginia.edu panic("Lowest priority delivery mode from the " 21511725Sar4jc@virginia.edu "IO APIC aren't supported in physical " 21611725Sar4jc@virginia.edu "destination mode.\n"); 21712848Sar4jc@virginia.edu } 21811725Sar4jc@virginia.edu if (message.destination == 0xFF) { 21912849Sar4jc@virginia.edu for (int i = 0; i < numContexts; i++) { 22012849Sar4jc@virginia.edu apics.push_back(i); 22112848Sar4jc@virginia.edu } 22211725Sar4jc@virginia.edu } else { 22311725Sar4jc@virginia.edu apics.push_back(message.destination); 22412848Sar4jc@virginia.edu } 22511725Sar4jc@virginia.edu } else { 22611725Sar4jc@virginia.edu for (int i = 0; i < numContexts; i++) { 22712849Sar4jc@virginia.edu Interrupts *localApic = sys->getThreadContext(i)-> 22812849Sar4jc@virginia.edu getCpuPtr()->getInterruptController(0); 22912849Sar4jc@virginia.edu if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) & 23012849Sar4jc@virginia.edu message.destination) { 23112849Sar4jc@virginia.edu apics.push_back(localApic->getInitialApicId()); 23212849Sar4jc@virginia.edu } 23312849Sar4jc@virginia.edu } 23412849Sar4jc@virginia.edu if (message.deliveryMode == DeliveryMode::LowestPriority && 23512849Sar4jc@virginia.edu apics.size()) { 23612849Sar4jc@virginia.edu // The manual seems to suggest that the chipset just does 23712849Sar4jc@virginia.edu // something reasonable for these instead of actually using 23812849Sar4jc@virginia.edu // state from the local APIC. We'll just rotate an offset 23912849Sar4jc@virginia.edu // through the set of APICs selected above. 24011723Sar4jc@virginia.edu uint64_t modOffset = lowestPriorityOffset % apics.size(); 24111723Sar4jc@virginia.edu lowestPriorityOffset++; 24212849Sar4jc@virginia.edu ApicList::iterator apicIt = apics.begin(); 24312849Sar4jc@virginia.edu while (modOffset--) { 24412849Sar4jc@virginia.edu apicIt++; 24511723Sar4jc@virginia.edu assert(apicIt != apics.end()); 24612849Sar4jc@virginia.edu } 24712849Sar4jc@virginia.edu int selected = *apicIt; 24812849Sar4jc@virginia.edu apics.clear(); 24912849Sar4jc@virginia.edu apics.push_back(selected); 25012849Sar4jc@virginia.edu } 25112848Sar4jc@virginia.edu } 25211723Sar4jc@virginia.edu intMasterPort.sendMessage(apics, message, sys->isTimingMode()); 25311723Sar4jc@virginia.edu } 25411723Sar4jc@virginia.edu} 25511723Sar4jc@virginia.edu 25611723Sar4jc@virginia.eduvoid 25711723Sar4jc@virginia.eduX86ISA::I82094AA::raiseInterruptPin(int number) 25811723Sar4jc@virginia.edu{ 25912848Sar4jc@virginia.edu assert(number < TableSize); 26012848Sar4jc@virginia.edu if (!pinStates[number]) 26111723Sar4jc@virginia.edu signalInterrupt(number); 26211723Sar4jc@virginia.edu pinStates[number] = true; 26311723Sar4jc@virginia.edu} 26411723Sar4jc@virginia.edu 26512849Sar4jc@virginia.eduvoid 266X86ISA::I82094AA::lowerInterruptPin(int number) 267{ 268 assert(number < TableSize); 269 pinStates[number] = false; 270} 271 272void 273X86ISA::I82094AA::serialize(CheckpointOut &cp) const 274{ 275 uint64_t* redirTableArray = (uint64_t*)redirTable; 276 SERIALIZE_SCALAR(regSel); 277 SERIALIZE_SCALAR(initialApicId); 278 SERIALIZE_SCALAR(id); 279 SERIALIZE_SCALAR(arbId); 280 SERIALIZE_SCALAR(lowestPriorityOffset); 281 SERIALIZE_ARRAY(redirTableArray, TableSize); 282 SERIALIZE_ARRAY(pinStates, TableSize); 283} 284 285void 286X86ISA::I82094AA::unserialize(CheckpointIn &cp) 287{ 288 uint64_t redirTableArray[TableSize]; 289 UNSERIALIZE_SCALAR(regSel); 290 UNSERIALIZE_SCALAR(initialApicId); 291 UNSERIALIZE_SCALAR(id); 292 UNSERIALIZE_SCALAR(arbId); 293 UNSERIALIZE_SCALAR(lowestPriorityOffset); 294 UNSERIALIZE_ARRAY(redirTableArray, TableSize); 295 UNSERIALIZE_ARRAY(pinStates, TableSize); 296 for (int i = 0; i < TableSize; i++) { 297 redirTable[i] = (RedirTableEntry)redirTableArray[i]; 298 } 299} 300 301X86ISA::I82094AA * 302I82094AAParams::create() 303{ 304 return new X86ISA::I82094AA(this); 305} 306