arm: Create a GIC base class and make the PL390 derive from it
authorAndreas Sandberg <Andreas.Sandberg@ARM.com>
Thu, 25 Oct 2012 13:05:24 +0000 (14:05 +0100)
committerAndreas Sandberg <Andreas.Sandberg@ARM.com>
Thu, 25 Oct 2012 13:05:24 +0000 (14:05 +0100)
This patch moves the GIC interface to a separate base class and makes
all interrupt devices use that base class instead of a pointer to the
PL390 implementation. This allows us to have multiple GIC
implementations. Future implementations will allow in-kernel GIC
implementations when using hardware virtualization.

--HG--
rename : src/dev/arm/gic.cc => src/dev/arm/gic_pl390.cc
rename : src/dev/arm/gic.hh => src/dev/arm/gic_pl390.hh

21 files changed:
src/dev/arm/Gic.py [new file with mode: 0644]
src/dev/arm/RealView.py
src/dev/arm/SConscript
src/dev/arm/amba_device.hh
src/dev/arm/base_gic.cc [new file with mode: 0644]
src/dev/arm/base_gic.hh [new file with mode: 0644]
src/dev/arm/gic.cc [deleted file]
src/dev/arm/gic.hh [deleted file]
src/dev/arm/gic_pl390.cc [new file with mode: 0644]
src/dev/arm/gic_pl390.hh [new file with mode: 0644]
src/dev/arm/kmi.hh
src/dev/arm/pl011.cc
src/dev/arm/pl011.hh
src/dev/arm/pl111.cc
src/dev/arm/pl111.hh
src/dev/arm/realview.cc
src/dev/arm/realview.hh
src/dev/arm/timer_cpulocal.cc
src/dev/arm/timer_cpulocal.hh
src/dev/arm/timer_sp804.cc
src/dev/arm/timer_sp804.hh

diff --git a/src/dev/arm/Gic.py b/src/dev/arm/Gic.py
new file mode 100644 (file)
index 0000000..0461758
--- /dev/null
@@ -0,0 +1,61 @@
+# Copyright (c) 2012 ARM Limited
+# All rights reserved.
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder.  You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# 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: Andreas Sandberg
+
+from m5.params import *
+from m5.proxy import *
+
+from Device import PioDevice
+from Platform import Platform
+
+class BaseGic(PioDevice):
+    type = 'BaseGic'
+    abstract = True
+    cxx_header = "dev/arm/base_gic.hh"
+
+    platform = Param.Platform(Parent.any, "Platform this device is part of.")
+
+class Pl390(BaseGic):
+    type = 'Pl390'
+    cxx_header = "dev/arm/gic_pl390.hh"
+
+    dist_addr = Param.Addr(0x1f001000, "Address for distributor")
+    cpu_addr = Param.Addr(0x1f000100, "Address for cpu")
+    dist_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to distributor")
+    cpu_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to cpu interface")
+    int_latency = Param.Latency('10ns', "Delay for interrupt to get to CPU")
+    it_lines = Param.UInt32(128, "Number of interrupt lines supported (max = 1020)")
+
index f2fc9c0af2055da3586b12050e3265c34ae12adc..f01572e4087517957814e2d3c48cf97d69c61a09 100644 (file)
@@ -50,6 +50,7 @@ from Platform import Platform
 from Terminal import Terminal
 from Uart import Uart
 from SimpleMemory import SimpleMemory
+from Gic import *
 
 class AmbaDevice(BasicPioDevice):
     type = 'AmbaDevice'
@@ -61,7 +62,7 @@ class AmbaIntDevice(AmbaDevice):
     type = 'AmbaIntDevice'
     abstract = True
     cxx_header = "dev/arm/amba_device.hh"
-    gic = Param.Gic(Parent.any, "Gic to use for interrupting")
+    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
     int_num = Param.UInt32("Interrupt number that connects to GIC")
     int_delay = Param.Latency("100ns",
             "Time between action and interrupt generation by device")
@@ -72,7 +73,7 @@ class AmbaDmaDevice(DmaDevice):
     cxx_header = "dev/arm/amba_device.hh"
     pio_addr = Param.Addr("Address for AMBA slave interface")
     pio_latency = Param.Latency("10ns", "Time between action and write/read result by AMBA DMA Device")
-    gic = Param.Gic(Parent.any, "Gic to use for interrupting")
+    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
     int_num = Param.UInt32("Interrupt number that connects to GIC")
     amba_id = Param.UInt32("ID of AMBA device for kernel detection")
 
@@ -87,17 +88,6 @@ class RealViewCtrl(BasicPioDevice):
     proc_id1 = Param.UInt32(0x0C000222, "Processor ID, SYS_PROCID1")
     idreg = Param.UInt32(0x00000000, "ID Register, SYS_ID")
 
-class Gic(PioDevice):
-    type = 'Gic'
-    cxx_header = "dev/arm/gic.hh"
-    platform = Param.Platform(Parent.any, "Platform this device is part of.")
-    dist_addr = Param.Addr(0x1f001000, "Address for distributor")
-    cpu_addr = Param.Addr(0x1f000100, "Address for cpu")
-    dist_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to distributor")
-    cpu_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to cpu interface")
-    int_latency = Param.Latency('10ns', "Delay for interrupt to get to CPU")
-    it_lines = Param.UInt32(128, "Number of interrupt lines supported (max = 1020)")
-
 class AmbaFake(AmbaDevice):
     type = 'AmbaFake'
     cxx_header = "dev/arm/amba_fake.hh"
@@ -107,7 +97,7 @@ class AmbaFake(AmbaDevice):
 class Pl011(Uart):
     type = 'Pl011'
     cxx_header = "dev/arm/pl011.hh"
-    gic = Param.Gic(Parent.any, "Gic to use for interrupting")
+    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
     int_num = Param.UInt32("Interrupt number that connects to GIC")
     end_on_eot = Param.Bool(False, "End the simulation when a EOT is received on the UART")
     int_delay = Param.Latency("100ns", "Time between action and interrupt generation by UART")
@@ -115,7 +105,7 @@ class Pl011(Uart):
 class Sp804(AmbaDevice):
     type = 'Sp804'
     cxx_header = "dev/arm/timer_sp804.hh"
-    gic = Param.Gic(Parent.any, "Gic to use for interrupting")
+    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
     int_num0 = Param.UInt32("Interrupt number that connects to GIC")
     clock0 = Param.Clock('1MHz', "Clock speed of the input")
     int_num1 = Param.UInt32("Interrupt number that connects to GIC")
@@ -125,7 +115,7 @@ class Sp804(AmbaDevice):
 class CpuLocalTimer(BasicPioDevice):
     type = 'CpuLocalTimer'
     cxx_header = "dev/arm/timer_cpulocal.hh"
-    gic = Param.Gic(Parent.any, "Gic to use for interrupting")
+    gic = Param.BaseGic(Parent.any, "Gic to use for interrupting")
     int_num_timer = Param.UInt32("Interrrupt number used per-cpu to GIC")
     int_num_watchdog = Param.UInt32("Interrupt number for per-cpu watchdog to GIC")
     # Override the default clock
@@ -174,7 +164,7 @@ class RealView(Platform):
 class RealViewPBX(RealView):
     uart = Pl011(pio_addr=0x10009000, int_num=44)
     realview_io = RealViewCtrl(pio_addr=0x10000000)
-    gic = Gic()
+    gic = Pl390()
     timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
     timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
     local_cpu_timer = CpuLocalTimer(int_num_timer=29, int_num_watchdog=30, pio_addr=0x1f000600)
@@ -262,7 +252,7 @@ class RealViewPBX(RealView):
 class RealViewEB(RealView):
     uart = Pl011(pio_addr=0x10009000, int_num=44)
     realview_io = RealViewCtrl(pio_addr=0x10000000)
-    gic = Gic(dist_addr=0x10041000, cpu_addr=0x10040000)
+    gic = Pl390(dist_addr=0x10041000, cpu_addr=0x10040000)
     timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
     timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
     clcd   = Pl111(pio_addr=0x10020000, int_num=23)
@@ -338,7 +328,7 @@ class VExpress_EMM(RealView):
     pci_cfg_base = 0x30000000
     uart = Pl011(pio_addr=0x1c090000, int_num=37)
     realview_io = RealViewCtrl(proc_id0=0x14000000, proc_id1=0x14000000, pio_addr=0x1C010000)
-    gic = Gic(dist_addr=0x2C001000, cpu_addr=0x2C002000)
+    gic = Pl390(dist_addr=0x2C001000, cpu_addr=0x2C002000)
     local_cpu_timer = CpuLocalTimer(int_num_timer=29, int_num_watchdog=30, pio_addr=0x2C080000)
     timer0 = Sp804(int_num0=34, int_num1=34, pio_addr=0x1C110000, clock0='1MHz', clock1='1MHz')
     timer1 = Sp804(int_num0=35, int_num1=35, pio_addr=0x1C120000, clock0='1MHz', clock1='1MHz')
index a6ead28bea132afa9ed4d93c2c5e9681fe255f67..048fe24443d4b44bc00cacc1de313127882e100f 100644 (file)
 Import('*')
 
 if env['TARGET_ISA'] == 'arm':
+    SimObject('Gic.py')
     SimObject('RealView.py')
 
     Source('a9scu.cc')
     Source('amba_device.cc')
     Source('amba_fake.cc')
-    Source('gic.cc')
+    Source('base_gic.cc')
+    Source('gic_pl390.cc')
     Source('pl011.cc')
     Source('pl111.cc')
     Source('kmi.cc')
index 92dfed541d5c6568647610a53273aae6a1ff9858..6a3ed1c9e3d5cf016cccd57d11dd633029073b2f 100644 (file)
@@ -49,7 +49,7 @@
 #ifndef __DEV_ARM_AMBA_DEVICE_HH__
 #define __DEV_ARM_AMBA_DEVICE_HH__
 
-#include "dev/arm/gic.hh"
+#include "dev/arm/base_gic.hh"
 #include "dev/dma_device.hh"
 #include "dev/io_device.hh"
 #include "mem/packet.hh"
