i82094aa.cc revision 13229:b45254f2733a
12686Sksewell@umich.edu/*
22100SN/A * Copyright (c) 2008 The Regents of The University of Michigan
35254Sksewell@umich.edu * All rights reserved.
45254Sksewell@umich.edu *
55254Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
65254Sksewell@umich.edu * modification, are permitted provided that the following conditions are
75254Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
85254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
95254Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
105254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
115254Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
125254Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
135254Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
145254Sksewell@umich.edu * this software without specific prior written permission.
155254Sksewell@umich.edu *
165254Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175254Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185254Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195254Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205254Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215254Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225254Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235254Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245254Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255254Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265254Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275254Sksewell@umich.edu *
285254Sksewell@umich.edu * Authors: Gabe Black
295254Sksewell@umich.edu */
305254Sksewell@umich.edu
315254Sksewell@umich.edu#include "dev/x86/i82094aa.hh"
322706Sksewell@umich.edu
332022SN/A#include "arch/x86/interrupts.hh"
342022SN/A#include "arch/x86/intmessage.hh"
352043SN/A#include "cpu/base.hh"
362024SN/A#include "debug/I82094AA.hh"
372024SN/A#include "dev/x86/i8259.hh"
382043SN/A#include "mem/packet.hh"
392686Sksewell@umich.edu#include "mem/packet_access.hh"
404661Sksewell@umich.edu#include "sim/system.hh"
412022SN/A
422083SN/AX86ISA::I82094AA::I82094AA(Params *p)
432686Sksewell@umich.edu    : BasicPioDevice(p, 20), IntDevice(this, p->int_latency),
442101SN/A      extIntPic(p->external_int_pic), lowestPriorityOffset(0)
452043SN/A{
462043SN/A    // This assumes there's only one I/O APIC in the system and since the apic
472101SN/A    // id is stored in a 8-bit field with 0xff meaning broadcast, the id must
482101SN/A    // be less than 0xff
496384Sgblack@eecs.umich.edu
506384Sgblack@eecs.umich.edu    assert(p->apic_id < 0xff);
516384Sgblack@eecs.umich.edu    initialApicId = id = p->apic_id;
526384Sgblack@eecs.umich.edu    arbId = id;
536384Sgblack@eecs.umich.edu    regSel = 0;
546384Sgblack@eecs.umich.edu    RedirTableEntry entry = 0;
552101SN/A    entry.mask = 1;
562101SN/A    for (int i = 0; i < TableSize; i++) {
572101SN/A        redirTable[i] = entry;
582046SN/A        pinStates[i] = false;
592686Sksewell@umich.edu    }
602686Sksewell@umich.edu}
612686Sksewell@umich.edu
622470SN/Avoid
632686Sksewell@umich.eduX86ISA::I82094AA::init()
644661Sksewell@umich.edu{
655222Sksewell@umich.edu    // The io apic must register its address ranges on both its pio port
665222Sksewell@umich.edu    // via the piodevice init() function and its int port that it inherited
672686Sksewell@umich.edu    // from IntDevice.  Note IntDevice is not a SimObject itself.
688588Sgblack@eecs.umich.edu
692470SN/A    BasicPioDevice::init();
702241SN/A    IntDevice::init();
712101SN/A}
722495SN/A
732495SN/ABaseMasterPort &
748588Sgblack@eecs.umich.eduX86ISA::I82094AA::getMasterPort(const std::string &if_name, PortID idx)
752101SN/A{
766384Sgblack@eecs.umich.edu    if (if_name == "int_master")
776384Sgblack@eecs.umich.edu        return intMasterPort;
786384Sgblack@eecs.umich.edu    return BasicPioDevice::getMasterPort(if_name, idx);
798588Sgblack@eecs.umich.edu}
806384Sgblack@eecs.umich.edu
812495SN/AAddrRangeList
822101SN/AX86ISA::I82094AA::getIntAddrRange() const
832101SN/A{
842495SN/A    AddrRangeList ranges;
852495SN/A    ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
862495SN/A                             x86InterruptAddress(initialApicId, 0) +
872495SN/A                             PhysAddrAPICRangeSize));
882495SN/A    return ranges;
892495SN/A}
902495SN/A
912495SN/ATick
922495SN/AX86ISA::I82094AA::recvResponse(PacketPtr pkt)
932495SN/A{
942495SN/A    // Packet instantiated calling sendMessage() in signalInterrupt()
952495SN/A    delete pkt;
962495SN/A    return 0;
972101SN/A}
988588Sgblack@eecs.umich.edu
992101SN/ATick
1002101SN/AX86ISA::I82094AA::read(PacketPtr pkt)
1018588Sgblack@eecs.umich.edu{
1022101SN/A    assert(pkt->getSize() == 4);
1036384Sgblack@eecs.umich.edu    Addr offset = pkt->getAddr() - pioAddr;
1046384Sgblack@eecs.umich.edu    switch(offset) {
1056384Sgblack@eecs.umich.edu      case 0:
1068588Sgblack@eecs.umich.edu        pkt->setLE<uint32_t>(regSel);
1078588Sgblack@eecs.umich.edu        break;
1086384Sgblack@eecs.umich.edu      case 16:
1092101SN/A        pkt->setLE<uint32_t>(readReg(regSel));
1102101SN/A        break;
1112495SN/A      default:
1122495SN/A        panic("Illegal read from I/O APIC.\n");
1132495SN/A    }
1142495SN/A    pkt->makeAtomicResponse();
1152495SN/A    return pioDelay;
1166384Sgblack@eecs.umich.edu}
1176384Sgblack@eecs.umich.edu
1186384Sgblack@eecs.umich.eduTick
1196384Sgblack@eecs.umich.eduX86ISA::I82094AA::write(PacketPtr pkt)
1206384Sgblack@eecs.umich.edu{
1212495SN/A    assert(pkt->getSize() == 4);
1226384Sgblack@eecs.umich.edu    Addr offset = pkt->getAddr() - pioAddr;
1232495SN/A    switch(offset) {
1242495SN/A      case 0:
1252043SN/A        regSel = pkt->getLE<uint32_t>();
1262043SN/A        break;
1272025SN/A      case 16:
1282043SN/A        writeReg(regSel, pkt->getLE<uint32_t>());
1292686Sksewell@umich.edu        break;
1302686Sksewell@umich.edu      default:
1312123SN/A        panic("Illegal write to I/O APIC.\n");
1322101SN/A    }
1336376Sgblack@eecs.umich.edu    pkt->makeAtomicResponse();
1346376Sgblack@eecs.umich.edu    return pioDelay;
1356376Sgblack@eecs.umich.edu}
1367792Sgblack@eecs.umich.edu
1376376Sgblack@eecs.umich.eduvoid
1386376Sgblack@eecs.umich.eduX86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value)
1396376Sgblack@eecs.umich.edu{
1406376Sgblack@eecs.umich.edu    if (offset == 0x0) {
1416376Sgblack@eecs.umich.edu        id = bits(value, 31, 24);
1426376Sgblack@eecs.umich.edu    } else if (offset == 0x1) {
1436376Sgblack@eecs.umich.edu        // The IOAPICVER register is read only.
1447792Sgblack@eecs.umich.edu    } else if (offset == 0x2) {
1456376Sgblack@eecs.umich.edu        arbId = bits(value, 31, 24);
1466376Sgblack@eecs.umich.edu    } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
1476376Sgblack@eecs.umich.edu        int index = (offset - 0x10) / 2;
1486376Sgblack@eecs.umich.edu        if (offset % 2) {
1492101SN/A            redirTable[index].topDW = value;
1502042SN/A            redirTable[index].topReserved = 0;
1512101SN/A        } else {
1527720Sgblack@eecs.umich.edu            redirTable[index].bottomDW = value;
1537792Sgblack@eecs.umich.edu            redirTable[index].bottomReserved = 0;
1547792Sgblack@eecs.umich.edu        }
1557720Sgblack@eecs.umich.edu    } else {
1567720Sgblack@eecs.umich.edu        warn("Access to undefined I/O APIC register %#x.\n", offset);
1577792Sgblack@eecs.umich.edu    }
1587792Sgblack@eecs.umich.edu    DPRINTF(I82094AA,
1597720Sgblack@eecs.umich.edu            "Wrote %#x to I/O APIC register %#x .\n", value, offset);
1602101SN/A}
1612101SN/A
1622042SN/Auint32_t
1632101SN/AX86ISA::I82094AA::readReg(uint8_t offset)
1642686Sksewell@umich.edu{
1652686Sksewell@umich.edu    uint32_t result = 0;
1668901Sandreas.hansson@arm.com    if (offset == 0x0) {
1678564Sgblack@eecs.umich.edu        result = id << 24;
1688564Sgblack@eecs.umich.edu    } else if (offset == 0x1) {
16910474Sandreas.hansson@arm.com        result = ((TableSize - 1) << 16) | APICVersion;
1708564Sgblack@eecs.umich.edu    } else if (offset == 0x2) {
1712686Sksewell@umich.edu        result = arbId << 24;
17210474Sandreas.hansson@arm.com    } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) {
1732101SN/A        int index = (offset - 0x10) / 2;
1742083SN/A        if (offset % 2) {
1752043SN/A            result = redirTable[index].topDW;
1762025SN/A        } else {
1772043SN/A            result = redirTable[index].bottomDW;
1786384Sgblack@eecs.umich.edu        }
1796384Sgblack@eecs.umich.edu    } else {
1804661Sksewell@umich.edu        warn("Access to undefined I/O APIC register %#x.\n", offset);
1816384Sgblack@eecs.umich.edu    }
1826384Sgblack@eecs.umich.edu    DPRINTF(I82094AA,
1834661Sksewell@umich.edu            "Read %#x from I/O APIC register %#x.\n", result, offset);
1842083SN/A    return result;
1852025SN/A}
1862043SN/A
1874661Sksewell@umich.eduvoid
1888588Sgblack@eecs.umich.eduX86ISA::I82094AA::signalInterrupt(int line)
1898588Sgblack@eecs.umich.edu{
1904661Sksewell@umich.edu    DPRINTF(I82094AA, "Received interrupt %d.\n", line);
1914661Sksewell@umich.edu    assert(line < TableSize);
1922686Sksewell@umich.edu    RedirTableEntry entry = redirTable[line];
1936384Sgblack@eecs.umich.edu    if (entry.mask) {
1948588Sgblack@eecs.umich.edu        DPRINTF(I82094AA, "Entry was masked.\n");
1958588Sgblack@eecs.umich.edu        return;
1968588Sgblack@eecs.umich.edu    } else {
1976384Sgblack@eecs.umich.edu        TriggerIntMessage message = 0;
1985222Sksewell@umich.edu        message.destination = entry.dest;
1995222Sksewell@umich.edu        if (entry.deliveryMode == DeliveryMode::ExtInt) {
2006384Sgblack@eecs.umich.edu            assert(extIntPic);
2018588Sgblack@eecs.umich.edu            message.vector = extIntPic->getVector();
2028588Sgblack@eecs.umich.edu        } else {
2038588Sgblack@eecs.umich.edu            message.vector = entry.vector;
2046384Sgblack@eecs.umich.edu        }
2055222Sksewell@umich.edu        message.deliveryMode = entry.deliveryMode;
2062101SN/A        message.destMode = entry.destMode;
2072084SN/A        message.level = entry.polarity;
2082025SN/A        message.trigger = entry.trigger;
2092495SN/A        ApicList apics;
2102495SN/A        int numContexts = sys->numContexts();
2112495SN/A        if (message.destMode == 0) {
2126384Sgblack@eecs.umich.edu            if (message.deliveryMode == DeliveryMode::LowestPriority) {
2138564Sgblack@eecs.umich.edu                panic("Lowest priority delivery mode from the "
2148564Sgblack@eecs.umich.edu                        "IO APIC aren't supported in physical "
2158738Sgblack@eecs.umich.edu                        "destination mode.\n");
2168564Sgblack@eecs.umich.edu            }
21710474Sandreas.hansson@arm.com            if (message.destination == 0xFF) {
2186384Sgblack@eecs.umich.edu                for (int i = 0; i < numContexts; i++) {
2196384Sgblack@eecs.umich.edu                    apics.push_back(i);
2208588Sgblack@eecs.umich.edu                }
2215222Sksewell@umich.edu            } else {
2228564Sgblack@eecs.umich.edu                apics.push_back(message.destination);
2238564Sgblack@eecs.umich.edu            }
2248738Sgblack@eecs.umich.edu        } else {
2258564Sgblack@eecs.umich.edu            for (int i = 0; i < numContexts; i++) {
22610474Sandreas.hansson@arm.com                Interrupts *localApic = sys->getThreadContext(i)->
2276384Sgblack@eecs.umich.edu                    getCpuPtr()->getInterruptController(0);
2286384Sgblack@eecs.umich.edu                if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) &
2298588Sgblack@eecs.umich.edu                        message.destination) {
2306384Sgblack@eecs.umich.edu                    apics.push_back(localApic->getInitialApicId());
2316384Sgblack@eecs.umich.edu                }
2326384Sgblack@eecs.umich.edu            }
2336384Sgblack@eecs.umich.edu            if (message.deliveryMode == DeliveryMode::LowestPriority &&
2342495SN/A                    apics.size()) {
2352101SN/A                // The manual seems to suggest that the chipset just does
2362043SN/A                // something reasonable for these instead of actually using
2372025SN/A                // state from the local APIC. We'll just rotate an offset
2382495SN/A                // through the set of APICs selected above.
2392495SN/A                uint64_t modOffset = lowestPriorityOffset % apics.size();
2402495SN/A                lowestPriorityOffset++;
2418588Sgblack@eecs.umich.edu                ApicList::iterator apicIt = apics.begin();
2428588Sgblack@eecs.umich.edu                while (modOffset--) {
2432495SN/A                    apicIt++;
2442101SN/A                    assert(apicIt != apics.end());
2452084SN/A                }
2462024SN/A                int selected = *apicIt;
2472043SN/A                apics.clear();
2482239SN/A                apics.push_back(selected);
2498588Sgblack@eecs.umich.edu            }
2508588Sgblack@eecs.umich.edu        }
2518588Sgblack@eecs.umich.edu        intMasterPort.sendMessage(apics, message, sys->isTimingMode());
2528588Sgblack@eecs.umich.edu    }
2538588Sgblack@eecs.umich.edu}
2548588Sgblack@eecs.umich.edu
2552101SN/Avoid
2562043SN/AX86ISA::I82094AA::raiseInterruptPin(int number)
2572043SN/A{
2582025SN/A    assert(number < TableSize);
2592043SN/A    if (!pinStates[number])
2602043SN/A        signalInterrupt(number);
2612101SN/A    pinStates[number] = true;
2628588Sgblack@eecs.umich.edu}
2638588Sgblack@eecs.umich.edu
2648588Sgblack@eecs.umich.eduvoid
2658588Sgblack@eecs.umich.eduX86ISA::I82094AA::lowerInterruptPin(int number)
2662101SN/A{
2672043SN/A    assert(number < TableSize);
2682025SN/A    pinStates[number] = false;
2692043SN/A}
2705222Sksewell@umich.edu
2718588Sgblack@eecs.umich.eduvoid
2726384Sgblack@eecs.umich.eduX86ISA::I82094AA::serialize(CheckpointOut &cp) const
2738588Sgblack@eecs.umich.edu{
2746384Sgblack@eecs.umich.edu    uint64_t* redirTableArray = (uint64_t*)redirTable;
2758588Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regSel);
2766384Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(initialApicId);
2778588Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(id);
2786384Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(arbId);
2798588Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(lowestPriorityOffset);
2808588Sgblack@eecs.umich.edu    SERIALIZE_ARRAY(redirTableArray, TableSize);
2812101SN/A    SERIALIZE_ARRAY(pinStates, TableSize);
2822043SN/A}
2832043SN/A
2842043SN/Avoid
2852101SN/AX86ISA::I82094AA::unserialize(CheckpointIn &cp)
2868588Sgblack@eecs.umich.edu{
2872686Sksewell@umich.edu    uint64_t redirTableArray[TableSize];
2882686Sksewell@umich.edu    UNSERIALIZE_SCALAR(regSel);
2898588Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(initialApicId);
2902686Sksewell@umich.edu    UNSERIALIZE_SCALAR(id);
2918588Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(arbId);
2928588Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(lowestPriorityOffset);
2932101SN/A    UNSERIALIZE_ARRAY(redirTableArray, TableSize);
2942043SN/A    UNSERIALIZE_ARRAY(pinStates, TableSize);
2952043SN/A    for (int i = 0; i < TableSize; i++) {
2962043SN/A        redirTable[i] = (RedirTableEntry)redirTableArray[i];
2976384Sgblack@eecs.umich.edu    }
2986384Sgblack@eecs.umich.edu}
2994661Sksewell@umich.edu
3002101SN/AX86ISA::I82094AA *
3012101SN/AI82094AAParams::create()
3022101SN/A{
3032043SN/A    return new X86ISA::I82094AA(this);
3042043SN/A}
3052043SN/A