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