From 557bde43c331024eb5cecf4093a24a5b7a9cc266 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 13:28:54 -0700 Subject: X86: Make APICs communicate through the memory system. --- src/arch/x86/X86LocalApic.py | 1 + src/arch/x86/interrupts.cc | 21 +++++++++++ src/arch/x86/interrupts.hh | 21 +++++++++-- src/arch/x86/intmessage.hh | 84 ++++++++++++++++++++++++++++++++++++++++++++ src/arch/x86/x86_traits.hh | 8 +++++ 5 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 src/arch/x86/intmessage.hh (limited to 'src/arch/x86') diff --git a/src/arch/x86/X86LocalApic.py b/src/arch/x86/X86LocalApic.py index 94e32ae50..483c65ef8 100644 --- a/src/arch/x86/X86LocalApic.py +++ b/src/arch/x86/X86LocalApic.py @@ -33,3 +33,4 @@ class X86LocalApic(BasicPioDevice): type = 'X86LocalApic' cxx_class = 'X86ISA::Interrupts' pio_latency = Param.Latency('1ns', 'Programmed IO latency in simticks') + int_port = Port("Port for sending and receiving interrupt messages") diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 6f1920de0..5614a37eb 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -239,6 +239,27 @@ X86ISA::Interrupts::write(PacketPtr pkt) return latency; } +Tick +X86ISA::Interrupts::recvMessage(PacketPtr pkt) +{ + Addr offset = pkt->getAddr() - x86InterruptAddress(0, 0); + assert(pkt->cmd == MemCmd::MessageReq); + switch(offset) + { + case 0: + DPRINTF(LocalApic, "Got Trigger Interrupt message.\n"); + break; + default: + panic("Local apic got unknown interrupt message at offset %#x.\n", + offset); + break; + } + delete pkt->req; + delete pkt; + return latency; +} + + uint32_t X86ISA::Interrupts::readReg(ApicRegIndex reg) { diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index 1d5f600bd..c4760dc0f 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -62,16 +62,16 @@ #include "arch/x86/faults.hh" #include "cpu/thread_context.hh" #include "dev/io_device.hh" +#include "dev/x86/intdev.hh" #include "params/X86LocalApic.hh" #include "sim/eventq.hh" -#include "sim/sim_object.hh" class ThreadContext; namespace X86ISA { -class Interrupts : public BasicPioDevice +class Interrupts : public BasicPioDevice, IntDev { protected: uint32_t regs[NUM_APIC_REGS]; @@ -108,6 +108,7 @@ class Interrupts : public BasicPioDevice Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); + Tick recvMessage(PacketPtr pkt); void addressRanges(AddrRangeList &range_list) { @@ -116,6 +117,13 @@ class Interrupts : public BasicPioDevice x86LocalAPICAddress(0, 0) + PageBytes)); } + void getIntAddrRange(AddrRangeList &range_list) + { + range_list.clear(); + range_list.push_back(RangeEx(x86InterruptAddress(0, 0), + x86InterruptAddress(0, 0) + PhysAddrAPICRangeSize)); + } + uint32_t readReg(ApicRegIndex miscReg); void setReg(ApicRegIndex reg, uint32_t val); void setRegNoEffect(ApicRegIndex reg, uint32_t val) @@ -123,7 +131,7 @@ class Interrupts : public BasicPioDevice regs[reg] = val; } - Interrupts(Params * p) : BasicPioDevice(p), + Interrupts(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), clock(0) { pioSize = PageBytes; @@ -133,6 +141,13 @@ class Interrupts : public BasicPioDevice clear_all(); } + Port *getPort(const std::string &if_name, int idx = -1) + { + if (if_name == "int_port") + return intPort; + return BasicPioDevice::getPort(if_name, idx); + } + int InterruptLevel(uint64_t softint) { panic("Interrupts::InterruptLevel unimplemented!\n"); diff --git a/src/arch/x86/intmessage.hh b/src/arch/x86/intmessage.hh new file mode 100644 index 000000000..64e821a41 --- /dev/null +++ b/src/arch/x86/intmessage.hh @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_INTMESSAGE_HH__ +#define __ARCH_X86_INTMESSAGE_HH__ + +#include "arch/x86/x86_traits.hh" +#include "base/bitunion.hh" +#include "mem/packet.hh" +#include "mem/request.hh" +#include "sim/host.hh" + +namespace X86ISA +{ + BitUnion32(TriggerIntMessage) + Bitfield<7, 0> destination; + Bitfield<15, 8> vector; + Bitfield<18, 16> deliveryMode; + Bitfield<19> destMode; + EndBitUnion(TriggerIntMessage) + + static const Addr TriggerIntOffset = 0; + + static inline PacketPtr + prepIntRequest(const uint8_t id, Addr offset, Addr size) + { + RequestPtr req = new Request(x86InterruptAddress(id, offset), + size, UNCACHEABLE); + PacketPtr pkt = new Packet(req, MemCmd::MessageReq, Packet::Broadcast); + pkt->allocate(); + return pkt; + } + + template + PacketPtr + buildIntRequest(const uint8_t id, T payload, Addr offset, Addr size) + { + PacketPtr pkt = prepIntRequest(id, offset, size); + pkt->set(payload); + return pkt; + } + + static inline PacketPtr + buildIntRequest(const uint8_t id, TriggerIntMessage payload) + { + return buildIntRequest(id, payload, TriggerIntOffset, + sizeof(TriggerIntMessage)); + } + + static inline PacketPtr + buildIntResponse() + { + panic("buildIntResponse not implemented.\n"); + } +} + +#endif diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh index 6b4671a08..be7572517 100644 --- a/src/arch/x86/x86_traits.hh +++ b/src/arch/x86/x86_traits.hh @@ -93,6 +93,7 @@ namespace X86ISA const Addr PhysAddrPrefixIO = ULL(0x8000000000000000); const Addr PhysAddrPrefixPciConfig = ULL(0xC000000000000000); const Addr PhysAddrPrefixLocalAPIC = ULL(0xA000000000000000); + const Addr PhysAddrPrefixInterrupts = ULL(0x2000000000000000); // Each APIC gets two pages. One page is used for local apics to field // accesses from the CPU, and the other is for all APICs to communicate. const Addr PhysAddrAPICRangeSize = 1 << 12; @@ -115,6 +116,13 @@ namespace X86ISA assert(addr < (1 << 12)); return PhysAddrPrefixLocalAPIC | (id * (1 << 12)) | addr; } + + static inline Addr + x86InterruptAddress(const uint8_t id, const uint16_t addr) + { + assert(addr < PhysAddrAPICRangeSize); + return PhysAddrPrefixInterrupts | (id * PhysAddrAPICRangeSize) | addr; + } } #endif //__ARCH_X86_X86TRAITS_HH__ -- cgit v1.2.3