summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Sandberg <andreas.sandberg@arm.com>2017-03-23 18:49:57 +0000
committerAndreas Sandberg <andreas.sandberg@arm.com>2018-06-07 12:36:44 +0000
commit409fbc653f5177f9f1da91877591a27b27302a3b (patch)
tree654a2b987fb207ea16e18254020d01ba4386c150
parent60600f09c25255b3c8f72da7fb49100e2682093a (diff)
downloadgem5-409fbc653f5177f9f1da91877591a27b27302a3b.tar.xz
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 <andreas.sandberg@arm.com> Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com> Reviewed-on: https://gem5-review.googlesource.com/2521 Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
-rw-r--r--src/dev/arm/Gic.py19
-rw-r--r--src/dev/arm/base_gic.cc82
-rw-r--r--src/dev/arm/base_gic.hh74
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<const Params *>(_params);
}
+
+
+ArmInterruptPin::ArmInterruptPin(const ArmInterruptPinParams *p)
+ : SimObject(p),
+ threadContext(nullptr),
+ platform(dynamic_cast<RealView*>(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