i82094aa.cc revision 5657:7539092b28ac
13536SN/A/* 27752SWilliam.Wang@arm.com * Copyright (c) 2008 The Regents of The University of Michigan 37752SWilliam.Wang@arm.com * All rights reserved. 47752SWilliam.Wang@arm.com * 57752SWilliam.Wang@arm.com * Redistribution and use in source and binary forms, with or without 67752SWilliam.Wang@arm.com * modification, are permitted provided that the following conditions are 77752SWilliam.Wang@arm.com * met: redistributions of source code must retain the above copyright 87752SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer; 97752SWilliam.Wang@arm.com * redistributions in binary form must reproduce the above copyright 107752SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer in the 117752SWilliam.Wang@arm.com * documentation and/or other materials provided with the distribution; 127752SWilliam.Wang@arm.com * neither the name of the copyright holders nor the names of its 137752SWilliam.Wang@arm.com * contributors may be used to endorse or promote products derived from 143536SN/A * this software without specific prior written permission. 153536SN/A * 163536SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173536SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183536SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193536SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203536SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213536SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223536SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233536SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243536SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253536SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263536SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273536SN/A * 283536SN/A * Authors: Gabe Black 293536SN/A */ 303536SN/A 313536SN/A#include "arch/x86/intmessage.hh" 323536SN/A#include "dev/x86/i82094aa.hh" 333536SN/A#include "dev/x86/i8259.hh" 343536SN/A#include "mem/packet.hh" 353536SN/A#include "mem/packet_access.hh" 363536SN/A#include "sim/system.hh" 373536SN/A 383536SN/AX86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), 393536SN/A latency(p->pio_latency), pioAddr(p->pio_addr), extIntPic(NULL) 403536SN/A{ 417752SWilliam.Wang@arm.com // This assumes there's only one I/O APIC in the system 423536SN/A id = sys->getNumCPUs(); 433536SN/A assert(id <= 0xf); 443536SN/A arbId = id; 453536SN/A regSel = 0; 465543SN/A RedirTableEntry entry = 0; 473536SN/A entry.mask = 1; 483536SN/A for (int i = 0; i < TableSize; i++) { 493536SN/A redirTable[i] = entry; 503536SN/A } 513536SN/A} 523536SN/A 533536SN/ATick 545543SN/AX86ISA::I82094AA::read(PacketPtr pkt) 555543SN/A{ 563536SN/A assert(pkt->getSize() == 4); 573536SN/A Addr offset = pkt->getAddr() - pioAddr; 583536SN/A switch(offset) { 593536SN/A case 0: 603536SN/A pkt->set<uint32_t>(regSel); 613536SN/A break; 623536SN/A case 16: 633536SN/A pkt->set<uint32_t>(readReg(regSel)); 643536SN/A break; 653536SN/A default: 663536SN/A panic("Illegal read from I/O APIC.\n"); 675543SN/A } 685543SN/A return latency; 693536SN/A} 703536SN/A 713536SN/ATick 723536SN/AX86ISA::I82094AA::write(PacketPtr pkt) 733536SN/A{ 743536SN/A assert(pkt->getSize() == 4); 753536SN/A Addr offset = pkt->getAddr() - pioAddr; 763536SN/A switch(offset) { 773536SN/A case 0: 783536SN/A regSel = pkt->get<uint32_t>(); 793536SN/A break; 803536SN/A case 16: 813536SN/A writeReg(regSel, pkt->get<uint32_t>()); 823536SN/A break; 833536SN/A default: 843536SN/A panic("Illegal write to I/O APIC.\n"); 855543SN/A } 863536SN/A return latency; 873536SN/A} 883536SN/A 893536SN/Avoid 903536SN/AX86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value) 913536SN/A{ 923536SN/A if (offset == 0x0) { 933536SN/A id = bits(value, 27, 24); 943536SN/A } else if (offset == 0x1) { 953536SN/A // The IOAPICVER register is read only. 963536SN/A } else if (offset == 0x2) { 973536SN/A arbId = bits(value, 27, 24); 983536SN/A } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 993536SN/A int index = (offset - 0x10) / 2; 1003536SN/A if (offset % 2) { 1013536SN/A redirTable[index].topDW = value; 1023536SN/A redirTable[index].topReserved = 0; 1033536SN/A } else { 1043536SN/A redirTable[index].bottomDW = value; 1055543SN/A redirTable[index].bottomReserved = 0; 1065543SN/A } 1073536SN/A } else { 1083536SN/A warn("Access to undefined I/O APIC register %#x.\n", offset); 1093536SN/A } 1103536SN/A DPRINTF(I82094AA, 1113536SN/A "Wrote %#x to I/O APIC register %#x .\n", value, offset); 1123536SN/A} 1133536SN/A 1143536SN/Auint32_t 1153536SN/AX86ISA::I82094AA::readReg(uint8_t offset) 1163536SN/A{ 1173536SN/A uint32_t result = 0; 1183536SN/A if (offset == 0x0) { 1193536SN/A result = id << 24; 1203536SN/A } else if (offset == 0x1) { 1213536SN/A result = ((TableSize - 1) << 16) | APICVersion; 1223536SN/A } else if (offset == 0x2) { 1233536SN/A result = arbId << 24; 1243536SN/A } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { 1253536SN/A int index = (offset - 0x10) / 2; 1263536SN/A if (offset % 2) { 1273536SN/A result = redirTable[index].topDW; 1283536SN/A } else { 1293536SN/A result = redirTable[index].bottomDW; 1303536SN/A } 1313536SN/A } else { 1323536SN/A warn("Access to undefined I/O APIC register %#x.\n", offset); 1335569SN/A } 1343536SN/A DPRINTF(I82094AA, 1353536SN/A "Read %#x from I/O APIC register %#x.\n", result, offset); 1363536SN/A return result; 1373961SN/A} 1383961SN/A 1397752SWilliam.Wang@arm.comvoid 1403961SN/AX86ISA::I82094AA::signalInterrupt(int line) 1413961SN/A{ 1428229Snate@binkert.org DPRINTF(I82094AA, "Received interrupt %d.\n", line); 1438229Snate@binkert.org assert(line < TableSize); 1448229Snate@binkert.org RedirTableEntry entry = redirTable[line]; 1457752SWilliam.Wang@arm.com if (entry.mask) { 1467752SWilliam.Wang@arm.com DPRINTF(I82094AA, "Entry was masked.\n"); 1473536SN/A return; 1483536SN/A } else { 1493536SN/A TriggerIntMessage message; 1503536SN/A message.destination = entry.dest; 1518229Snate@binkert.org if (entry.deliveryMode == DeliveryMode::ExtInt) { 1523536SN/A assert(extIntPic); 1537752SWilliam.Wang@arm.com message.vector = extIntPic->getVector(); 1548232Snate@binkert.org } else { 1558232Snate@binkert.org message.vector = entry.vector; 1568229Snate@binkert.org } 1573536SN/A message.deliveryMode = entry.deliveryMode; 1583536SN/A message.destMode = entry.destMode; 1593536SN/A message.level = entry.polarity; 1603536SN/A message.trigger = entry.trigger; 1613536SN/A 1627752SWilliam.Wang@arm.com if (DeliveryMode::isReserved(entry.deliveryMode)) { 1633536SN/A fatal("Tried to use reserved delivery mode " 1645569SN/A "for IO APIC entry %d.\n", line); 1657752SWilliam.Wang@arm.com } else if (DTRACE(I82094AA)) { 1663536SN/A DPRINTF(I82094AA, "Delivery mode is: %s.\n", 1673536SN/A DeliveryMode::names[entry.deliveryMode]); 1683536SN/A DPRINTF(I82094AA, "Vector is %#x.\n", message.vector); 1695569SN/A } 1705569SN/A 1715569SN/A if (entry.destMode == 0) { 1723536SN/A DPRINTF(I82094AA, 1733536SN/A "Sending interrupt to APIC ID %d.\n", entry.dest); 1743536SN/A PacketPtr pkt = buildIntRequest(entry.dest, message); 1757752SWilliam.Wang@arm.com if (sys->getMemoryMode() == Enums::timing) 1763536SN/A intPort->sendMessageTiming(pkt, latency); 1777752SWilliam.Wang@arm.com else if (sys->getMemoryMode() == Enums::atomic) 1787752SWilliam.Wang@arm.com intPort->sendMessageAtomic(pkt); 1793536SN/A else 1803536SN/A panic("Unrecognized memory mode.\n"); 1817752SWilliam.Wang@arm.com } else { 1823536SN/A DPRINTF(I82094AA, "Sending interrupts to APIC IDs:" 1833536SN/A "%s%s%s%s%s%s%s%s\n", 1845568SN/A bits((int)entry.dest, 0) ? " 0": "", 1853536SN/A bits((int)entry.dest, 1) ? " 1": "", 1863536SN/A bits((int)entry.dest, 2) ? " 2": "", 1873536SN/A bits((int)entry.dest, 3) ? " 3": "", 1883536SN/A bits((int)entry.dest, 4) ? " 4": "", 1897752SWilliam.Wang@arm.com bits((int)entry.dest, 5) ? " 5": "", 1907752SWilliam.Wang@arm.com bits((int)entry.dest, 6) ? " 6": "", 1917752SWilliam.Wang@arm.com bits((int)entry.dest, 7) ? " 7": "" 1927752SWilliam.Wang@arm.com ); 1937752SWilliam.Wang@arm.com uint8_t dests = entry.dest; 1947752SWilliam.Wang@arm.com uint8_t id = 0; 1957752SWilliam.Wang@arm.com while(dests) { 1963961SN/A if (dests & 0x1) { 1973536SN/A PacketPtr pkt = buildIntRequest(id, message); 1983536SN/A if (sys->getMemoryMode() == Enums::timing) 1995569SN/A intPort->sendMessageTiming(pkt, latency); 2005569SN/A else if (sys->getMemoryMode() == Enums::atomic) 2015569SN/A intPort->sendMessageAtomic(pkt); 2025569SN/A else 2033536SN/A panic("Unrecognized memory mode.\n"); 2043536SN/A } 2053536SN/A dests >>= 1; 2067752SWilliam.Wang@arm.com id++; 2077752SWilliam.Wang@arm.com } 2083579SN/A } 2093536SN/A } 2107752SWilliam.Wang@arm.com} 2117752SWilliam.Wang@arm.com 2127752SWilliam.Wang@arm.comX86ISA::I82094AA * 2137752SWilliam.Wang@arm.comI82094AAParams::create() 2147752SWilliam.Wang@arm.com{ 2157752SWilliam.Wang@arm.com return new X86ISA::I82094AA(this); 2167752SWilliam.Wang@arm.com} 2177752SWilliam.Wang@arm.com