i82094aa.cc revision 5654
15703SN/A/*
25703SN/A * Copyright (c) 2008 The Regents of The University of Michigan
39348SAli.Saidi@ARM.com * All rights reserved.
49348SAli.Saidi@ARM.com *
59348SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
65703SN/A * modification, are permitted provided that the following conditions are
79348SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
89348SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
99348SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
109348SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
119348SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
129348SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
139348SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
149348SAli.Saidi@ARM.com * this software without specific prior written permission.
159348SAli.Saidi@ARM.com *
169348SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179348SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189348SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199348SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209348SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219348SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229348SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239348SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249348SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259348SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269348SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279348SAli.Saidi@ARM.com *
289348SAli.Saidi@ARM.com * Authors: Gabe Black
299348SAli.Saidi@ARM.com */
309348SAli.Saidi@ARM.com
319348SAli.Saidi@ARM.com#include "arch/x86/intmessage.hh"
329348SAli.Saidi@ARM.com#include "dev/x86/i82094aa.hh"
339348SAli.Saidi@ARM.com#include "mem/packet.hh"
349348SAli.Saidi@ARM.com#include "mem/packet_access.hh"
359348SAli.Saidi@ARM.com#include "sim/system.hh"
369348SAli.Saidi@ARM.com
379348SAli.Saidi@ARM.comX86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this),
389348SAli.Saidi@ARM.com   latency(p->pio_latency), pioAddr(p->pio_addr)
399348SAli.Saidi@ARM.com{
409348SAli.Saidi@ARM.com    // This assumes there's only one I/O APIC in the system
419348SAli.Saidi@ARM.com    id = sys->getNumCPUs();
429348SAli.Saidi@ARM.com    assert(id <= 0xf);
439348SAli.Saidi@ARM.com    arbId = id;
449348SAli.Saidi@ARM.com    regSel = 0;
459348SAli.Saidi@ARM.com    RedirTableEntry entry = 0;
469348SAli.Saidi@ARM.com    entry.mask = 1;
479348SAli.Saidi@ARM.com    for (int i = 0; i < TableSize; i++) {
489348SAli.Saidi@ARM.com        redirTable[i] = entry;
499348SAli.Saidi@ARM.com    }
509348SAli.Saidi@ARM.com}
519348SAli.Saidi@ARM.com
529348SAli.Saidi@ARM.comTick
539348SAli.Saidi@ARM.comX86ISA::I82094AA::read(PacketPtr pkt)
549348SAli.Saidi@ARM.com{
559348SAli.Saidi@ARM.com    assert(pkt->getSize() == 4);
569348SAli.Saidi@ARM.com    Addr offset = pkt->getAddr() - pioAddr;
579348SAli.Saidi@ARM.com    switch(offset) {
589348SAli.Saidi@ARM.com      case 0:
599348SAli.Saidi@ARM.com        pkt->set<uint32_t>(regSel);
609348SAli.Saidi@ARM.com        break;
619348SAli.Saidi@ARM.com      case 16:
629348SAli.Saidi@ARM.com        pkt->set<uint32_t>(readReg(regSel));
639348SAli.Saidi@ARM.com        break;
649348SAli.Saidi@ARM.com      default:
659348SAli.Saidi@ARM.com        panic("Illegal read from I/O APIC.\n");
669348SAli.Saidi@ARM.com    }
679348SAli.Saidi@ARM.com    return latency;
689348SAli.Saidi@ARM.com}
699348SAli.Saidi@ARM.com
709348SAli.Saidi@ARM.comTick
719348SAli.Saidi@ARM.comX86ISA::I82094AA::write(PacketPtr pkt)
729348SAli.Saidi@ARM.com{
739348SAli.Saidi@ARM.com    assert(pkt->getSize() == 4);
749348SAli.Saidi@ARM.com    Addr offset = pkt->getAddr() - pioAddr;
759348SAli.Saidi@ARM.com    switch(offset) {
769348SAli.Saidi@ARM.com      case 0:
779348SAli.Saidi@ARM.com        regSel = pkt->get<uint32_t>();
789348SAli.Saidi@ARM.com        break;
799348SAli.Saidi@ARM.com      case 16:
809348SAli.Saidi@ARM.com        writeReg(regSel, pkt->get<uint32_t>());
819348SAli.Saidi@ARM.com        break;
829348SAli.Saidi@ARM.com      default:
839348SAli.Saidi@ARM.com        panic("Illegal write to I/O APIC.\n");
849348SAli.Saidi@ARM.com    }
859348SAli.Saidi@ARM.com    return latency;
869348SAli.Saidi@ARM.com}
879348SAli.Saidi@ARM.com
889348SAli.Saidi@ARM.comvoid
899348SAli.Saidi@ARM.comX86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value)
909348SAli.Saidi@ARM.com{
919348SAli.Saidi@ARM.com    if (offset == 0x0) {
929312Sandreas.hansson@arm.com        id = bits(value, 27, 24);
939348SAli.Saidi@ARM.com    } else if (offset == 0x1) {
949348SAli.Saidi@ARM.com        // The IOAPICVER register is read only.
959312Sandreas.hansson@arm.com    } else if (offset == 0x2) {
969312Sandreas.hansson@arm.com        arbId = bits(value, 27, 24);
979312Sandreas.hansson@arm.com    } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
989312Sandreas.hansson@arm.com        int index = (offset - 0x10) / 2;
999312Sandreas.hansson@arm.com        if (offset % 2) {
1009312Sandreas.hansson@arm.com            redirTable[index].topDW = value;
1019348SAli.Saidi@ARM.com            redirTable[index].topReserved = 0;
1029312Sandreas.hansson@arm.com        } else {
1039312Sandreas.hansson@arm.com            redirTable[index].bottomDW = value;
1049312Sandreas.hansson@arm.com            redirTable[index].bottomReserved = 0;
1059312Sandreas.hansson@arm.com        }
1069312Sandreas.hansson@arm.com    } else {
1079312Sandreas.hansson@arm.com        warn("Access to undefined I/O APIC register %#x.\n", offset);
1089312Sandreas.hansson@arm.com    }
1099312Sandreas.hansson@arm.com    DPRINTF(I82094AA,
1109348SAli.Saidi@ARM.com            "Wrote %#x to I/O APIC register %#x .\n", value, offset);
1119312Sandreas.hansson@arm.com}
1129312Sandreas.hansson@arm.com
1139312Sandreas.hansson@arm.comuint32_t
1149312Sandreas.hansson@arm.comX86ISA::I82094AA::readReg(uint8_t offset)
1159312Sandreas.hansson@arm.com{
1169312Sandreas.hansson@arm.com    uint32_t result = 0;
1179312Sandreas.hansson@arm.com    if (offset == 0x0) {
1189312Sandreas.hansson@arm.com        result = id << 24;
1199348SAli.Saidi@ARM.com    } else if (offset == 0x1) {
1209312Sandreas.hansson@arm.com        result = ((TableSize - 1) << 16) | APICVersion;
1219312Sandreas.hansson@arm.com    } else if (offset == 0x2) {
1229348SAli.Saidi@ARM.com        result = arbId << 24;
1239348SAli.Saidi@ARM.com    } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
1249348SAli.Saidi@ARM.com        int index = (offset - 0x10) / 2;
1259348SAli.Saidi@ARM.com        if (offset % 2) {
1269348SAli.Saidi@ARM.com            result = redirTable[index].topDW;
1279348SAli.Saidi@ARM.com        } else {
1289348SAli.Saidi@ARM.com            result = redirTable[index].bottomDW;
1299348SAli.Saidi@ARM.com        }
1309348SAli.Saidi@ARM.com    } else {
1319348SAli.Saidi@ARM.com        warn("Access to undefined I/O APIC register %#x.\n", offset);
1329348SAli.Saidi@ARM.com    }
1339348SAli.Saidi@ARM.com    DPRINTF(I82094AA,
1349348SAli.Saidi@ARM.com            "Read %#x from I/O APIC register %#x.\n", result, offset);
1359348SAli.Saidi@ARM.com    return result;
1369314Sandreas.hansson@arm.com}
1379348SAli.Saidi@ARM.com
1389348SAli.Saidi@ARM.comvoid
1399348SAli.Saidi@ARM.comX86ISA::I82094AA::signalInterrupt(int line)
1409348SAli.Saidi@ARM.com{
1419348SAli.Saidi@ARM.com    DPRINTF(I82094AA, "Received interrupt %d.\n", line);
1429348SAli.Saidi@ARM.com    assert(line < TableSize);
1439348SAli.Saidi@ARM.com    RedirTableEntry entry = redirTable[line];
1449312Sandreas.hansson@arm.com    if (entry.mask) {
1459312Sandreas.hansson@arm.com        DPRINTF(I82094AA, "Entry was masked.\n");
1469312Sandreas.hansson@arm.com        return;
1479312Sandreas.hansson@arm.com    } else {
1489312Sandreas.hansson@arm.com        if (DTRACE(I82094AA)) {
1499312Sandreas.hansson@arm.com            if (DeliveryMode::isReserved(entry.deliveryMode)) {
1509312Sandreas.hansson@arm.com                fatal("Tried to use reserved delivery mode "
1519312Sandreas.hansson@arm.com                        "for IO APIC entry %d.\n", line);
1529312Sandreas.hansson@arm.com            } else {
1539312Sandreas.hansson@arm.com                DPRINTF(I82094AA, "Delivery mode is: %s.\n",
1549312Sandreas.hansson@arm.com                        DeliveryMode::names[entry.deliveryMode]);
1559348SAli.Saidi@ARM.com            }
1569348SAli.Saidi@ARM.com            DPRINTF(I82094AA, "Vector is %#x.\n", entry.vector);
1579348SAli.Saidi@ARM.com        }
1589348SAli.Saidi@ARM.com
1599348SAli.Saidi@ARM.com        TriggerIntMessage message;
1609348SAli.Saidi@ARM.com        message.destination = entry.dest;
1619348SAli.Saidi@ARM.com        message.vector = entry.vector;
1629348SAli.Saidi@ARM.com        message.deliveryMode = entry.deliveryMode;
1639348SAli.Saidi@ARM.com        message.destMode = entry.destMode;
1649348SAli.Saidi@ARM.com        message.level = entry.polarity;
1659348SAli.Saidi@ARM.com        message.trigger = entry.trigger;
1669348SAli.Saidi@ARM.com
1679348SAli.Saidi@ARM.com        if (entry.destMode == 0) {
1689348SAli.Saidi@ARM.com            DPRINTF(I82094AA,
1699348SAli.Saidi@ARM.com                    "Sending interrupt to APIC ID %d.\n", entry.dest);
1709348SAli.Saidi@ARM.com            PacketPtr pkt = buildIntRequest(entry.dest, message);
1719348SAli.Saidi@ARM.com            if (sys->getMemoryMode() == Enums::timing)
1729348SAli.Saidi@ARM.com                intPort->sendMessageTiming(pkt, latency);
1739348SAli.Saidi@ARM.com            else if (sys->getMemoryMode() == Enums::atomic)
1749348SAli.Saidi@ARM.com                intPort->sendMessageAtomic(pkt);
1759348SAli.Saidi@ARM.com            else
1769348SAli.Saidi@ARM.com                panic("Unrecognized memory mode.\n");
1779348SAli.Saidi@ARM.com        } else {
1789348SAli.Saidi@ARM.com            DPRINTF(I82094AA, "Sending interrupts to APIC IDs:"
1799348SAli.Saidi@ARM.com                    "%s%s%s%s%s%s%s%s\n",
1809348SAli.Saidi@ARM.com                    bits((int)entry.dest, 0) ? " 0": "",
1819314Sandreas.hansson@arm.com                    bits((int)entry.dest, 1) ? " 1": "",
1829314Sandreas.hansson@arm.com                    bits((int)entry.dest, 2) ? " 2": "",
1839348SAli.Saidi@ARM.com                    bits((int)entry.dest, 3) ? " 3": "",
1849348SAli.Saidi@ARM.com                    bits((int)entry.dest, 4) ? " 4": "",
1859348SAli.Saidi@ARM.com                    bits((int)entry.dest, 5) ? " 5": "",
1869348SAli.Saidi@ARM.com                    bits((int)entry.dest, 6) ? " 6": "",
1879312Sandreas.hansson@arm.com                    bits((int)entry.dest, 7) ? " 7": ""
1889348SAli.Saidi@ARM.com                    );
1899348SAli.Saidi@ARM.com            uint8_t dests = entry.dest;
1909348SAli.Saidi@ARM.com            uint8_t id = 0;
1919348SAli.Saidi@ARM.com            while(dests) {
1929348SAli.Saidi@ARM.com                if (dests & 0x1) {
1939348SAli.Saidi@ARM.com                    PacketPtr pkt = buildIntRequest(id, message);
1949312Sandreas.hansson@arm.com                    if (sys->getMemoryMode() == Enums::timing)
1959348SAli.Saidi@ARM.com                        intPort->sendMessageTiming(pkt, latency);
1969348SAli.Saidi@ARM.com                    else if (sys->getMemoryMode() == Enums::atomic)
1979348SAli.Saidi@ARM.com                        intPort->sendMessageAtomic(pkt);
1989348SAli.Saidi@ARM.com                    else
1999348SAli.Saidi@ARM.com                        panic("Unrecognized memory mode.\n");
2009312Sandreas.hansson@arm.com                }
2019312Sandreas.hansson@arm.com                dests >>= 1;
2029312Sandreas.hansson@arm.com                id++;
2039348SAli.Saidi@ARM.com            }
2049348SAli.Saidi@ARM.com        }
2059348SAli.Saidi@ARM.com    }
2069348SAli.Saidi@ARM.com}
2079348SAli.Saidi@ARM.com
2089348SAli.Saidi@ARM.comX86ISA::I82094AA *
2099348SAli.Saidi@ARM.comI82094AAParams::create()
2109348SAli.Saidi@ARM.com{
2119348SAli.Saidi@ARM.com    return new X86ISA::I82094AA(this);
2129348SAli.Saidi@ARM.com}
2139348SAli.Saidi@ARM.com