From c75d185d8ada4345ac3323b6603fedc4a79c94cc Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 11 Sep 2019 16:45:41 -0700 Subject: [PATCH] x86: Turn the local APIC Interrupts class into a SimObject. It will no longer be a PioDevice or a ClockedObject, but will carry forward the little bits and pieces of those classes that it was using. Those are a PIO port for memory mapped register accesses, and a clock domain parameter for setting the apic tick frequency. This brings the x86 Interrupts class in line with the Interrupts of the other ISAs so that they can inherit from a standard base class. Change-Id: I6b25fa21911b39a756e0cf9408c5489a81d6ca56 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20829 Reviewed-by: Jason Lowe-Power Reviewed-by: Brandon Potter Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/arch/x86/X86LocalApic.py | 11 +++++++---- src/arch/x86/interrupts.cc | 17 +++++++---------- src/arch/x86/interrupts.hh | 20 +++++++++++++++----- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/arch/x86/X86LocalApic.py b/src/arch/x86/X86LocalApic.py index 456409a62..914f29766 100644 --- a/src/arch/x86/X86LocalApic.py +++ b/src/arch/x86/X86LocalApic.py @@ -42,10 +42,10 @@ from m5.defines import buildEnv from m5.params import * from m5.proxy import * -from m5.objects.Device import PioDevice from m5.objects.ClockDomain import DerivedClockDomain +from m5.SimObject import SimObject -class X86LocalApic(PioDevice): +class X86LocalApic(SimObject): type = 'X86LocalApic' cxx_class = 'X86ISA::Interrupts' cxx_header = 'arch/x86/interrupts.hh' @@ -53,6 +53,8 @@ class X86LocalApic(PioDevice): int_slave = SlavePort("Port for receiving interrupt messages") int_latency = Param.Latency('1ns', \ "Latency for an interrupt to propagate through this device.") + pio = SlavePort("Programmed I/O port") + system = Param.System(Parent.any, "System this device is part of") pio_latency = Param.Latency('100ns', 'Programmed IO latency') @@ -60,5 +62,6 @@ class X86LocalApic(PioDevice): # which we assume is 1/16th the rate of the CPU clock. I don't think this # is a hard rule, but seems to be true in practice. This can be overriden # in configs that use it. - clk_domain = DerivedClockDomain( - clk_domain=Parent.clk_domain, clk_divider=16) + clk_domain = Param.DerivedClockDomain( + DerivedClockDomain(clk_domain=Parent.clk_domain, clk_divider=16), + "The clock for the local APIC. Should not be modified.") diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 14bdc0fc7..d237366ab 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -290,16 +290,13 @@ X86ISA::Interrupts::setCPU(BaseCPU * newCPU) void X86ISA::Interrupts::init() { - // - // The local apic must register its address ranges on its pio - // port via the basicpiodevice(piodevice) init() function. - PioDevice::init(); - - // The slave port has a range, so inform the connected master. - intSlavePort.sendRangeChange(); - // If the master port isn't connected, we can't send interrupts anywhere. panic_if(!intMasterPort.isConnected(), "Int port not connected to anything!"); + panic_if(!pioPort.isConnected(), + "Pio port of %s not connected to anything!", name()); + + intSlavePort.sendRangeChange(); + pioPort.sendRangeChange(); } @@ -599,7 +596,7 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) X86ISA::Interrupts::Interrupts(Params * p) - : PioDevice(p), + : SimObject(p), sys(p->system), clockDomain(*p->clk_domain), apicTimerEvent([this]{ processApicTimerEvent(); }, name()), pendingSmi(false), smiVector(0), pendingNmi(false), nmiVector(0), @@ -610,7 +607,7 @@ X86ISA::Interrupts::Interrupts(Params * p) pendingIPIs(0), cpu(NULL), intSlavePort(name() + ".int_slave", this, this), intMasterPort(name() + ".int_master", this, this, p->int_latency), - pioDelay(p->pio_latency) + pioPort(this), pioDelay(p->pio_latency) { memset(regs, 0, sizeof(regs)); //Set the local apic DFR to the flat model. diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index 3d6ef1f82..519d9f10e 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -72,9 +72,12 @@ namespace X86ISA { ApicRegIndex decodeAddr(Addr paddr); -class Interrupts : public PioDevice +class Interrupts : public SimObject { protected: + System *sys; + ClockDomain &clockDomain; + // Storage for the APIC registers uint32_t regs[NUM_APIC_REGS]; @@ -165,6 +168,8 @@ class Interrupts : public PioDevice return bits(regs[base + (vector / 32)], vector % 32); } + Tick clockPeriod() const { return clockDomain.clockPeriod(); } + void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level); BaseCPU *cpu; @@ -175,6 +180,9 @@ class Interrupts : public PioDevice IntSlavePort intSlavePort; IntMasterPort intMasterPort; + // Port for memory mapped register accesses. + PioPort pioPort; + Tick pioDelay; Addr pioAddr = MaxAddr; @@ -203,8 +211,8 @@ class Interrupts : public PioDevice /* * Functions to interact with the interrupt port. */ - Tick read(PacketPtr pkt) override; - Tick write(PacketPtr pkt) override; + Tick read(PacketPtr pkt); + Tick write(PacketPtr pkt); Tick recvMessage(PacketPtr pkt); void completeIPI(PacketPtr pkt); @@ -217,7 +225,7 @@ class Interrupts : public PioDevice return entry.periodic; } - AddrRangeList getAddrRanges() const override; + AddrRangeList getAddrRanges() const; AddrRangeList getIntAddrRange() const; Port &getPort(const std::string &if_name, @@ -227,8 +235,10 @@ class Interrupts : public PioDevice return intMasterPort; } else if (if_name == "int_slave") { return intSlavePort; + } else if (if_name == "pio") { + return pioPort; } - return PioDevice::getPort(if_name, idx); + return SimObject::getPort(if_name, idx); } /* -- 2.30.2