i82094aa.cc revision 6138:6cbdd76b93db
12124SN/A/*
22124SN/A * Copyright (c) 2008 The Regents of The University of Michigan
35222Sksewell@umich.edu * All rights reserved.
45222Sksewell@umich.edu *
55222Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
65222Sksewell@umich.edu * modification, are permitted provided that the following conditions are
75222Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
85222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
95222Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
105222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
115222Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
125222Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
135222Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
145222Sksewell@umich.edu * this software without specific prior written permission.
155222Sksewell@umich.edu *
165222Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175222Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185222Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195222Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205222Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215222Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225222Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235222Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245222Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255222Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265222Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275222Sksewell@umich.edu *
285222Sksewell@umich.edu * Authors: Gabe Black
295222Sksewell@umich.edu */
305222Sksewell@umich.edu
315222Sksewell@umich.edu#include "arch/x86/interrupts.hh"
325222Sksewell@umich.edu#include "arch/x86/intmessage.hh"
335222Sksewell@umich.edu#include "dev/x86/i82094aa.hh"
345222Sksewell@umich.edu#include "dev/x86/i8259.hh"
355222Sksewell@umich.edu#include "mem/packet.hh"
365222Sksewell@umich.edu#include "mem/packet_access.hh"
372022SN/A#include "sim/system.hh"
382649Ssaidi@eecs.umich.edu
392649Ssaidi@eecs.umich.eduX86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this),
402706Sksewell@umich.edu    latency(p->pio_latency), pioAddr(p->pio_addr),
412649Ssaidi@eecs.umich.edu    extIntPic(p->external_int_pic)
422649Ssaidi@eecs.umich.edu{
432022SN/A    // This assumes there's only one I/O APIC in the system
442124SN/A    initialApicId = id = p->apic_id;
452124SN/A    assert(id <= 0xf);
462124SN/A    arbId = id;
472124SN/A    regSel = 0;
482124SN/A    RedirTableEntry entry = 0;
492124SN/A    entry.mask = 1;
502124SN/A    for (int i = 0; i < TableSize; i++) {
512124SN/A        redirTable[i] = entry;
522124SN/A        pinStates[i] = false;
532124SN/A    }
542124SN/A}
552124SN/A
562124SN/ATick
572239SN/AX86ISA::I82094AA::read(PacketPtr pkt)
582124SN/A{
592124SN/A    assert(pkt->getSize() == 4);
602124SN/A    Addr offset = pkt->getAddr() - pioAddr;
612124SN/A    switch(offset) {
622124SN/A      case 0:
632124SN/A        pkt->set<uint32_t>(regSel);
642124SN/A        break;
652124SN/A      case 16:
662124SN/A        pkt->set<uint32_t>(readReg(regSel));
672742Sksewell@umich.edu        break;
682022SN/A      default:
692124SN/A        panic("Illegal read from I/O APIC.\n");
702022SN/A    }
712124SN/A    pkt->makeAtomicResponse();
722124SN/A    return latency;
732022SN/A}
742124SN/A
752124SN/ATick
762124SN/AX86ISA::I82094AA::write(PacketPtr pkt)
772124SN/A{
784661Sksewell@umich.edu    assert(pkt->getSize() == 4);
794661Sksewell@umich.edu    Addr offset = pkt->getAddr() - pioAddr;
802124SN/A    switch(offset) {
812124SN/A      case 0:
822742Sksewell@umich.edu        regSel = pkt->get<uint32_t>();
832742Sksewell@umich.edu        break;
842742Sksewell@umich.edu      case 16:
852742Sksewell@umich.edu        writeReg(regSel, pkt->get<uint32_t>());
862742Sksewell@umich.edu        break;
872742Sksewell@umich.edu      default:
882742Sksewell@umich.edu        panic("Illegal write to I/O APIC.\n");
892742Sksewell@umich.edu    }
902742Sksewell@umich.edu    pkt->makeAtomicResponse();
912742Sksewell@umich.edu    return latency;
922742Sksewell@umich.edu}
932742Sksewell@umich.edu
942742Sksewell@umich.eduvoid
952742Sksewell@umich.eduX86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value)
962742Sksewell@umich.edu{
972742Sksewell@umich.edu    if (offset == 0x0) {
982742Sksewell@umich.edu        id = bits(value, 27, 24);
992742Sksewell@umich.edu    } else if (offset == 0x1) {
1002022SN/A        // The IOAPICVER register is read only.
1012022SN/A    } else if (offset == 0x2) {
1022124SN/A        arbId = bits(value, 27, 24);
1032022SN/A    } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
1042124SN/A        int index = (offset - 0x10) / 2;
1052124SN/A        if (offset % 2) {
1062124SN/A            redirTable[index].topDW = value;
1072742Sksewell@umich.edu            redirTable[index].topReserved = 0;
1082239SN/A        } else {
1092124SN/A            redirTable[index].bottomDW = value;
1102124SN/A            redirTable[index].bottomReserved = 0;
1112742Sksewell@umich.edu        }
1122742Sksewell@umich.edu    } else {
1132742Sksewell@umich.edu        warn("Access to undefined I/O APIC register %#x.\n", offset);
1142742Sksewell@umich.edu    }
1152742Sksewell@umich.edu    DPRINTF(I82094AA,
1162742Sksewell@umich.edu            "Wrote %#x to I/O APIC register %#x .\n", value, offset);
1172742Sksewell@umich.edu}
1182742Sksewell@umich.edu
1194661Sksewell@umich.eduuint32_t
1204661Sksewell@umich.eduX86ISA::I82094AA::readReg(uint8_t offset)
1214661Sksewell@umich.edu{
1224661Sksewell@umich.edu    uint32_t result = 0;
1234661Sksewell@umich.edu    if (offset == 0x0) {
1244661Sksewell@umich.edu        result = id << 24;
1254661Sksewell@umich.edu    } else if (offset == 0x1) {
1265222Sksewell@umich.edu        result = ((TableSize - 1) << 16) | APICVersion;
1274661Sksewell@umich.edu    } else if (offset == 0x2) {
1284661Sksewell@umich.edu        result = arbId << 24;
1295222Sksewell@umich.edu    } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
1304661Sksewell@umich.edu        int index = (offset - 0x10) / 2;
1314661Sksewell@umich.edu        if (offset % 2) {
1325222Sksewell@umich.edu            result = redirTable[index].topDW;
1334661Sksewell@umich.edu        } else {
1344661Sksewell@umich.edu            result = redirTable[index].bottomDW;
1355222Sksewell@umich.edu        }
1364661Sksewell@umich.edu    } else {
1374661Sksewell@umich.edu        warn("Access to undefined I/O APIC register %#x.\n", offset);
1385222Sksewell@umich.edu    }
1394661Sksewell@umich.edu    DPRINTF(I82094AA,
1404661Sksewell@umich.edu            "Read %#x from I/O APIC register %#x.\n", result, offset);
1414661Sksewell@umich.edu    return result;
1424661Sksewell@umich.edu}
1434661Sksewell@umich.edu
1444661Sksewell@umich.eduvoid
1454661Sksewell@umich.eduX86ISA::I82094AA::signalInterrupt(int line)
1464661Sksewell@umich.edu{
1474661Sksewell@umich.edu    DPRINTF(I82094AA, "Received interrupt %d.\n", line);
1484661Sksewell@umich.edu    assert(line < TableSize);
1494661Sksewell@umich.edu    RedirTableEntry entry = redirTable[line];
1502022SN/A    if (entry.mask) {
1512022SN/A        DPRINTF(I82094AA, "Entry was masked.\n");
1522124SN/A        return;
1532124SN/A    } else {
1542124SN/A        TriggerIntMessage message;
1552124SN/A        message.destination = entry.dest;
1562124SN/A        if (entry.deliveryMode == DeliveryMode::ExtInt) {
1572124SN/A            assert(extIntPic);
1582124SN/A            message.vector = extIntPic->getVector();
1592124SN/A        } else {
1602124SN/A            message.vector = entry.vector;
1612124SN/A        }
1622124SN/A        message.deliveryMode = entry.deliveryMode;
1632124SN/A        message.destMode = entry.destMode;
1642124SN/A        message.level = entry.polarity;
1652124SN/A        message.trigger = entry.trigger;
1662124SN/A        ApicList apics;
1674661Sksewell@umich.edu        int numContexts = sys->numContexts();
1682124SN/A        if (message.destMode == 0) {
1692124SN/A            if (message.deliveryMode == DeliveryMode::LowestPriority) {
1702124SN/A                panic("Lowest priority delivery mode from the "
1712124SN/A                        "IO APIC aren't supported in physical "
1722124SN/A                        "destination mode.\n");
1732124SN/A            }
1742124SN/A            if (message.destination == 0xFF) {
1752124SN/A                for (int i = 0; i < numContexts; i++) {
1762124SN/A                    apics.push_back(i);
1772124SN/A                }
1782124SN/A            } else {
1794661Sksewell@umich.edu                apics.push_back(message.destination);
1802124SN/A            }
1812124SN/A        } else {
1822124SN/A            for (int i = 0; i < numContexts; i++) {
1832124SN/A                std::map<int, Interrupts *>::iterator localApicIt =
1842124SN/A                    localApics.find(i);
1852124SN/A                assert(localApicIt != localApics.end());
1862124SN/A                Interrupts *localApic = localApicIt->second;
1874661Sksewell@umich.edu                if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) &
1882124SN/A                        message.destination) {
1892124SN/A                    apics.push_back(localApicIt->first);
1902124SN/A                }
1912124SN/A            }
1922124SN/A            if (message.deliveryMode == DeliveryMode::LowestPriority) {
1932124SN/A                panic("Lowest priority delivery mode is not implemented.\n");
1944661Sksewell@umich.edu            }
1954661Sksewell@umich.edu        }
1962124SN/A        intPort->sendMessage(apics, message,
1972022SN/A                sys->getMemoryMode() == Enums::timing);
1982022SN/A    }
1992124SN/A}
2002124SN/A
2012132SN/Avoid
2022022SN/AX86ISA::I82094AA::raiseInterruptPin(int number)
2032124SN/A{
2042124SN/A    assert(number < TableSize);
2052124SN/A    if (!pinStates[number])
2064661Sksewell@umich.edu        signalInterrupt(number);
2072124SN/A    pinStates[number] = true;
2082124SN/A}
2094661Sksewell@umich.edu
2104661Sksewell@umich.eduvoid
2114661Sksewell@umich.eduX86ISA::I82094AA::lowerInterruptPin(int number)
2122124SN/A{
2135222Sksewell@umich.edu    assert(number < TableSize);
2145222Sksewell@umich.edu    pinStates[number] = false;
2155222Sksewell@umich.edu}
2165222Sksewell@umich.edu
2175222Sksewell@umich.eduvoid
2185222Sksewell@umich.eduX86ISA::I82094AA::registerLocalApic(int initialId, Interrupts *localApic)
2195222Sksewell@umich.edu{
2205222Sksewell@umich.edu    assert(localApic);
2215222Sksewell@umich.edu    localApics[initialId] = localApic;
2223953Sstever@eecs.umich.edu}
2232124SN/A
2242124SN/AX86ISA::I82094AA *
2252124SN/AI82094AAParams::create()
2264661Sksewell@umich.edu{
2272124SN/A    return new X86ISA::I82094AA(this);
2282124SN/A}
2293953Sstever@eecs.umich.edu