From 409fbc653f5177f9f1da91877591a27b27302a3b Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Thu, 23 Mar 2017 18:49:57 +0000 Subject: [PATCH] dev-arm: Add a GIC interrupt adaptor Add GIC-based interrupt adaptor implementations that support PPI (ArmPPI) and SPI (ArmSPI) delivery. In addition to being useful for "normal" memory-mapped devices, the PPI adaptor makes it possible to use the same device model to generate both PPIs and SPIs (e.g., the PMU). Change-Id: I73d6591c168040faef2443430c4f1da10c387a2a Signed-off-by: Andreas Sandberg Reviewed-by: Nikos Nikoleris Reviewed-on: https://gem5-review.googlesource.com/2521 Reviewed-by: Giacomo Travaglini --- src/dev/arm/Gic.py | 19 +++++++++- src/dev/arm/base_gic.cc | 82 ++++++++++++++++++++++++++++++++++++++++- src/dev/arm/base_gic.hh | 74 ++++++++++++++++++++++++++++++++++++- 3 files changed, 171 insertions(+), 4 deletions(-) diff --git a/src/dev/arm/Gic.py b/src/dev/arm/Gic.py index bc7794af7..5f756639e 100644 --- a/src/dev/arm/Gic.py +++ b/src/dev/arm/Gic.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2013 ARM Limited +# Copyright (c) 2012-2013, 2017-2018 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -49,6 +49,23 @@ class BaseGic(PioDevice): platform = Param.Platform(Parent.any, "Platform this device is part of.") +class ArmInterruptPin(SimObject): + type = 'ArmInterruptPin' + cxx_header = "dev/arm/base_gic.hh" + abstract = True + + platform = Param.Platform(Parent.any, "Platform with interrupt controller") + num = Param.UInt32("Interrupt number in GIC") + +class ArmSPI(ArmInterruptPin): + type = 'ArmSPI' + cxx_header = "dev/arm/base_gic.hh" + +class ArmPPI(ArmInterruptPin): + type = 'ArmPPI' + cxx_header = "dev/arm/base_gic.hh" + + class Pl390(BaseGic): type = 'Pl390' cxx_header = "dev/arm/gic_pl390.hh" diff --git a/src/dev/arm/base_gic.cc b/src/dev/arm/base_gic.cc index ece8352d3..65754d018 100644 --- a/src/dev/arm/base_gic.cc +++ b/src/dev/arm/base_gic.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 ARM Limited + * Copyright (c) 2012, 2017-2018 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -39,7 +39,11 @@ #include "dev/arm/base_gic.hh" +#include "cpu/thread_context.hh" #include "dev/arm/realview.hh" +#include "params/ArmInterruptPin.hh" +#include "params/ArmPPI.hh" +#include "params/ArmSPI.hh" #include "params/BaseGic.hh" BaseGic::BaseGic(const Params *p) @@ -65,3 +69,79 @@ BaseGic::params() const { return dynamic_cast(_params); } + + +ArmInterruptPin::ArmInterruptPin(const ArmInterruptPinParams *p) + : SimObject(p), + threadContext(nullptr), + platform(dynamic_cast(p->platform)), + intNum(p->num) +{ + fatal_if(!platform, "Interrupt not connected to a RealView platform"); +} + +void +ArmInterruptPin::setThreadContext(ThreadContext *tc) +{ + panic_if(threadContext, + "InterruptLine::setThreadContext called twice\n"); + + threadContext = tc; +} + +ContextID +ArmInterruptPin::targetContext() const +{ + panic_if(!threadContext, "Per-context interrupt triggered without a " \ + "call to InterruptLine::setThreadContext.\n"); + return threadContext->contextId(); +} + + + +ArmSPI::ArmSPI(const ArmSPIParams *p) + : ArmInterruptPin(p) +{ +} + +void +ArmSPI::raise() +{ + platform->gic->sendInt(intNum); +} + +void +ArmSPI::clear() +{ + platform->gic->clearInt(intNum); +} + +ArmPPI::ArmPPI(const ArmPPIParams *p) + : ArmInterruptPin(p) +{ +} + +void +ArmPPI::raise() +{ + platform->gic->sendPPInt(intNum, targetContext()); +} + +void +ArmPPI::clear() +{ + platform->gic->clearPPInt(intNum, targetContext()); +} + + +ArmSPI * +ArmSPIParams::create() +{ + return new ArmSPI(this); +} + +ArmPPI * +ArmPPIParams::create() +{ + return new ArmPPI(this); +} diff --git a/src/dev/arm/base_gic.hh b/src/dev/arm/base_gic.hh index cd16c0362..73d73e471 100644 --- a/src/dev/arm/base_gic.hh +++ b/src/dev/arm/base_gic.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2017 ARM Limited + * Copyright (c) 2012-2013, 2017-2018 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -47,11 +47,18 @@ #include "dev/io_device.hh" class Platform; +class RealView; +class ThreadContext; + +struct ArmInterruptPinParams; +struct ArmPPIParams; +struct ArmSPIParams; +struct BaseGicParams; class BaseGic : public PioDevice { public: - typedef struct BaseGicParams Params; + typedef BaseGicParams Params; BaseGic(const Params *p); virtual ~BaseGic(); @@ -103,4 +110,67 @@ class BaseGicRegisters virtual void writeCpu(ContextID ctx, Addr daddr, uint32_t data) = 0; }; +/** + * Generic representation of an Arm interrupt pin. + */ +class ArmInterruptPin : public SimObject +{ + public: + ArmInterruptPin(const ArmInterruptPinParams *p); + + public: /* Public interface */ + /** + * Set the thread context owning this interrupt. + * + * This method is used to set the thread context for interrupts + * that are thread/CPU-specific. Only devices that are used in + * such a context are expected to call this method. + */ + void setThreadContext(ThreadContext *tc); + + /** Signal an interrupt */ + virtual void raise() = 0; + /** Clear a signalled interrupt */ + virtual void clear() = 0; + + protected: + /** + * Get the target context ID of this interrupt. + * + * @pre setThreadContext() must have been called prior to calling + * this method. + */ + ContextID targetContext() const; + + /** + * Pointer to the thread context that owns this interrupt in case + * it is a thread-/CPU-private interrupt + */ + const ThreadContext *threadContext; + + /** Arm platform to use for interrupt generation */ + RealView *const platform; + /** Interrupt number to generate */ + const uint32_t intNum; +}; + +class ArmSPI : public ArmInterruptPin +{ + public: + ArmSPI(const ArmSPIParams *p); + + void raise() override; + void clear() override; +}; + +class ArmPPI : public ArmInterruptPin +{ + public: + ArmPPI(const ArmPPIParams *p); + + void raise() override; + void clear() override; +}; + + #endif -- 2.30.2