@@ -86,7 +86,7 @@ class AmbaIntDevice : public AmbaDevice
 {
   protected:
     int intNum;
-    Gic *gic;
+    BaseGic *gic;
     Tick intDelay;
 
   public:
@@ -102,7 +102,7 @@ class AmbaDmaDevice : public DmaDevice
     Addr     pioSize;
     Tick     pioDelay;
     int      intNum;
-    Gic      *gic;
+    BaseGic  *gic;
 
   public:
     typedef AmbaDmaDeviceParams Params;
diff --git a/src/dev/arm/base_gic.cc b/src/dev/arm/base_gic.cc
new file mode 100644 (file)
index 0000000..47e2110
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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: Andreas Sandberg
+ */
+
+#include "dev/arm/base_gic.hh"
+
+#include "params/BaseGic.hh"
+
+BaseGic::BaseGic(const Params *p)
+        : PioDevice(p),
+          platform(p->platform)
+{
+}
+
+BaseGic::~BaseGic()
+{
+}
+
+const BaseGic::Params *
+BaseGic::params() const
+{
+    return dynamic_cast<const Params *>(_params);
+}
diff --git a/src/dev/arm/base_gic.hh b/src/dev/arm/base_gic.hh
new file mode 100644 (file)
index 0000000..d177487
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2012 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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: Andreas Sandberg
+ */
+
+/** @file
+ * Base class for ARM GIC implementations
+ */
+
+#ifndef __DEV_ARM_BASE_GIC_H__
+#define __DEV_ARM_BASE_GIC_H__
+
+#include "dev/io_device.hh"
+
+class Platform;
+
+class BaseGic :  public PioDevice
+{
+  public:
+    typedef struct BaseGicParams Params;
+
+    BaseGic(const Params *p);
+    virtual ~BaseGic();
+
+    const Params * params() const;
+
+    /**
+     * Post an interrupt from a device that is connected to the GIC.
+     *
+     * Depending on the configuration, the GIC will pass this interrupt
+     * on through to a CPU.
+     *
+     * @param num number of interrupt to send
+     */
+    virtual void sendInt(uint32_t num) = 0;
+
+    /**
+     * Interface call for private peripheral interrupts.
+     *
+     * @param num number of interrupt to send
+     * @param cpu CPU to forward interrupt to
+     */
+    virtual void sendPPInt(uint32_t num, uint32_t cpu) = 0;
+
+    /**
+     * Clear an interrupt from a device that is connected to the GIC.
+     *
+     * Depending on the configuration, the GIC may de-assert it's CPU
+     * line.
+     *
+     * @param num number of interrupt to send
+     */
+    virtual void clearInt(uint32_t num) = 0;
+
+  protected:
+    /** Platform this GIC belongs to. */
+    Platform *platform;
+};
+
+#endif
diff --git a/src/dev/arm/gic.cc b/src/dev/arm/gic.cc
deleted file mode 100644 (file)
index 725199b..0000000
+++ /dev/null
@@ -1,843 +0,0 @@
-/*
- * Copyright (c) 2010 ARM Limited
- * All rights reserved
- *
- * The license below extends only to copyright in the software and shall
- * not be construed as granting a license to any other intellectual
- * property including but not limited to intellectual property relating
- * to a hardware implementation of the functionality of the software
- * licensed hereunder.  You may use the software subject to the license
- * terms below provided that you ensure that this notice is replicated
- * unmodified and in its entirety in all distributions of the software,
- * modified or unmodified, in source code or in binary form.
- *
- * Copyright (c) 2005 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: Ali Saidi
- *          Prakash Ramrakhyani
- */
-
-#include "base/trace.hh"
-#include "debug/Checkpoint.hh"
-#include "debug/GIC.hh"
-#include "debug/IPI.hh"
-#include "debug/Interrupt.hh"
-#include "dev/arm/gic.hh"
-#include "dev/arm/realview.hh"
-#include "dev/terminal.hh"
-#include "mem/packet.hh"
-#include "mem/packet_access.hh"
-
-Gic::Gic(const Params *p)
-    : PioDevice(p), platform(p->platform), distAddr(p->dist_addr),
-      cpuAddr(p->cpu_addr), distPioDelay(p->dist_pio_delay),
-      cpuPioDelay(p->cpu_pio_delay), intLatency(p->int_latency),
-      enabled(false), itLines(p->it_lines)
-{
-    itLinesLog2 = ceilLog2(itLines);
-
-    for (int x = 0; x < CPU_MAX; x++) {
-        cpuEnabled[x] = false;
-        cpuPriority[x] = 0xff;
-        cpuBpr[x] = 0;
-        // Initialize cpu highest int
-        cpuHighestInt[x] = SPURIOUS_INT;
-        postIntEvent[x] = new PostIntEvent(x, p->platform);
-    }
-    DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled[0],
-            cpuEnabled[1]);
-
-    for (int x = 0; x < INT_BITS_MAX; x++) {
-        intEnabled[x] = 0;
-        pendingInt[x] = 0;
-        activeInt[x] = 0;
-    }
-
-    for (int x = 0; x < INT_LINES_MAX; x++) {
-        intPriority[x] = 0;
-        cpuTarget[x] = 0;
-    }
-
-    for (int x = 0; x < INT_BITS_MAX*2; x++) {
-        intConfig[x] = 0;
-    }
-
-    for (int x = 0; x < SGI_MAX; x++) {
-        cpuSgiActive[x] = 0;
-        cpuSgiPending[x] = 0;
-    }
-    for (int x = 0; x < CPU_MAX; x++) {
-        cpuPpiActive[x] = 0;
-        cpuPpiPending[x] = 0;
-    }
-
-    for (int i = 0; i < CPU_MAX; i++) {
-        for (int j = 0; j < (SGI_MAX + PPI_MAX); j++) {
-            bankedIntPriority[i][j] = 0;
-        }
-    }
-
-    RealView *rv = dynamic_cast<RealView*>(p->platform);
-    assert(rv);
-    rv->setGic(this);
-
-}
-
-Tick
-Gic::read(PacketPtr pkt)
-{
-
-    Addr addr = pkt->getAddr();
-
-    if (addr >= distAddr && addr < distAddr + DIST_SIZE)
-        return readDistributor(pkt);
-    else if (addr >= cpuAddr && addr < cpuAddr + CPU_SIZE)
-        return readCpu(pkt);
-    else
-        panic("Read to unknown address %#x\n", pkt->getAddr());
-}
-
-
-Tick
-Gic::write(PacketPtr pkt)
-{
-
-    Addr addr = pkt->getAddr();
-
-    if (addr >= distAddr && addr < distAddr + DIST_SIZE)
-        return writeDistributor(pkt);
-    else if (addr >= cpuAddr && addr < cpuAddr + CPU_SIZE)
-        return writeCpu(pkt);
-    else
-        panic("Write to unknown address %#x\n", pkt->getAddr());
-}
-
-Tick
-Gic::readDistributor(PacketPtr pkt)
-{
-    Addr daddr = pkt->getAddr() - distAddr;
-    pkt->allocate();
-
-    int ctx_id = pkt->req->contextId();
-
-    DPRINTF(GIC, "gic distributor read register %#x\n", daddr);
-
-    if (daddr >= ICDISER_ST && daddr < ICDISER_ED + 4) {
-        assert((daddr-ICDISER_ST) >> 2 < 32);
-        pkt->set<uint32_t>(intEnabled[(daddr-ICDISER_ST)>>2]);
-        goto done;
-    }
-
-    if (daddr >= ICDICER_ST && daddr < ICDICER_ED + 4) {
-        assert((daddr-ICDICER_ST) >> 2 < 32);
-        pkt->set<uint32_t>(intEnabled[(daddr-ICDICER_ST)>>2]);
-        goto done;
-    }
-
-    if (daddr >= ICDISPR_ST && daddr < ICDISPR_ED + 4) {
-        assert((daddr-ICDISPR_ST) >> 2 < 32);
-        pkt->set<uint32_t>(pendingInt[(daddr-ICDISPR_ST)>>2]);
-        goto done;
-    }
-
-    if (daddr >= ICDICPR_ST && daddr < ICDICPR_ED + 4) {
-        assert((daddr-ICDICPR_ST) >> 2 < 32);
-        pkt->set<uint32_t>(pendingInt[(daddr-ICDICPR_ST)>>2]);
-        goto done;
-    }
-
-    if (daddr >= ICDABR_ST && daddr < ICDABR_ED + 4) {
-        assert((daddr-ICDABR_ST) >> 2 < 32);
-        pkt->set<uint32_t>(activeInt[(daddr-ICDABR_ST)>>2]);
-        goto done;
-    }
-
-    if (daddr >= ICDIPR_ST && daddr < ICDIPR_ED + 4) {
-        Addr int_num;
-        int_num = daddr - ICDIPR_ST;
-        assert(int_num < INT_LINES_MAX);
-        DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n",int_num);
-
-        uint8_t* int_p;
-        if (int_num < (SGI_MAX + PPI_MAX))
-            int_p = bankedIntPriority[ctx_id];
-        else
-            int_p = intPriority;
-
-        switch (pkt->getSize()) {
-          case 1:
-            pkt->set<uint8_t>(int_p[int_num]);
-            break;
-          case 2:
-            assert((int_num + 1) < INT_LINES_MAX);
-            pkt->set<uint16_t>(int_p[int_num] |
-                               int_p[int_num+1] << 8);
-            break;
-          case 4:
-            assert((int_num + 3) < INT_LINES_MAX);
-            pkt->set<uint32_t>(int_p[int_num] |
-                               int_p[int_num+1] << 8 |
-                               int_p[int_num+2] << 16 |
-                               int_p[int_num+3] << 24);
-            break;
-          default:
-            panic("Invalid size while reading priority regs in GIC: %d\n",
-                   pkt->getSize());
-        }
-        goto done;
-    }
-
-    if (daddr >= ICDIPTR_ST && daddr < ICDIPTR_ED + 4) {
-        Addr int_num;
-        int_num = (daddr-ICDIPTR_ST) ;
-        DPRINTF(GIC, "Reading processor target register for int# %#x \n",
-                 int_num);
-        assert(int_num < INT_LINES_MAX);
-
-        // First 31 interrupts only target single processor (SGI)
-        if (int_num > 31) {
-            if (pkt->getSize() == 1) {
-                pkt->set<uint8_t>(cpuTarget[int_num]);
-            } else {
-                assert(pkt->getSize() == 4);
-                int_num = mbits(int_num, 31, 2);
-                pkt->set<uint32_t>(cpuTarget[int_num] |
-                                   cpuTarget[int_num+1] << 8 |
-                                   cpuTarget[int_num+2] << 16 |
-                                   cpuTarget[int_num+3] << 24) ;
-            }
-        } else {
-            int ctx_id = pkt->req->contextId();
-            assert(ctx_id < sys->numRunningContexts());
-            pkt->set<uint32_t>(ctx_id);
-        }
-        goto done;
-    }
-
-    if (daddr >= ICDICFR_ST && daddr < ICDICFR_ED + 4) {
-        assert((daddr-ICDICFR_ST) >> 2 < 64);
-        /** @todo software generated interrutps and PPIs
-         * can't be configured in some ways
-         */
-        pkt->set<uint32_t>(intConfig[(daddr-ICDICFR_ST)>>2]);
-        goto done;
-    }
-
-    switch(daddr) {
-      case ICDDCR:
-        pkt->set<uint32_t>(enabled);
-        break;
-      case ICDICTR:
-        uint32_t tmp;
-        tmp = ((sys->numRunningContexts() - 1) << 5) |
-              (itLines/INT_BITS_MAX -1);
-        pkt->set<uint32_t>(tmp);
-        break;
-      default:
-        panic("Tried to read Gic distributor at offset %#x\n", daddr);
-        break;
-    }
-done:
-    pkt->makeAtomicResponse();
-    return distPioDelay;
-}
-
-Tick
-Gic::readCpu(PacketPtr pkt)
-{
-    Addr daddr = pkt->getAddr() - cpuAddr;
-    pkt->allocate();
-
-    assert(pkt->req->hasContextId());
-    int ctx_id = pkt->req->contextId();
-    assert(ctx_id < sys->numRunningContexts());
-
-    DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr,
-            ctx_id);
-
-    switch(daddr) {
-      case ICCICR:
-        pkt->set<uint32_t>(cpuEnabled[ctx_id]);
-        break;
-      case ICCPMR:
-        pkt->set<uint32_t>(cpuPriority[ctx_id]);
-        break;
-      case ICCBPR:
-        pkt->set<uint32_t>(cpuBpr[ctx_id]);
-        break;
-      case ICCIAR:
-        if (enabled && cpuEnabled[ctx_id]) {
-            int active_int = cpuHighestInt[ctx_id];
-            IAR iar = 0;
-            iar.ack_id = active_int;
-            iar.cpu_id = 0;
-            if (active_int < SGI_MAX) {
-                // this is a software interrupt from another CPU
-                if (!cpuSgiPending[active_int])
-                    panic("Interrupt %d active but no CPU generated it?\n",
-                            active_int);
-                for (int x = 0; x < CPU_MAX; x++) {
-                    // See which CPU generated the interrupt
-                    uint8_t cpugen =
-                        bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x);
-                    if (cpugen & (1 << ctx_id)) {
-                        iar.cpu_id = x;
-                        break;
-                    }
-                }
-                uint64_t sgi_num = ULL(1) << (ctx_id + 8 * iar.cpu_id);
-                cpuSgiActive[iar.ack_id] |= sgi_num;
-                cpuSgiPending[iar.ack_id] &= ~sgi_num;
-            } else if (active_int < (SGI_MAX + PPI_MAX) ) {
-                uint32_t int_num = 1 << (cpuHighestInt[ctx_id] - SGI_MAX);
-                cpuPpiActive[ctx_id] |= int_num;
-                updateRunPri();
-                cpuPpiPending[ctx_id] &= ~int_num;
-
-            } else {
-                uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx_id]);
-                activeInt[intNumToWord(cpuHighestInt[ctx_id])] |= int_num;
-                updateRunPri();
-                pendingInt[intNumToWord(cpuHighestInt[ctx_id])] &= ~int_num;
-            }
-
-            DPRINTF(Interrupt,"CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
-                    ctx_id, iar.ack_id, iar.cpu_id, iar);
-            cpuHighestInt[ctx_id] = SPURIOUS_INT;
-            updateIntState(-1);
-            pkt->set<uint32_t>(iar);
-            platform->intrctrl->clear(ctx_id, ArmISA::INT_IRQ, 0);
-        } else {
-             pkt->set<uint32_t>(SPURIOUS_INT);
-        }
-
-        break;
-      case ICCRPR:
-        pkt->set<uint32_t>(iccrpr[0]);
-        break;
-      case ICCHPIR:
-        pkt->set<uint32_t>(0);
-        panic("Need to implement HPIR");
-        break;
-      default:
-        panic("Tried to read Gic cpu at offset %#x\n", daddr);
-        break;
-    }
-    pkt->makeAtomicResponse();
-    return cpuPioDelay;
-}
-
-
-Tick
-Gic::writeDistributor(PacketPtr pkt)
-{
-    Addr daddr = pkt->getAddr() - distAddr;
-    pkt->allocate();
-
-    assert(pkt->req->hasContextId());
-    int ctx_id = pkt->req->contextId();
-
-    DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n",
-            daddr, pkt->getSize(), pkt->get<uint32_t>());
-
-    if (daddr >= ICDISER_ST && daddr < ICDISER_ED + 4) {
-        assert((daddr-ICDISER_ST) >> 2 < 32);
-        intEnabled[(daddr-ICDISER_ST) >> 2] |= pkt->get<uint32_t>();
-        goto done;
-    }
-
-    if (daddr >= ICDICER_ST && daddr < ICDICER_ED + 4) {
-        assert((daddr-ICDICER_ST) >> 2 < 32);
-        intEnabled[(daddr-ICDICER_ST) >> 2] &= ~pkt->get<uint32_t>();
-        goto done;
-    }
-
-    if (daddr >= ICDISPR_ST && daddr < ICDISPR_ED + 4) {
-        assert((daddr-ICDISPR_ST) >> 2 < 32);
-        pendingInt[(daddr-ICDISPR_ST) >> 2] |= pkt->get<uint32_t>();
-        pendingInt[0] &= SGI_MASK; // Don't allow SGIs to be changed
-        updateIntState((daddr-ICDISPR_ST) >> 2);
-        goto done;
-    }
-
-    if (daddr >= ICDICPR_ST && daddr < ICDICPR_ED + 4) {
-        assert((daddr-ICDICPR_ST) >> 2 < 32);
-        pendingInt[(daddr-ICDICPR_ST) >> 2] &= ~pkt->get<uint32_t>();
-        pendingInt[0] &= SGI_MASK; // Don't allow SGIs to be changed
-        updateIntState((daddr-ICDICPR_ST) >> 2);
-        goto done;
-    }
-
-    if (daddr >= ICDIPR_ST && daddr < ICDIPR_ED + 4) {
-        Addr int_num = daddr - ICDIPR_ST;
-        assert(int_num < INT_LINES_MAX);
-        uint8_t* int_p;
-        if (int_num < (SGI_MAX + PPI_MAX))
-            int_p = bankedIntPriority[ctx_id];
-        else
-            int_p = intPriority;
-        uint32_t tmp;
-        switch(pkt->getSize()) {
-          case 1:
-            tmp = pkt->get<uint8_t>();
-            int_p[int_num] = bits(tmp, 7, 0);
-            break;
-          case 2:
-            tmp = pkt->get<uint16_t>();
-            int_p[int_num] = bits(tmp, 7, 0);
-            int_p[int_num + 1] = bits(tmp, 15, 8);
-            break;
-          case 4:
-            tmp = pkt->get<uint32_t>();
-            int_p[int_num] = bits(tmp, 7, 0);
-            int_p[int_num + 1] = bits(tmp, 15, 8);
-            int_p[int_num + 2] = bits(tmp, 23, 16);
-            int_p[int_num + 3] = bits(tmp, 31, 24);
-            break;
-          default:
-            panic("Invalid size when writing to priority regs in Gic: %d\n",
-                   pkt->getSize());
-        }
-
-        updateIntState(-1);
-        updateRunPri();
-        goto done;
-    }
-
-    if (daddr >= ICDIPTR_ST && daddr < ICDIPTR_ED + 4) {
-        Addr int_num = (daddr-ICDIPTR_ST) ;
-        assert(int_num < INT_LINES_MAX);
-        // First 31 interrupts only target single processor
-        if (int_num >= SGI_MAX) {
-            if (pkt->getSize() == 1) {
-                uint8_t tmp = pkt->get<uint8_t>();
-                cpuTarget[int_num] = tmp & 0xff;
-            } else {
-                assert (pkt->getSize() == 4);
-                int_num = mbits(int_num, 31, 2);
-                uint32_t tmp = pkt->get<uint32_t>();
-                cpuTarget[int_num]   = bits(tmp, 7, 0);
-                cpuTarget[int_num+1] = bits(tmp, 15, 8);
-                cpuTarget[int_num+2] = bits(tmp, 23, 16);
-                cpuTarget[int_num+3] = bits(tmp, 31, 24);
-            }
-            updateIntState((daddr-ICDIPTR_ST)>>2);
-        }
-        goto done;
-    }
-
-    if (daddr >= ICDICFR_ST && daddr < ICDICFR_ED + 4) {
-        assert((daddr-ICDICFR_ST) >> 2 < 64);
-        intConfig[(daddr-ICDICFR_ST)>>2] = pkt->get<uint32_t>();
-        if (pkt->get<uint32_t>() & NN_CONFIG_MASK)
-            warn("GIC N:N mode selected and not supported at this time\n");
-        goto done;
-    }
-
-    switch(daddr) {
-      case ICDDCR:
-        enabled = pkt->get<uint32_t>();
-        DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled);
-        break;
-      case ICDSGIR:
-        softInt(ctx_id, pkt->get<uint32_t>());
-        break;
-      default:
-        panic("Tried to write Gic distributor at offset %#x\n", daddr);
-        break;
-    }
-
-done:
-    pkt->makeAtomicResponse();
-    return distPioDelay;
-}
-
-Tick
-Gic::writeCpu(PacketPtr pkt)
-{
-    Addr daddr = pkt->getAddr() - cpuAddr;
-    pkt->allocate();
-
-    assert(pkt->req->hasContextId());
-    int ctx_id = pkt->req->contextId();
-    IAR iar;
-
-    DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n",
-            ctx_id, daddr, pkt->get<uint32_t>());
-
-    switch(daddr) {
-      case ICCICR:
-        cpuEnabled[ctx_id] = pkt->get<uint32_t>();
-        break;
-      case ICCPMR:
-        cpuPriority[ctx_id] = pkt->get<uint32_t>();
-        break;
-      case ICCBPR:
-        cpuBpr[ctx_id] = pkt->get<uint32_t>();
-        break;
-      case ICCEOIR:
-        iar = pkt->get<uint32_t>();
-        if (iar.ack_id < SGI_MAX) {
-            // Clear out the bit that corrseponds to the cleared int
-            uint64_t clr_int = ULL(1) << (ctx_id + 8 * iar.cpu_id);
-            if (!(cpuSgiActive[iar.ack_id] & clr_int))
-                panic("Done handling a SGI that isn't active?\n");
-            cpuSgiActive[iar.ack_id] &= ~clr_int;
-        } else if (iar.ack_id < (SGI_MAX + PPI_MAX) ) {
-            uint32_t int_num = 1 << (iar.ack_id - SGI_MAX);
-            if (!(cpuPpiActive[ctx_id] & int_num))
-                panic("CPU %d Done handling a PPI interrupt that isn't active?\n", ctx_id);
-            cpuPpiActive[ctx_id] &= ~int_num;
-        } else {
-            uint32_t int_num = 1 << intNumToBit(iar.ack_id);
-            if (!(activeInt[intNumToWord(iar.ack_id)] & int_num))
-                panic("Done handling interrupt that isn't active?\n");
-            activeInt[intNumToWord(iar.ack_id)] &= ~int_num;
-        }
-        updateRunPri();
-        DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
-                ctx_id, iar.ack_id, iar.cpu_id);
-        break;
-      default:
-        panic("Tried to write Gic cpu at offset %#x\n", daddr);
-        break;
-    }
-    if (cpuEnabled[ctx_id]) updateIntState(-1);
-    pkt->makeAtomicResponse();
-    return cpuPioDelay;
-}
-
-void
-Gic::softInt(int ctx_id, SWI swi)
-{
-    switch (swi.list_type) {
-      case 1:
-        // interrupt all
-        uint8_t cpu_list;
-        cpu_list = 0;
-        for (int x = 0; x < CPU_MAX; x++)
-            cpu_list |= cpuEnabled[x] ? 1 << x : 0;
-        swi.cpu_list = cpu_list;
-        break;
-      case 2:
-        // interrupt requesting cpu only
-        swi.cpu_list = 1 << ctx_id;
-        break;
-        // else interrupt cpus specified
-    }
-
-    DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx_id,
-            swi.cpu_list);
-    for (int i = 0; i < CPU_MAX; i++) {
-        DPRINTF(IPI, "Processing CPU %d\n", i);
-        if (!cpuEnabled[i])
-            continue;
-        if (swi.cpu_list & (1 << i))
-            cpuSgiPending[swi.sgi_id] |= (1 << i) << (8 * ctx_id);
-        DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id, cpuSgiPending[swi.sgi_id]);
-    }
-    updateIntState(-1);
-}
-
-uint64_t
-Gic::genSwiMask(int cpu)
-{
-    if (cpu > 7)
-        panic("Invalid CPU ID\n");
-    return ULL(0x0101010101010101) << cpu;
-}
-
-void
-Gic::updateIntState(int hint)
-{
-    for (int cpu = 0; cpu < CPU_MAX; cpu++) {
-        if (!cpuEnabled[cpu])
-            continue;
-        if (cpu >= sys->numContexts())
-            break;
-
-        /*@todo use hint to do less work. */
-        int highest_int = SPURIOUS_INT;
-        // Priorities below that set in ICCPMR can be ignored
-        uint8_t highest_pri = cpuPriority[cpu];
-
-        // Check SGIs
-        for (int swi = 0; swi < SGI_MAX; swi++) {
-            if (!cpuSgiPending[swi])
-                continue;
-            if (cpuSgiPending[swi] & genSwiMask(cpu))
-                if (highest_pri > bankedIntPriority[cpu][swi]) {
-                    highest_pri = bankedIntPriority[cpu][swi];
-                    highest_int = swi;
-                }
-        }
-
-        // Check PPIs
-        if (cpuPpiPending[cpu]) {
-        for (int ppi = 0; ppi < PPI_MAX; ppi++) {
-            if (cpuPpiPending[cpu] & (1 << ppi))
-                if (highest_pri > bankedIntPriority[cpu][SGI_MAX + ppi]) {
-                    highest_pri = bankedIntPriority[cpu][SGI_MAX + ppi];
-                    highest_int = SGI_MAX + ppi;
-                }
-            }
-        }
-
-        bool mp_sys = sys->numRunningContexts() > 1;
-        // Check other ints
-        for (int x = 0; x < (itLines/INT_BITS_MAX); x++) {
-            if (intEnabled[x] & pendingInt[x]) {
-                for (int y = 0; y < INT_BITS_MAX; y++) {
-                   uint32_t int_nm = x * INT_BITS_MAX + y;
-                   DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm);
-                    /* Set current pending int as highest int for current cpu
-                       if the interrupt's priority higher than current prioirty
-                       and if currrent cpu is the target (for mp configs only)
-                     */
-                    if ((bits(intEnabled[x], y) & bits(pendingInt[x], y)) &&
-                        (intPriority[int_nm] < highest_pri))
-                        if ( (!mp_sys) || (cpuTarget[int_nm] & (1 << cpu))) {
-                            highest_pri = intPriority[int_nm];
-                            highest_int = int_nm;
-                        }
-                }
-            }
-        }
-
-        cpuHighestInt[cpu] = highest_int;
-
-        if (highest_int == SPURIOUS_INT)
-            continue;
-
-        /* @todo make this work for more than one cpu, need to handle 1:N, N:N
-         * models */
-        if (enabled && cpuEnabled[cpu] && (highest_pri < cpuPriority[cpu]) &&
-            !(activeInt[intNumToWord(highest_int)]
-            & (1 << intNumToBit(highest_int)))) {
-
-            DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int,
-                    cpu);
-            postInt(cpu, curTick() + intLatency);
-        }
-    }
-}
-
-void
-Gic::updateRunPri()
-{
-    for (int cpu = 0; cpu < CPU_MAX; cpu++) {
-        if (!cpuEnabled[cpu])
-            continue;
-        uint8_t maxPriority = 0xff;
-        for (int i = 0; i < itLines; i++){
-            if (i < SGI_MAX) {
-                if ((cpuSgiActive[i] & genSwiMask(cpu)) &&
-                        (bankedIntPriority[cpu][i] < maxPriority))
-                    maxPriority = bankedIntPriority[cpu][i];
-            } else if (i < (SGI_MAX + PPI_MAX)) {
-                if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) &&
-                        (bankedIntPriority[cpu][i] < maxPriority))
-                    maxPriority = bankedIntPriority[cpu][i];
-
-            } else {
-                if (activeInt[intNumToWord(i)] & (1 << intNumToBit(i)))
-                    if (intPriority[i] < maxPriority)
-                        maxPriority = intPriority[i];
-            }
-        }
-        iccrpr[cpu] = maxPriority;
-    }
-}
-
-void
-Gic::sendInt(uint32_t num)
-{
-    DPRINTF(Interrupt, "Received Interupt number %d,  cpuTarget %#x: \n",
-            num, cpuTarget[num]);
-    if (cpuTarget[num] & (cpuTarget[num] - 1))
-        panic("Multiple targets for peripheral interrupts is not supported\n");
-    pendingInt[intNumToWord(num)] |= 1 << intNumToBit(num);
-    updateIntState(intNumToWord(num));
-
-}
-
-void
-Gic::sendPPInt(uint32_t num, uint32_t cpu)
-{
-    DPRINTF(Interrupt, "Received Interrupt number %d, cpuTarget %#x: \n",
-            num, cpu);
-    cpuPpiPending[cpu] |= 1 << (num - SGI_MAX);
-    updateIntState(intNumToWord(num));
-}
-
-void
-Gic::clearInt(uint32_t number)
-{
-    /* @todo assume edge triggered only at the moment. Nothing to do. */
-}
-
-void
-Gic::postInt(uint32_t cpu, Tick when)
-{
-    if (!(postIntEvent[cpu]->scheduled()))
-        eventq->schedule(postIntEvent[cpu], when);
-}
-
-AddrRangeList
-Gic::getAddrRanges() const
-{
-    AddrRangeList ranges;
-    ranges.push_back(RangeSize(distAddr, DIST_SIZE));
-    ranges.push_back(RangeSize(cpuAddr, CPU_SIZE));
-    return ranges;
-}
-
-
-void
-Gic::serialize(std::ostream &os)
-{
-    DPRINTF(Checkpoint, "Serializing Arm GIC\n");
-
-    SERIALIZE_SCALAR(distAddr);
-    SERIALIZE_SCALAR(cpuAddr);
-    SERIALIZE_SCALAR(distPioDelay);
-    SERIALIZE_SCALAR(cpuPioDelay);
-    SERIALIZE_SCALAR(enabled);
-    SERIALIZE_SCALAR(itLines);
-    SERIALIZE_SCALAR(itLinesLog2);
-    SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX);
-    SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX);
-    SERIALIZE_ARRAY(activeInt, INT_BITS_MAX);
-    SERIALIZE_ARRAY(iccrpr, CPU_MAX);
-    SERIALIZE_ARRAY(intPriority, INT_LINES_MAX);
-    SERIALIZE_ARRAY(cpuTarget, INT_LINES_MAX);
-    SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
-    SERIALIZE_ARRAY(cpuEnabled, CPU_MAX);
-    SERIALIZE_ARRAY(cpuPriority, CPU_MAX);
-    SERIALIZE_ARRAY(cpuBpr, CPU_MAX);
-    SERIALIZE_ARRAY(cpuHighestInt, CPU_MAX);
-    SERIALIZE_ARRAY(cpuSgiActive, SGI_MAX);
-    SERIALIZE_ARRAY(cpuSgiPending, SGI_MAX);
-    SERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
-    SERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
-    SERIALIZE_ARRAY(*bankedIntPriority, CPU_MAX * (SGI_MAX + PPI_MAX));
-    SERIALIZE_SCALAR(irqEnable);
-    Tick interrupt_time[CPU_MAX];
-    for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
-        interrupt_time[cpu] = 0;
-        if (postIntEvent[cpu]->scheduled()) {
-            interrupt_time[cpu] = postIntEvent[cpu]->when();
-        }
-    }
-    SERIALIZE_ARRAY(interrupt_time, CPU_MAX);
-
-}
-
-void
-Gic::unserialize(Checkpoint *cp, const std::string &section)
-{
-    DPRINTF(Checkpoint, "Unserializing Arm GIC\n");
-
-    UNSERIALIZE_SCALAR(distAddr);
-    UNSERIALIZE_SCALAR(cpuAddr);
-    UNSERIALIZE_SCALAR(distPioDelay);
-    UNSERIALIZE_SCALAR(cpuPioDelay);
-    UNSERIALIZE_SCALAR(enabled);
-    UNSERIALIZE_SCALAR(itLines);
-    UNSERIALIZE_SCALAR(itLinesLog2);
-    UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX);
-    UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX);
-    UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX);
-    UNSERIALIZE_ARRAY(iccrpr, CPU_MAX);
-    UNSERIALIZE_ARRAY(intPriority, INT_LINES_MAX);
-    UNSERIALIZE_ARRAY(cpuTarget, INT_LINES_MAX);
-    UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
-    UNSERIALIZE_ARRAY(cpuEnabled, CPU_MAX);
-    UNSERIALIZE_ARRAY(cpuPriority, CPU_MAX);
-    UNSERIALIZE_ARRAY(cpuBpr, CPU_MAX);
-    UNSERIALIZE_ARRAY(cpuHighestInt, CPU_MAX);
-    UNSERIALIZE_ARRAY(cpuSgiActive, SGI_MAX);
-    UNSERIALIZE_ARRAY(cpuSgiPending, SGI_MAX);
-    UNSERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
-    UNSERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
-    UNSERIALIZE_ARRAY(*bankedIntPriority, CPU_MAX * (SGI_MAX + PPI_MAX));
-    UNSERIALIZE_SCALAR(irqEnable);
-
-    Tick interrupt_time[CPU_MAX];
-    UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX);
-
-    for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
-        if (interrupt_time[cpu])
-            schedule(postIntEvent[cpu], interrupt_time[cpu]);
-    }
-
-}
-
-Gic *
-GicParams::create()
-{
-    return new Gic(this);
-}
-
-/* Functions for debugging and testing */
-void
-Gic::driveSPI(unsigned int spiVect)
-{
-    DPRINTF(GIC, "Received SPI Vector:%x Enable: %d\n", spiVect, irqEnable);
-    pendingInt[1] |= spiVect;
-    if (irqEnable && enabled) {
-        updateIntState(-1);
-    }
-}
-
-void
-Gic::driveIrqEn( bool state)
-{
-    irqEnable = state;
-    DPRINTF(GIC, " Enabling Irq\n");
-    updateIntState(-1);
-}
-
-void
-Gic::driveLegIRQ(bool state)
-{
-    if (irqEnable && !(!enabled && cpuEnabled[0])) {
-        if (state) {
-            DPRINTF(GIC, "Driving Legacy Irq\n");
-            platform->intrctrl->post(0, ArmISA::INT_IRQ, 0);
-        }
-        else platform->intrctrl->clear(0, ArmISA::INT_IRQ, 0);
-    }
-}
-
-void
-Gic::driveLegFIQ(bool state)
-{
-    if (state)
-        platform->intrctrl->post(0, ArmISA::INT_FIQ, 0);
-    else platform->intrctrl->clear(0, ArmISA::INT_FIQ, 0);
-}
diff --git a/src/dev/arm/gic.hh b/src/dev/arm/gic.hh
deleted file mode 100644 (file)
index 02448f6..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (c) 2010 ARM Limited
- * All rights reserved
- *
- * The license below extends only to copyright in the software and shall
- * not be construed as granting a license to any other intellectual
- * property including but not limited to intellectual property relating
- * to a hardware implementation of the functionality of the software
- * licensed hereunder.  You may use the software subject to the license
- * terms below provided that you ensure that this notice is replicated
- * unmodified and in its entirety in all distributions of the software,
- * modified or unmodified, in source code or in binary form.
- *
- * Copyright (c) 2005 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: Ali Saidi
- */
-
-
-/** @file
- * Implementiation of a PL390 GIC
- */
-
-#ifndef __DEV_ARM_GIC_H__
-#define __DEV_ARM_GIC_H__
-
-#include "base/bitunion.hh"
-#include "dev/io_device.hh"
-#include "dev/platform.hh"
-#include "cpu/intr_control.hh"
-#include "params/Gic.hh"
-
-/** @todo this code only assumes one processor for now. Low word
- * of intEnabled and pendingInt need to be replicated per CPU.
- * bottom 31 interrupts (7 words) need to be replicated for
- * for interrupt priority register, processor target registers
- * interrupt config registers  */
-
-class Gic : public PioDevice
-{
-  protected:
-    // distributor memory addresses
-    static const int ICDDCR     = 0x000; // control register
-    static const int ICDICTR    = 0x004; // controller type
-    static const int ICDIIDR    = 0x008; // implementer id
-    static const int ICDISER_ST = 0x100; // interrupt set enable
-    static const int ICDISER_ED = 0x17c;
-    static const int ICDICER_ST = 0x180; // interrupt clear enable
-    static const int ICDICER_ED = 0x1fc;
-    static const int ICDISPR_ST = 0x200; // set pending interrupt
-    static const int ICDISPR_ED = 0x27c;
-    static const int ICDICPR_ST = 0x280; // clear pending interrupt
-    static const int ICDICPR_ED = 0x2fc;
-    static const int ICDABR_ST  = 0x300; // active bit registers
-    static const int ICDABR_ED  = 0x37c;
-    static const int ICDIPR_ST  = 0x400; // interrupt priority registers
-    static const int ICDIPR_ED  = 0x7f8;
-    static const int ICDIPTR_ST = 0x800; // processor target registers
-    static const int ICDIPTR_ED = 0xbf8;
-    static const int ICDICFR_ST = 0xc00; // interrupt config registers
-    static const int ICDICFR_ED = 0xcfc;
-    static const int ICDSGIR    = 0xf00; // software generated interrupt
-    static const int DIST_SIZE  = 0xfff;
-
-    // cpu memory addressesa
-    static const int ICCICR  = 0x00; // CPU control register
-    static const int ICCPMR  = 0x04; // Interrupt priority mask
-    static const int ICCBPR  = 0x08; // binary point register
-    static const int ICCIAR  = 0x0C; // interrupt ack register
-    static const int ICCEOIR = 0x10; // end of interrupt
-    static const int ICCRPR  = 0x14; // runing priority
-    static const int ICCHPIR = 0x18; // highest pending interrupt
-    static const int ICCABPR = 0x1c; // aliased binary point
-    static const int ICCIIDR = 0xfc; // cpu interface id register
-    static const int CPU_SIZE  = 0xff;
-
-    static const int SGI_MAX = 16;  // Number of Software Gen Interrupts
-    static const int PPI_MAX = 16;  // Number of Private Peripheral Interrupts
-
-    /** Mask off SGI's when setting/clearing pending bits */
-    static const int SGI_MASK = 0xFFFF0000;
-
-    /** Mask for bits that config N:N mode in ICDICFR's */
-    static const int NN_CONFIG_MASK = 0x55555555;
-
-    static const int CPU_MAX = 8;   // Max number of supported CPU interfaces
-    static const int SPURIOUS_INT = 1023;
-    static const int INT_BITS_MAX = 32;
-    static const int INT_LINES_MAX = 1020;
-
-    BitUnion32(SWI)
-        Bitfield<3,0> sgi_id;
-        Bitfield<23,16> cpu_list;
-        Bitfield<25,24> list_type;
-    EndBitUnion(SWI)
-
-    BitUnion32(IAR)
-        Bitfield<9,0> ack_id;
-        Bitfield<12,10> cpu_id;
-    EndBitUnion(IAR)
-
-    Platform *platform;
-
-    /** Distributor address GIC listens at */
-    Addr distAddr;
-
-    /** CPU address GIC listens at */
-    /** @todo is this one per cpu? */
-    Addr cpuAddr;
-
-    /** Latency for a distributor operation */
-    Tick distPioDelay;
-
-    /** Latency for a cpu operation */
-    Tick cpuPioDelay;
-
-    /** Latency for a interrupt to get to CPU */
-    Tick intLatency;
-
-    /** Gic enabled */
-    bool enabled;
-
-    /** Number of itLines enabled */
-    uint32_t itLines;
-
-    uint32_t itLinesLog2;
-
-    /** interrupt enable bits for all possible 1020 interupts.
-     * one bit per interrupt, 32 bit per word = 32 words */
-    uint32_t intEnabled[INT_BITS_MAX];
-
-    /** interrupt pending bits for all possible 1020 interupts.
-     * one bit per interrupt, 32 bit per word = 32 words */
-    uint32_t pendingInt[INT_BITS_MAX];
-
-    /** interrupt active bits for all possible 1020 interupts.
-     * one bit per interrupt, 32 bit per word = 32 words */
-    uint32_t activeInt[INT_BITS_MAX];
-
-    /** read only running priroity register, 1 per cpu*/
-    uint32_t iccrpr[CPU_MAX];
-
-    /** an 8 bit priority (lower is higher priority) for each
-     * of the 1020 possible supported interrupts.
-     */
-    uint8_t intPriority[INT_LINES_MAX];
-
-    /** an 8 bit cpu target id for each shared peripheral interrupt
-     * of the 1020 possible supported interrupts.
-     */
-    uint8_t cpuTarget[INT_LINES_MAX];
-
-    /** 2 bit per interrupt signaling if it's level or edge sensitive
-     * and if it is 1:N or N:N */
-    uint32_t intConfig[INT_BITS_MAX*2];
-
-    /** CPU enabled */
-    bool cpuEnabled[CPU_MAX];
-
-    /** CPU priority */
-    uint8_t cpuPriority[CPU_MAX];
-
-    /** Binary point registers */
-    uint8_t cpuBpr[CPU_MAX];
-
-    /** highest interrupt that is interrupting CPU */
-    uint32_t cpuHighestInt[CPU_MAX];
-
-    /** One bit per cpu per software interrupt that is pending for each possible
-     * sgi source. Indexed by SGI number. Each byte in generating cpu id and
-     * bits in position is destination id. e.g. 0x4 = CPU 0 generated interrupt
-     * for CPU 2. */
-    uint64_t cpuSgiPending[SGI_MAX];
-    uint64_t cpuSgiActive[SGI_MAX];
-
-    /** One bit per private peripheral interrupt. Only upper 16 bits
-     * will be used since PPI interrupts are numberred from 16 to 32 */
-    uint32_t cpuPpiPending[CPU_MAX];
-    uint32_t cpuPpiActive[CPU_MAX];
-
-    /** Banked interrupt prioirty registers for SGIs and PPIs */
-    uint8_t bankedIntPriority[CPU_MAX][SGI_MAX + PPI_MAX];
-
-    /** IRQ Enable Used for debug */
-    bool irqEnable;
-
-    /** software generated interrupt
-     * @param data data to decode that indicates which cpus to interrupt
-     */
-    void softInt(int ctx_id, SWI swi);
-
-    /** See if some processor interrupt flags need to be enabled/disabled
-     * @param hint which set of interrupts needs to be checked
-     */
-    void updateIntState(int hint);
-
-    /** Update the register that records priority of the highest priority
-     *  active interrupt*/
-    void updateRunPri();
-
-    /** generate a bit mask to check cpuSgi for an interrupt. */
-    uint64_t genSwiMask(int cpu);
-
-    int intNumToWord(int num) const { return num >> 5; }
-    int intNumToBit(int num) const { return num % 32; }
-
-    /** Post an interrupt to a CPU
-     */
-    void postInt(uint32_t cpu, Tick when);
-
-    /** Event definition to post interrupt to CPU after a delay
-    */
-    class PostIntEvent : public Event
-    {
-      private:
-        uint32_t cpu;
-        Platform *platform;
-      public:
-        PostIntEvent( uint32_t c, Platform* p)
-            : cpu(c), platform(p)
-        { }
-        void process() { platform->intrctrl->post(cpu, ArmISA::INT_IRQ, 0);}
-        const char *description() const { return "Post Interrupt to CPU"; }
-    };
-    PostIntEvent *postIntEvent[CPU_MAX];
-
-  public:
-   typedef GicParams Params;
-   const Params *
-    params() const
-    {
-        return dynamic_cast<const Params *>(_params);
-    }
-    Gic(const Params *p);
-
-    /** Return the address ranges used by the Gic
-     * This is the distributor address + all cpu addresses
-     */
-    virtual AddrRangeList getAddrRanges() const;
-
-    /** A PIO read to the device, immediately split up into
-     * readDistributor() or readCpu()
-     */
-    virtual Tick read(PacketPtr pkt);
-
-    /** A PIO read to the device, immediately split up into
-     * writeDistributor() or writeCpu()
-     */
-    virtual Tick write(PacketPtr pkt);
-
-    /** Handle a read to the distributor poriton of the GIC
-     * @param pkt packet to respond to
-     */
-    Tick readDistributor(PacketPtr pkt);
-
-    /** Handle a read to the cpu poriton of the GIC
-     * @param pkt packet to respond to
-     */
-    Tick readCpu(PacketPtr pkt);
-
-    /** Handle a write to the distributor poriton of the GIC
-     * @param pkt packet to respond to
-     */
-    Tick writeDistributor(PacketPtr pkt);
-
-    /** Handle a write to the cpu poriton of the GIC
-     * @param pkt packet to respond to
-     */
-    Tick writeCpu(PacketPtr pkt);
-
-    /** Post an interrupt from a device that is connected to the Gic.
-     * Depending on the configuration, the gic will pass this interrupt
-     * on through to a CPU.
-     * @param number number of interrupt to send */
-    void sendInt(uint32_t number);
-
-    /** Interface call for private peripheral interrupts  */
-    void sendPPInt(uint32_t num, uint32_t cpu);
-
-    /** Clear an interrupt from a device that is connected to the Gic
-     * Depending on the configuration, the gic may de-assert it's cpu line
-     * @param number number of interrupt to send */
-    void clearInt(uint32_t number);
-
-    /* Various functions fer testing and debugging */
-    void driveSPI(uint32_t spi);
-    void driveLegIRQ(bool state);
-    void driveLegFIQ(bool state);
-    void driveIrqEn(bool state);
-
-    virtual void serialize(std::ostream &os);
-    virtual void unserialize(Checkpoint *cp, const std::string &section);
-
-};
-
-#endif //__DEV_ARM_GIC_H__
diff --git a/src/dev/arm/gic_pl390.cc b/src/dev/arm/gic_pl390.cc
new file mode 100644 (file)
index 0000000..0cd4359
--- /dev/null
@@ -0,0 +1,843 @@
+/*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2005 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: Ali Saidi
+ *          Prakash Ramrakhyani
+ */
+
+#include "base/trace.hh"
+#include "debug/Checkpoint.hh"
+#include "debug/GIC.hh"
+#include "debug/IPI.hh"
+#include "debug/Interrupt.hh"
+#include "dev/arm/gic_pl390.hh"
+#include "dev/arm/realview.hh"
+#include "dev/terminal.hh"
+#include "mem/packet.hh"
+#include "mem/packet_access.hh"
+
+Pl390::Pl390(const Params *p)
+    : BaseGic(p), distAddr(p->dist_addr),
+      cpuAddr(p->cpu_addr), distPioDelay(p->dist_pio_delay),
+      cpuPioDelay(p->cpu_pio_delay), intLatency(p->int_latency),
+      enabled(false), itLines(p->it_lines)
+{
+    itLinesLog2 = ceilLog2(itLines);
+
+    for (int x = 0; x < CPU_MAX; x++) {
+        cpuEnabled[x] = false;
+        cpuPriority[x] = 0xff;
+        cpuBpr[x] = 0;
+        // Initialize cpu highest int
+        cpuHighestInt[x] = SPURIOUS_INT;
+        postIntEvent[x] = new PostIntEvent(x, p->platform);
+    }
+    DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled[0],
+            cpuEnabled[1]);
+
+    for (int x = 0; x < INT_BITS_MAX; x++) {
+        intEnabled[x] = 0;
+        pendingInt[x] = 0;
+        activeInt[x] = 0;
+    }
+
+    for (int x = 0; x < INT_LINES_MAX; x++) {
+        intPriority[x] = 0;
+        cpuTarget[x] = 0;
+    }
+
+    for (int x = 0; x < INT_BITS_MAX*2; x++) {
+        intConfig[x] = 0;
+    }
+
+    for (int x = 0; x < SGI_MAX; x++) {
+        cpuSgiActive[x] = 0;
+        cpuSgiPending[x] = 0;
+    }
+    for (int x = 0; x < CPU_MAX; x++) {
+        cpuPpiActive[x] = 0;
+        cpuPpiPending[x] = 0;
+    }
+
+    for (int i = 0; i < CPU_MAX; i++) {
+        for (int j = 0; j < (SGI_MAX + PPI_MAX); j++) {
+            bankedIntPriority[i][j] = 0;
+        }
+    }
+
+    RealView *rv = dynamic_cast<RealView*>(p->platform);
+    assert(rv);
+    rv->setGic(this);
+
+}
+
+Tick
+Pl390::read(PacketPtr pkt)
+{
+
+    Addr addr = pkt->getAddr();
+
+    if (addr >= distAddr && addr < distAddr + DIST_SIZE)
+        return readDistributor(pkt);
+    else if (addr >= cpuAddr && addr < cpuAddr + CPU_SIZE)
+        return readCpu(pkt);
+    else
+        panic("Read to unknown address %#x\n", pkt->getAddr());
+}
+
+
+Tick
+Pl390::write(PacketPtr pkt)
+{
+
+    Addr addr = pkt->getAddr();
+
+    if (addr >= distAddr && addr < distAddr + DIST_SIZE)
+        return writeDistributor(pkt);
+    else if (addr >= cpuAddr && addr < cpuAddr + CPU_SIZE)
+        return writeCpu(pkt);
+    else
+        panic("Write to unknown address %#x\n", pkt->getAddr());
+}
+
+Tick
+Pl390::readDistributor(PacketPtr pkt)
+{
+    Addr daddr = pkt->getAddr() - distAddr;
+    pkt->allocate();
+
+    int ctx_id = pkt->req->contextId();
+
+    DPRINTF(GIC, "gic distributor read register %#x\n", daddr);
+
+    if (daddr >= ICDISER_ST && daddr < ICDISER_ED + 4) {
+        assert((daddr-ICDISER_ST) >> 2 < 32);
+        pkt->set<uint32_t>(intEnabled[(daddr-ICDISER_ST)>>2]);
+        goto done;
+    }
+
+    if (daddr >= ICDICER_ST && daddr < ICDICER_ED + 4) {
+        assert((daddr-ICDICER_ST) >> 2 < 32);
+        pkt->set<uint32_t>(intEnabled[(daddr-ICDICER_ST)>>2]);
+        goto done;
+    }
+
+    if (daddr >= ICDISPR_ST && daddr < ICDISPR_ED + 4) {
+        assert((daddr-ICDISPR_ST) >> 2 < 32);
+        pkt->set<uint32_t>(pendingInt[(daddr-ICDISPR_ST)>>2]);
+        goto done;
+    }
+
+    if (daddr >= ICDICPR_ST && daddr < ICDICPR_ED + 4) {
+        assert((daddr-ICDICPR_ST) >> 2 < 32);
+        pkt->set<uint32_t>(pendingInt[(daddr-ICDICPR_ST)>>2]);
+        goto done;
+    }
+
+    if (daddr >= ICDABR_ST && daddr < ICDABR_ED + 4) {
+        assert((daddr-ICDABR_ST) >> 2 < 32);
+        pkt->set<uint32_t>(activeInt[(daddr-ICDABR_ST)>>2]);
+        goto done;
+    }
+
+    if (daddr >= ICDIPR_ST && daddr < ICDIPR_ED + 4) {
+        Addr int_num;
+        int_num = daddr - ICDIPR_ST;
+        assert(int_num < INT_LINES_MAX);
+        DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n",int_num);
+
+        uint8_t* int_p;
+        if (int_num < (SGI_MAX + PPI_MAX))
+            int_p = bankedIntPriority[ctx_id];
+        else
+            int_p = intPriority;
+
+        switch (pkt->getSize()) {
+          case 1:
+            pkt->set<uint8_t>(int_p[int_num]);
+            break;
+          case 2:
+            assert((int_num + 1) < INT_LINES_MAX);
+            pkt->set<uint16_t>(int_p[int_num] |
+                               int_p[int_num+1] << 8);
+            break;
+          case 4:
+            assert((int_num + 3) < INT_LINES_MAX);
+            pkt->set<uint32_t>(int_p[int_num] |
+                               int_p[int_num+1] << 8 |
+                               int_p[int_num+2] << 16 |
+                               int_p[int_num+3] << 24);
+            break;
+          default:
+            panic("Invalid size while reading priority regs in GIC: %d\n",
+                   pkt->getSize());
+        }
+        goto done;
+    }
+
+    if (daddr >= ICDIPTR_ST && daddr < ICDIPTR_ED + 4) {
+        Addr int_num;
+        int_num = (daddr-ICDIPTR_ST) ;
+        DPRINTF(GIC, "Reading processor target register for int# %#x \n",
+                 int_num);
+        assert(int_num < INT_LINES_MAX);
+
+        // First 31 interrupts only target single processor (SGI)
+        if (int_num > 31) {
+            if (pkt->getSize() == 1) {
+                pkt->set<uint8_t>(cpuTarget[int_num]);
+            } else {
+                assert(pkt->getSize() == 4);
+                int_num = mbits(int_num, 31, 2);
+                pkt->set<uint32_t>(cpuTarget[int_num] |
+                                   cpuTarget[int_num+1] << 8 |
+                                   cpuTarget[int_num+2] << 16 |
+                                   cpuTarget[int_num+3] << 24) ;
+            }
+        } else {
+            int ctx_id = pkt->req->contextId();
+            assert(ctx_id < sys->numRunningContexts());
+            pkt->set<uint32_t>(ctx_id);
+        }
+        goto done;
+    }
+
+    if (daddr >= ICDICFR_ST && daddr < ICDICFR_ED + 4) {
+        assert((daddr-ICDICFR_ST) >> 2 < 64);
+        /** @todo software generated interrutps and PPIs
+         * can't be configured in some ways
+         */
+        pkt->set<uint32_t>(intConfig[(daddr-ICDICFR_ST)>>2]);
+        goto done;
+    }
+
+    switch(daddr) {
+      case ICDDCR:
+        pkt->set<uint32_t>(enabled);
+        break;
+      case ICDICTR:
+        uint32_t tmp;
+        tmp = ((sys->numRunningContexts() - 1) << 5) |
+              (itLines/INT_BITS_MAX -1);
+        pkt->set<uint32_t>(tmp);
+        break;
+      default:
+        panic("Tried to read Gic distributor at offset %#x\n", daddr);
+        break;
+    }
+done:
+    pkt->makeAtomicResponse();
+    return distPioDelay;
+}
+
+Tick
+Pl390::readCpu(PacketPtr pkt)
+{
+    Addr daddr = pkt->getAddr() - cpuAddr;
+    pkt->allocate();
+
+    assert(pkt->req->hasContextId());
+    int ctx_id = pkt->req->contextId();
+    assert(ctx_id < sys->numRunningContexts());
+
+    DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr,
+            ctx_id);
+
+    switch(daddr) {
+      case ICCICR:
+        pkt->set<uint32_t>(cpuEnabled[ctx_id]);
+        break;
+      case ICCPMR:
+        pkt->set<uint32_t>(cpuPriority[ctx_id]);
+        break;
+      case ICCBPR:
+        pkt->set<uint32_t>(cpuBpr[ctx_id]);
+        break;
+      case ICCIAR:
+        if (enabled && cpuEnabled[ctx_id]) {
+            int active_int = cpuHighestInt[ctx_id];
+            IAR iar = 0;
+            iar.ack_id = active_int;
+            iar.cpu_id = 0;
+            if (active_int < SGI_MAX) {
+                // this is a software interrupt from another CPU
+                if (!cpuSgiPending[active_int])
+                    panic("Interrupt %d active but no CPU generated it?\n",
+                            active_int);
+                for (int x = 0; x < CPU_MAX; x++) {
+                    // See which CPU generated the interrupt
+                    uint8_t cpugen =
+                        bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x);
+                    if (cpugen & (1 << ctx_id)) {
+                        iar.cpu_id = x;
+                        break;
+                    }
+                }
+                uint64_t sgi_num = ULL(1) << (ctx_id + 8 * iar.cpu_id);
+                cpuSgiActive[iar.ack_id] |= sgi_num;
+                cpuSgiPending[iar.ack_id] &= ~sgi_num;
+            } else if (active_int < (SGI_MAX + PPI_MAX) ) {
+                uint32_t int_num = 1 << (cpuHighestInt[ctx_id] - SGI_MAX);
+                cpuPpiActive[ctx_id] |= int_num;
+                updateRunPri();
+                cpuPpiPending[ctx_id] &= ~int_num;
+
+            } else {
+                uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx_id]);
+                activeInt[intNumToWord(cpuHighestInt[ctx_id])] |= int_num;
+                updateRunPri();
+                pendingInt[intNumToWord(cpuHighestInt[ctx_id])] &= ~int_num;
+            }
+
+            DPRINTF(Interrupt,"CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
+                    ctx_id, iar.ack_id, iar.cpu_id, iar);
+            cpuHighestInt[ctx_id] = SPURIOUS_INT;
+            updateIntState(-1);
+            pkt->set<uint32_t>(iar);
+            platform->intrctrl->clear(ctx_id, ArmISA::INT_IRQ, 0);
+        } else {
+             pkt->set<uint32_t>(SPURIOUS_INT);
+        }
+
+        break;
+      case ICCRPR:
+        pkt->set<uint32_t>(iccrpr[0]);
+        break;
+      case ICCHPIR:
+        pkt->set<uint32_t>(0);
+        panic("Need to implement HPIR");
+        break;
+      default:
+        panic("Tried to read Gic cpu at offset %#x\n", daddr);
+        break;
+    }
+    pkt->makeAtomicResponse();
+    return cpuPioDelay;
+}
+
+
+Tick
+Pl390::writeDistributor(PacketPtr pkt)
+{
+    Addr daddr = pkt->getAddr() - distAddr;
+    pkt->allocate();
+
+    assert(pkt->req->hasContextId());
+    int ctx_id = pkt->req->contextId();
+
+    DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n",
+            daddr, pkt->getSize(), pkt->get<uint32_t>());
+
+    if (daddr >= ICDISER_ST && daddr < ICDISER_ED + 4) {
+        assert((daddr-ICDISER_ST) >> 2 < 32);
+        intEnabled[(daddr-ICDISER_ST) >> 2] |= pkt->get<uint32_t>();
+        goto done;
+    }
+
+    if (daddr >= ICDICER_ST && daddr < ICDICER_ED + 4) {
+        assert((daddr-ICDICER_ST) >> 2 < 32);
+        intEnabled[(daddr-ICDICER_ST) >> 2] &= ~pkt->get<uint32_t>();
+        goto done;
+    }
+
+    if (daddr >= ICDISPR_ST && daddr < ICDISPR_ED + 4) {
+        assert((daddr-ICDISPR_ST) >> 2 < 32);
+        pendingInt[(daddr-ICDISPR_ST) >> 2] |= pkt->get<uint32_t>();
+        pendingInt[0] &= SGI_MASK; // Don't allow SGIs to be changed
+        updateIntState((daddr-ICDISPR_ST) >> 2);
+        goto done;
+    }
+
+    if (daddr >= ICDICPR_ST && daddr < ICDICPR_ED + 4) {
+        assert((daddr-ICDICPR_ST) >> 2 < 32);
+        pendingInt[(daddr-ICDICPR_ST) >> 2] &= ~pkt->get<uint32_t>();
+        pendingInt[0] &= SGI_MASK; // Don't allow SGIs to be changed
+        updateIntState((daddr-ICDICPR_ST) >> 2);
+        goto done;
+    }
+
+    if (daddr >= ICDIPR_ST && daddr < ICDIPR_ED + 4) {
+        Addr int_num = daddr - ICDIPR_ST;
+        assert(int_num < INT_LINES_MAX);
+        uint8_t* int_p;
+        if (int_num < (SGI_MAX + PPI_MAX))
+            int_p = bankedIntPriority[ctx_id];
+        else
+            int_p = intPriority;
+        uint32_t tmp;
+        switch(pkt->getSize()) {
+          case 1:
+            tmp = pkt->get<uint8_t>();
+            int_p[int_num] = bits(tmp, 7, 0);
+            break;
+          case 2:
+            tmp = pkt->get<uint16_t>();
+            int_p[int_num] = bits(tmp, 7, 0);
+            int_p[int_num + 1] = bits(tmp, 15, 8);
+            break;
+          case 4:
+            tmp = pkt->get<uint32_t>();
+            int_p[int_num] = bits(tmp, 7, 0);
+            int_p[int_num + 1] = bits(tmp, 15, 8);
+            int_p[int_num + 2] = bits(tmp, 23, 16);
+            int_p[int_num + 3] = bits(tmp, 31, 24);
+            break;
+          default:
+            panic("Invalid size when writing to priority regs in Gic: %d\n",
+                   pkt->getSize());
+        }
+
+        updateIntState(-1);
+        updateRunPri();
+        goto done;
+    }
+
+    if (daddr >= ICDIPTR_ST && daddr < ICDIPTR_ED + 4) {
+        Addr int_num = (daddr-ICDIPTR_ST) ;
+        assert(int_num < INT_LINES_MAX);
+        // First 31 interrupts only target single processor
+        if (int_num >= SGI_MAX) {
+            if (pkt->getSize() == 1) {
+                uint8_t tmp = pkt->get<uint8_t>();
+                cpuTarget[int_num] = tmp & 0xff;
+            } else {
+                assert (pkt->getSize() == 4);
+                int_num = mbits(int_num, 31, 2);
+                uint32_t tmp = pkt->get<uint32_t>();
+                cpuTarget[int_num]   = bits(tmp, 7, 0);
+                cpuTarget[int_num+1] = bits(tmp, 15, 8);
+                cpuTarget[int_num+2] = bits(tmp, 23, 16);
+                cpuTarget[int_num+3] = bits(tmp, 31, 24);
+            }
+            updateIntState((daddr-ICDIPTR_ST)>>2);
+        }
+        goto done;
+    }
+
+    if (daddr >= ICDICFR_ST && daddr < ICDICFR_ED + 4) {
+        assert((daddr-ICDICFR_ST) >> 2 < 64);
+        intConfig[(daddr-ICDICFR_ST)>>2] = pkt->get<uint32_t>();
+        if (pkt->get<uint32_t>() & NN_CONFIG_MASK)
+            warn("GIC N:N mode selected and not supported at this time\n");
+        goto done;
+    }
+
+    switch(daddr) {
+      case ICDDCR:
+        enabled = pkt->get<uint32_t>();
+        DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled);
+        break;
+      case ICDSGIR:
+        softInt(ctx_id, pkt->get<uint32_t>());
+        break;
+      default:
+        panic("Tried to write Gic distributor at offset %#x\n", daddr);
+        break;
+    }
+
+done:
+    pkt->makeAtomicResponse();
+    return distPioDelay;
+}
+
+Tick
+Pl390::writeCpu(PacketPtr pkt)
+{
+    Addr daddr = pkt->getAddr() - cpuAddr;
+    pkt->allocate();
+
+    assert(pkt->req->hasContextId());
+    int ctx_id = pkt->req->contextId();
+    IAR iar;
+
+    DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n",
+            ctx_id, daddr, pkt->get<uint32_t>());
+
+    switch(daddr) {
+      case ICCICR:
+        cpuEnabled[ctx_id] = pkt->get<uint32_t>();
+        break;
+      case ICCPMR:
+        cpuPriority[ctx_id] = pkt->get<uint32_t>();
+        break;
+      case ICCBPR:
+        cpuBpr[ctx_id] = pkt->get<uint32_t>();
+        break;
+      case ICCEOIR:
+        iar = pkt->get<uint32_t>();
+        if (iar.ack_id < SGI_MAX) {
+            // Clear out the bit that corrseponds to the cleared int
+            uint64_t clr_int = ULL(1) << (ctx_id + 8 * iar.cpu_id);
+            if (!(cpuSgiActive[iar.ack_id] & clr_int))
+                panic("Done handling a SGI that isn't active?\n");
+            cpuSgiActive[iar.ack_id] &= ~clr_int;
+        } else if (iar.ack_id < (SGI_MAX + PPI_MAX) ) {
+            uint32_t int_num = 1 << (iar.ack_id - SGI_MAX);
+            if (!(cpuPpiActive[ctx_id] & int_num))
+                panic("CPU %d Done handling a PPI interrupt that isn't active?\n", ctx_id);
+            cpuPpiActive[ctx_id] &= ~int_num;
+        } else {
+            uint32_t int_num = 1 << intNumToBit(iar.ack_id);
+            if (!(activeInt[intNumToWord(iar.ack_id)] & int_num))
+                panic("Done handling interrupt that isn't active?\n");
+            activeInt[intNumToWord(iar.ack_id)] &= ~int_num;
+        }
+        updateRunPri();
+        DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
+                ctx_id, iar.ack_id, iar.cpu_id);
+        break;
+      default:
+        panic("Tried to write Gic cpu at offset %#x\n", daddr);
+        break;
+    }
+    if (cpuEnabled[ctx_id]) updateIntState(-1);
+    pkt->makeAtomicResponse();
+    return cpuPioDelay;
+}
+
+void
+Pl390::softInt(int ctx_id, SWI swi)
+{
+    switch (swi.list_type) {
+      case 1:
+        // interrupt all
+        uint8_t cpu_list;
+        cpu_list = 0;
+        for (int x = 0; x < CPU_MAX; x++)
+            cpu_list |= cpuEnabled[x] ? 1 << x : 0;
+        swi.cpu_list = cpu_list;
+        break;
+      case 2:
+        // interrupt requesting cpu only
+        swi.cpu_list = 1 << ctx_id;
+        break;
+        // else interrupt cpus specified
+    }
+
+    DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx_id,
+            swi.cpu_list);
+    for (int i = 0; i < CPU_MAX; i++) {
+        DPRINTF(IPI, "Processing CPU %d\n", i);
+        if (!cpuEnabled[i])
+            continue;
+        if (swi.cpu_list & (1 << i))
+            cpuSgiPending[swi.sgi_id] |= (1 << i) << (8 * ctx_id);
+        DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id, cpuSgiPending[swi.sgi_id]);
+    }
+    updateIntState(-1);
+}
+
+uint64_t
+Pl390::genSwiMask(int cpu)
+{
+    if (cpu > 7)
+        panic("Invalid CPU ID\n");
+    return ULL(0x0101010101010101) << cpu;
+}
+
+void
+Pl390::updateIntState(int hint)
+{
+    for (int cpu = 0; cpu < CPU_MAX; cpu++) {
+        if (!cpuEnabled[cpu])
+            continue;
+        if (cpu >= sys->numContexts())
+            break;
+
+        /*@todo use hint to do less work. */
+        int highest_int = SPURIOUS_INT;
+        // Priorities below that set in ICCPMR can be ignored
+        uint8_t highest_pri = cpuPriority[cpu];
+
+        // Check SGIs
+        for (int swi = 0; swi < SGI_MAX; swi++) {
+            if (!cpuSgiPending[swi])
+                continue;
+            if (cpuSgiPending[swi] & genSwiMask(cpu))
+                if (highest_pri > bankedIntPriority[cpu][swi]) {
+                    highest_pri = bankedIntPriority[cpu][swi];
+                    highest_int = swi;
+                }
+        }
+
+        // Check PPIs
+        if (cpuPpiPending[cpu]) {
+        for (int ppi = 0; ppi < PPI_MAX; ppi++) {
+            if (cpuPpiPending[cpu] & (1 << ppi))
+                if (highest_pri > bankedIntPriority[cpu][SGI_MAX + ppi]) {
+                    highest_pri = bankedIntPriority[cpu][SGI_MAX + ppi];
+                    highest_int = SGI_MAX + ppi;
+                }
+            }
+        }
+
+        bool mp_sys = sys->numRunningContexts() > 1;
+        // Check other ints
+        for (int x = 0; x < (itLines/INT_BITS_MAX); x++) {
+            if (intEnabled[x] & pendingInt[x]) {
+                for (int y = 0; y < INT_BITS_MAX; y++) {
+                   uint32_t int_nm = x * INT_BITS_MAX + y;
+                   DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm);
+                    /* Set current pending int as highest int for current cpu
+                       if the interrupt's priority higher than current prioirty
+                       and if currrent cpu is the target (for mp configs only)
+                     */
+                    if ((bits(intEnabled[x], y) & bits(pendingInt[x], y)) &&
+                        (intPriority[int_nm] < highest_pri))
+                        if ( (!mp_sys) || (cpuTarget[int_nm] & (1 << cpu))) {
+                            highest_pri = intPriority[int_nm];
+                            highest_int = int_nm;
+                        }
+                }
+            }
+        }
+
+        cpuHighestInt[cpu] = highest_int;
+
+        if (highest_int == SPURIOUS_INT)
+            continue;
+
+        /* @todo make this work for more than one cpu, need to handle 1:N, N:N
+         * models */
+        if (enabled && cpuEnabled[cpu] && (highest_pri < cpuPriority[cpu]) &&
+            !(activeInt[intNumToWord(highest_int)]
+            & (1 << intNumToBit(highest_int)))) {
+
+            DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int,
+                    cpu);
+            postInt(cpu, curTick() + intLatency);
+        }
+    }
+}
+
+void
+Pl390::updateRunPri()
+{
+    for (int cpu = 0; cpu < CPU_MAX; cpu++) {
+        if (!cpuEnabled[cpu])
+            continue;
+        uint8_t maxPriority = 0xff;
+        for (int i = 0; i < itLines; i++){
+            if (i < SGI_MAX) {
+                if ((cpuSgiActive[i] & genSwiMask(cpu)) &&
+                        (bankedIntPriority[cpu][i] < maxPriority))
+                    maxPriority = bankedIntPriority[cpu][i];
+            } else if (i < (SGI_MAX + PPI_MAX)) {
+                if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) &&
+                        (bankedIntPriority[cpu][i] < maxPriority))
+                    maxPriority = bankedIntPriority[cpu][i];
+
+            } else {
+                if (activeInt[intNumToWord(i)] & (1 << intNumToBit(i)))
+                    if (intPriority[i] < maxPriority)
+                        maxPriority = intPriority[i];
+            }
+        }
+        iccrpr[cpu] = maxPriority;
+    }
+}
+
+void
+Pl390::sendInt(uint32_t num)
+{
+    DPRINTF(Interrupt, "Received Interupt number %d,  cpuTarget %#x: \n",
+            num, cpuTarget[num]);
+    if (cpuTarget[num] & (cpuTarget[num] - 1))
+        panic("Multiple targets for peripheral interrupts is not supported\n");
+    pendingInt[intNumToWord(num)] |= 1 << intNumToBit(num);
+    updateIntState(intNumToWord(num));
+
+}
+
+void
+Pl390::sendPPInt(uint32_t num, uint32_t cpu)
+{
+    DPRINTF(Interrupt, "Received Interrupt number %d, cpuTarget %#x: \n",
+            num, cpu);
+    cpuPpiPending[cpu] |= 1 << (num - SGI_MAX);
+    updateIntState(intNumToWord(num));
+}
+
+void
+Pl390::clearInt(uint32_t number)
+{
+    /* @todo assume edge triggered only at the moment. Nothing to do. */
+}
+
+void
+Pl390::postInt(uint32_t cpu, Tick when)
+{
+    if (!(postIntEvent[cpu]->scheduled()))
+        eventq->schedule(postIntEvent[cpu], when);
+}
+
+AddrRangeList
+Pl390::getAddrRanges() const
+{
+    AddrRangeList ranges;
+    ranges.push_back(RangeSize(distAddr, DIST_SIZE));
+    ranges.push_back(RangeSize(cpuAddr, CPU_SIZE));
+    return ranges;
+}
+
+
+void
+Pl390::serialize(std::ostream &os)
+{
+    DPRINTF(Checkpoint, "Serializing Arm GIC\n");
+
+    SERIALIZE_SCALAR(distAddr);
+    SERIALIZE_SCALAR(cpuAddr);
+    SERIALIZE_SCALAR(distPioDelay);
+    SERIALIZE_SCALAR(cpuPioDelay);
+    SERIALIZE_SCALAR(enabled);
+    SERIALIZE_SCALAR(itLines);
+    SERIALIZE_SCALAR(itLinesLog2);
+    SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX);
+    SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX);
+    SERIALIZE_ARRAY(activeInt, INT_BITS_MAX);
+    SERIALIZE_ARRAY(iccrpr, CPU_MAX);
+    SERIALIZE_ARRAY(intPriority, INT_LINES_MAX);
+    SERIALIZE_ARRAY(cpuTarget, INT_LINES_MAX);
+    SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
+    SERIALIZE_ARRAY(cpuEnabled, CPU_MAX);
+    SERIALIZE_ARRAY(cpuPriority, CPU_MAX);
+    SERIALIZE_ARRAY(cpuBpr, CPU_MAX);
+    SERIALIZE_ARRAY(cpuHighestInt, CPU_MAX);
+    SERIALIZE_ARRAY(cpuSgiActive, SGI_MAX);
+    SERIALIZE_ARRAY(cpuSgiPending, SGI_MAX);
+    SERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
+    SERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
+    SERIALIZE_ARRAY(*bankedIntPriority, CPU_MAX * (SGI_MAX + PPI_MAX));
+    SERIALIZE_SCALAR(irqEnable);
+    Tick interrupt_time[CPU_MAX];
+    for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
+        interrupt_time[cpu] = 0;
+        if (postIntEvent[cpu]->scheduled()) {
+            interrupt_time[cpu] = postIntEvent[cpu]->when();
+        }
+    }
+    SERIALIZE_ARRAY(interrupt_time, CPU_MAX);
+
+}
+
+void
+Pl390::unserialize(Checkpoint *cp, const std::string &section)
+{
+    DPRINTF(Checkpoint, "Unserializing Arm GIC\n");
+
+    UNSERIALIZE_SCALAR(distAddr);
+    UNSERIALIZE_SCALAR(cpuAddr);
+    UNSERIALIZE_SCALAR(distPioDelay);
+    UNSERIALIZE_SCALAR(cpuPioDelay);
+    UNSERIALIZE_SCALAR(enabled);
+    UNSERIALIZE_SCALAR(itLines);
+    UNSERIALIZE_SCALAR(itLinesLog2);
+    UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX);
+    UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX);
+    UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX);
+    UNSERIALIZE_ARRAY(iccrpr, CPU_MAX);
+    UNSERIALIZE_ARRAY(intPriority, INT_LINES_MAX);
+    UNSERIALIZE_ARRAY(cpuTarget, INT_LINES_MAX);
+    UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
+    UNSERIALIZE_ARRAY(cpuEnabled, CPU_MAX);
+    UNSERIALIZE_ARRAY(cpuPriority, CPU_MAX);
+    UNSERIALIZE_ARRAY(cpuBpr, CPU_MAX);
+    UNSERIALIZE_ARRAY(cpuHighestInt, CPU_MAX);
+    UNSERIALIZE_ARRAY(cpuSgiActive, SGI_MAX);
+    UNSERIALIZE_ARRAY(cpuSgiPending, SGI_MAX);
+    UNSERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
+    UNSERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
+    UNSERIALIZE_ARRAY(*bankedIntPriority, CPU_MAX * (SGI_MAX + PPI_MAX));
+    UNSERIALIZE_SCALAR(irqEnable);
+
+    Tick interrupt_time[CPU_MAX];
+    UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX);
+
+    for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
+        if (interrupt_time[cpu])
+            schedule(postIntEvent[cpu], interrupt_time[cpu]);
+    }
+
+}
+
+Pl390 *
+Pl390Params::create()
+{
+    return new Pl390(this);
+}
+
+/* Functions for debugging and testing */
+void
+Pl390::driveSPI(unsigned int spiVect)
+{
+    DPRINTF(GIC, "Received SPI Vector:%x Enable: %d\n", spiVect, irqEnable);
+    pendingInt[1] |= spiVect;
+    if (irqEnable && enabled) {
+        updateIntState(-1);
+    }
+}
+
+void
+Pl390::driveIrqEn( bool state)
+{
+    irqEnable = state;
+    DPRINTF(GIC, " Enabling Irq\n");
+    updateIntState(-1);
+}
+
+void
+Pl390::driveLegIRQ(bool state)
+{
+    if (irqEnable && !(!enabled && cpuEnabled[0])) {
+        if (state) {
+            DPRINTF(GIC, "Driving Legacy Irq\n");
+            platform->intrctrl->post(0, ArmISA::INT_IRQ, 0);
+        }
+        else platform->intrctrl->clear(0, ArmISA::INT_IRQ, 0);
+    }
+}
+
+void
+Pl390::driveLegFIQ(bool state)
+{
+    if (state)
+        platform->intrctrl->post(0, ArmISA::INT_FIQ, 0);
+    else platform->intrctrl->clear(0, ArmISA::INT_FIQ, 0);
+}
diff --git a/src/dev/arm/gic_pl390.hh b/src/dev/arm/gic_pl390.hh
new file mode 100644 (file)
index 0000000..cc6e24d
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2005 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: Ali Saidi
+ */
+
+
+/** @file
+ * Implementiation of a PL390 GIC
+ */
+
+#ifndef __DEV_ARM_GIC_PL390_H__
+#define __DEV_ARM_GIC_PL390_H__
+
+#include "base/bitunion.hh"
+#include "cpu/intr_control.hh"
+#include "dev/arm/base_gic.hh"
+#include "dev/io_device.hh"
+#include "dev/platform.hh"
+#include "params/Pl390.hh"
+
+/** @todo this code only assumes one processor for now. Low word
+ * of intEnabled and pendingInt need to be replicated per CPU.
+ * bottom 31 interrupts (7 words) need to be replicated for
+ * for interrupt priority register, processor target registers
+ * interrupt config registers  */
+
+class Pl390 : public BaseGic
+{
+  protected:
+    // distributor memory addresses
+    static const int ICDDCR     = 0x000; // control register
+    static const int ICDICTR    = 0x004; // controller type
+    static const int ICDIIDR    = 0x008; // implementer id
+    static const int ICDISER_ST = 0x100; // interrupt set enable
+    static const int ICDISER_ED = 0x17c;
+    static const int ICDICER_ST = 0x180; // interrupt clear enable
+    static const int ICDICER_ED = 0x1fc;
+    static const int ICDISPR_ST = 0x200; // set pending interrupt
+    static const int ICDISPR_ED = 0x27c;
+    static const int ICDICPR_ST = 0x280; // clear pending interrupt
+    static const int ICDICPR_ED = 0x2fc;
+    static const int ICDABR_ST  = 0x300; // active bit registers
+    static const int ICDABR_ED  = 0x37c;
+    static const int ICDIPR_ST  = 0x400; // interrupt priority registers
+    static const int ICDIPR_ED  = 0x7f8;
+    static const int ICDIPTR_ST = 0x800; // processor target registers
+    static const int ICDIPTR_ED = 0xbf8;
+    static const int ICDICFR_ST = 0xc00; // interrupt config registers
+    static const int ICDICFR_ED = 0xcfc;
+    static const int ICDSGIR    = 0xf00; // software generated interrupt
+    static const int DIST_SIZE  = 0xfff;
+
+    // cpu memory addressesa
+    static const int ICCICR  = 0x00; // CPU control register
+    static const int ICCPMR  = 0x04; // Interrupt priority mask
+    static const int ICCBPR  = 0x08; // binary point register
+    static const int ICCIAR  = 0x0C; // interrupt ack register
+    static const int ICCEOIR = 0x10; // end of interrupt
+    static const int ICCRPR  = 0x14; // runing priority
+    static const int ICCHPIR = 0x18; // highest pending interrupt
+    static const int ICCABPR = 0x1c; // aliased binary point
+    static const int ICCIIDR = 0xfc; // cpu interface id register
+    static const int CPU_SIZE  = 0xff;
+
+    static const int SGI_MAX = 16;  // Number of Software Gen Interrupts
+    static const int PPI_MAX = 16;  // Number of Private Peripheral Interrupts
+
+    /** Mask off SGI's when setting/clearing pending bits */
+    static const int SGI_MASK = 0xFFFF0000;
+
+    /** Mask for bits that config N:N mode in ICDICFR's */
+    static const int NN_CONFIG_MASK = 0x55555555;
+
+    static const int CPU_MAX = 8;   // Max number of supported CPU interfaces
+    static const int SPURIOUS_INT = 1023;
+    static const int INT_BITS_MAX = 32;
+    static const int INT_LINES_MAX = 1020;
+
+    BitUnion32(SWI)
+        Bitfield<3,0> sgi_id;
+        Bitfield<23,16> cpu_list;
+        Bitfield<25,24> list_type;
+    EndBitUnion(SWI)
+
+    BitUnion32(IAR)
+        Bitfield<9,0> ack_id;
+        Bitfield<12,10> cpu_id;
+    EndBitUnion(IAR)
+
+    /** Distributor address GIC listens at */
+    Addr distAddr;
+
+    /** CPU address GIC listens at */
+    /** @todo is this one per cpu? */
+    Addr cpuAddr;
+
+    /** Latency for a distributor operation */
+    Tick distPioDelay;
+
+    /** Latency for a cpu operation */
+    Tick cpuPioDelay;
+
+    /** Latency for a interrupt to get to CPU */
+    Tick intLatency;
+
+    /** Gic enabled */
+    bool enabled;
+
+    /** Number of itLines enabled */
+    uint32_t itLines;
+
+    uint32_t itLinesLog2;
+
+    /** interrupt enable bits for all possible 1020 interupts.
+     * one bit per interrupt, 32 bit per word = 32 words */
+    uint32_t intEnabled[INT_BITS_MAX];
+
+    /** interrupt pending bits for all possible 1020 interupts.
+     * one bit per interrupt, 32 bit per word = 32 words */
+    uint32_t pendingInt[INT_BITS_MAX];
+
+    /** interrupt active bits for all possible 1020 interupts.
+     * one bit per interrupt, 32 bit per word = 32 words */
+    uint32_t activeInt[INT_BITS_MAX];
+
+    /** read only running priroity register, 1 per cpu*/
+    uint32_t iccrpr[CPU_MAX];
+
+    /** an 8 bit priority (lower is higher priority) for each
+     * of the 1020 possible supported interrupts.
+     */
+    uint8_t intPriority[INT_LINES_MAX];
+
+    /** an 8 bit cpu target id for each shared peripheral interrupt
+     * of the 1020 possible supported interrupts.
+     */
+    uint8_t cpuTarget[INT_LINES_MAX];
+
+    /** 2 bit per interrupt signaling if it's level or edge sensitive
+     * and if it is 1:N or N:N */
+    uint32_t intConfig[INT_BITS_MAX*2];
+
+    /** CPU enabled */
+    bool cpuEnabled[CPU_MAX];
+
+    /** CPU priority */
+    uint8_t cpuPriority[CPU_MAX];
+
+    /** Binary point registers */
+    uint8_t cpuBpr[CPU_MAX];
+
+    /** highest interrupt that is interrupting CPU */
+    uint32_t cpuHighestInt[CPU_MAX];
+
+    /** One bit per cpu per software interrupt that is pending for each possible
+     * sgi source. Indexed by SGI number. Each byte in generating cpu id and
+     * bits in position is destination id. e.g. 0x4 = CPU 0 generated interrupt
+     * for CPU 2. */
+    uint64_t cpuSgiPending[SGI_MAX];
+    uint64_t cpuSgiActive[SGI_MAX];
+
+    /** One bit per private peripheral interrupt. Only upper 16 bits
+     * will be used since PPI interrupts are numberred from 16 to 32 */
+    uint32_t cpuPpiPending[CPU_MAX];
+    uint32_t cpuPpiActive[CPU_MAX];
+
+    /** Banked interrupt prioirty registers for SGIs and PPIs */
+    uint8_t bankedIntPriority[CPU_MAX][SGI_MAX + PPI_MAX];
+
+    /** IRQ Enable Used for debug */
+    bool irqEnable;
+
+    /** software generated interrupt
+     * @param data data to decode that indicates which cpus to interrupt
+     */
+    void softInt(int ctx_id, SWI swi);
+
+    /** See if some processor interrupt flags need to be enabled/disabled
+     * @param hint which set of interrupts needs to be checked
+     */
+    void updateIntState(int hint);
+
+    /** Update the register that records priority of the highest priority
+     *  active interrupt*/
+    void updateRunPri();
+
+    /** generate a bit mask to check cpuSgi for an interrupt. */
+    uint64_t genSwiMask(int cpu);
+
+    int intNumToWord(int num) const { return num >> 5; }
+    int intNumToBit(int num) const { return num % 32; }
+
+    /** Post an interrupt to a CPU
+     */
+    void postInt(uint32_t cpu, Tick when);
+
+    /** Event definition to post interrupt to CPU after a delay
+    */
+    class PostIntEvent : public Event
+    {
+      private:
+        uint32_t cpu;
+        Platform *platform;
+      public:
+        PostIntEvent( uint32_t c, Platform* p)
+            : cpu(c), platform(p)
+        { }
+        void process() { platform->intrctrl->post(cpu, ArmISA::INT_IRQ, 0);}
+        const char *description() const { return "Post Interrupt to CPU"; }
+    };
+    PostIntEvent *postIntEvent[CPU_MAX];
+
+  public:
+    typedef Pl390Params Params;
+    const Params *
+    params() const
+    {
+        return dynamic_cast<const Params *>(_params);
+    }
+    Pl390(const Params *p);
+
+    /** Return the address ranges used by the Gic
+     * This is the distributor address + all cpu addresses
+     */
+    virtual AddrRangeList getAddrRanges() const;
+
+    /** A PIO read to the device, immediately split up into
+     * readDistributor() or readCpu()
+     */
+    virtual Tick read(PacketPtr pkt);
+
+    /** A PIO read to the device, immediately split up into
+     * writeDistributor() or writeCpu()
+     */
+    virtual Tick write(PacketPtr pkt);
+
+    /** Handle a read to the distributor poriton of the GIC
+     * @param pkt packet to respond to
+     */
+    Tick readDistributor(PacketPtr pkt);
+
+    /** Handle a read to the cpu poriton of the GIC
+     * @param pkt packet to respond to
+     */
+    Tick readCpu(PacketPtr pkt);
+
+    /** Handle a write to the distributor poriton of the GIC
+     * @param pkt packet to respond to
+     */
+    Tick writeDistributor(PacketPtr pkt);
+
+    /** Handle a write to the cpu poriton of the GIC
+     * @param pkt packet to respond to
+     */
+    Tick writeCpu(PacketPtr pkt);
+
+    /** Post an interrupt from a device that is connected to the Gic.
+     * Depending on the configuration, the gic will pass this interrupt
+     * on through to a CPU.
+     * @param number number of interrupt to send */
+    void sendInt(uint32_t number);
+
+    /** Interface call for private peripheral interrupts  */
+    void sendPPInt(uint32_t num, uint32_t cpu);
+
+    /** Clear an interrupt from a device that is connected to the Gic
+     * Depending on the configuration, the gic may de-assert it's cpu line
+     * @param number number of interrupt to send */
+    void clearInt(uint32_t number);
+
+    /* Various functions fer testing and debugging */
+    void driveSPI(uint32_t spi);
+    void driveLegIRQ(bool state);
+    void driveLegFIQ(bool state);
+    void driveIrqEn(bool state);
+
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+
+#endif //__DEV_ARM_GIC_H__
index e2e75cfefc53041bd92e3872a5037741176758c2..f9dbfcf762d4f6da3b8b370e50ab0bd238c60123 100644 (file)
@@ -54,8 +54,6 @@
 #include "dev/arm/amba_device.hh"
 #include "params/Pl050.hh"
 
-class Gic;
-
 class Pl050 : public AmbaIntDevice, public VncKeyboard, public VncMouse
 {
   protected:
index 4be7a5d905277cc3903879414284f92e020b7bcf..8593c4e5447d9ffb0977de1d1d82e2fabe06a442 100644 (file)
@@ -44,7 +44,7 @@
 #include "debug/Checkpoint.hh"
 #include "debug/Uart.hh"
 #include "dev/arm/amba_device.hh"
-#include "dev/arm/gic.hh"
+#include "dev/arm/base_gic.hh"
 #include "dev/arm/pl011.hh"
 #include "dev/terminal.hh"
 #include "mem/packet.hh"
index e96d33d83268f6c646113f5a59010c549d63119c..a13f635f0ad7d7c560ca673351e1f816bf7c30de 100644 (file)
@@ -54,7 +54,7 @@
 #include "dev/uart.hh"
 #include "params/Pl011.hh"
 
-class Gic;
+class BaseGic;
 
 class Pl011 : public Uart
 {
@@ -121,7 +121,7 @@ class Pl011 : public Uart
     int intNum;
 
     /** Gic to use for interrupting */
-    Gic *gic;
+    BaseGic *gic;
 
     /** Should the simulation end on an EOT */
     bool endOnEOT;
index acb3b7dd8d625b0202e21ebf4adaf837a4deb156..2cf401ce4f3328cdbd332bb26ccccc49060f64ed 100644 (file)
 #include "debug/PL111.hh"
 #include "debug/Uart.hh"
 #include "dev/arm/amba_device.hh"
-#include "dev/arm/gic.hh"
+#include "dev/arm/base_gic.hh"
 #include "dev/arm/pl111.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
+#include "sim/system.hh"
 
 // clang complains about std::set being overloaded with Packet::set if
 // we open up the entire namespace std
index 855fb8bef5fbe2e1f94ac4b0f8de6234e6c60b3b..a994067154984526591f65f836f89bbe975e1751 100644 (file)
@@ -52,7 +52,6 @@
 #include "params/Pl111.hh"
 #include "sim/serialize.hh"
 
-class Gic;
 class VncInput;
 class Bitmap;
 
index b33624cc63214880ff3f06bd1a1479542068863d..18208b402b435b0d299d9a8dd5547cc0c5c9c38b 100644 (file)
@@ -50,7 +50,7 @@
 
 #include "config/the_isa.hh"
 #include "cpu/intr_control.hh"
-#include "dev/arm/gic.hh"
+#include "dev/arm/base_gic.hh"
 #include "dev/arm/realview.hh"
 #include "dev/terminal.hh"
 #include "sim/system.hh"
index f38aa69fc7ef75cb00946f87e21c1247ab6f23b0..38fa040d51a8fbb656991b4cfba7f43b0ba97ffd 100644 (file)
@@ -52,7 +52,7 @@
 #include "dev/platform.hh"
 #include "params/RealView.hh"
 
-class Gic;
+class BaseGic;
 class IdeController;
 class System;
 
@@ -62,7 +62,7 @@ class RealView : public Platform
     /** Pointer to the system */
     System *system;
 
-    Gic *gic;
+    BaseGic *gic;
 
   public:
     typedef RealViewParams Params;
@@ -80,7 +80,7 @@ class RealView : public Platform
     RealView(const Params *p);
 
     /** Give platform a pointer to interrupt controller */
-    void setGic(Gic *_gic) { gic = _gic; }
+    void setGic(BaseGic *_gic) { gic = _gic; }
 
     /**
      * Cause the cpu to post a serial interrupt to the CPU.
index 097c521860696c11b100e987486d48f821f18757..84bc12aa91aaf5fdf9f5f86096af496b966c560f 100644 (file)
@@ -42,7 +42,7 @@
 #include "base/trace.hh"
 #include "debug/Checkpoint.hh"
 #include "debug/Timer.hh"
-#include "dev/arm/gic.hh"
+#include "dev/arm/base_gic.hh"
 #include "dev/arm/timer_cpulocal.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
index 9b60db4ec2651a485f8a8780d2b5ef85ccca589a..086dc1c63a3596f5e1423cfcd6021d65ca6cf5a2 100644 (file)
@@ -50,7 +50,7 @@
  * Technical Reference Manual rev r2p2 (ARM DDI 0407F)
  */
 
-class Gic;
+class BaseGic;
 
 class CpuLocalTimer : public BasicPioDevice
 {
@@ -157,7 +157,7 @@ class CpuLocalTimer : public BasicPioDevice
     static const int CPU_MAX = 8;
 
     /** Pointer to the GIC for causing an interrupt */
-    Gic *gic;
+    BaseGic *gic;
 
     /** Timers that do the actual work */
     Timer localTimer[CPU_MAX];
index af0227ec4490737bba5d50b1d3b6f6f9e77aa3b1..18a22e10804197afeb0faad32f728e52facd7439 100644 (file)
@@ -41,7 +41,7 @@
 #include "base/trace.hh"
 #include "debug/Checkpoint.hh"
 #include "debug/Timer.hh"
-#include "dev/arm/gic.hh"
+#include "dev/arm/base_gic.hh"
 #include "dev/arm/timer_sp804.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
index 745cb95e341af97a2d3fa0358c92f05796bebe2f..c000985bd4357864d05aa92681a38cb549fe30fe 100644 (file)
@@ -47,7 +47,7 @@
  * This implements the dual Sp804 timer block
  */
 
-class Gic;
+class BaseGic;
 
 class Sp804 : public AmbaDevice
 {
@@ -127,7 +127,7 @@ class Sp804 : public AmbaDevice
     };
 
     /** Pointer to the GIC for causing an interrupt */
-    Gic *gic;
+    BaseGic *gic;
 
     /** Timers that do the actual work */
     Timer timer0;