Getting GICv3's redistributor might look a bit clumsy, but we will need
those stubs as soon as we allow to kick secondary CPUs on ARM via PSCI.

Signed-off-by: Ralf Ramsauer <[email protected]>
---
 inmates/lib/arm-common/gic-v2.c | 23 +++++++--------
 inmates/lib/arm-common/gic-v3.c | 50 +++++++++++++++++++++++++++++----
 2 files changed, 56 insertions(+), 17 deletions(-)

diff --git a/inmates/lib/arm-common/gic-v2.c b/inmates/lib/arm-common/gic-v2.c
index e2c271c3..ab85fd27 100644
--- a/inmates/lib/arm-common/gic-v2.c
+++ b/inmates/lib/arm-common/gic-v2.c
@@ -39,11 +39,6 @@
 #include <mach.h>
 #include <gic.h>
 
-#ifndef GICD_V2_BASE
-#define GICD_V2_BASE           ((void *)-1)
-#define GICC_V2_BASE           ((void *)-1)
-#endif
-
 #define GICC_CTLR              0x0000
 #define GICC_PMR               0x0004
 #define GICC_IAR               0x000c
@@ -55,29 +50,35 @@
 
 #define GICC_PMR_DEFAULT       0xf0
 
+static void *gicc_v2_base;
+static void *gicd_v2_base;
+
 static void gic_v2_enable(unsigned int irqn)
 {
-       mmio_write32(GICD_V2_BASE + GICD_ISENABLER + ((irqn >> 3) & ~0x3),
+       mmio_write32(gicd_v2_base + GICD_ISENABLER + ((irqn >> 3) & ~0x3),
                     1 << (irqn & 0x1f));
 }
 
 static int gic_v2_init(void)
 {
-       mmio_write32(GICC_V2_BASE + GICC_CTLR, GICC_CTLR_GRPEN1);
-       mmio_write32(GICC_V2_BASE + GICC_PMR, GICC_PMR_DEFAULT);
-       mmio_write32(GICD_V2_BASE + GICD_CTLR, GICD_CTLR_ENABLE);
+       gicc_v2_base = (void*)(unsigned long)comm_region->gicc_base;
+       gicd_v2_base = (void*)(unsigned long)comm_region->gicd_base;
+
+       mmio_write32(gicc_v2_base + GICC_CTLR, GICC_CTLR_GRPEN1);
+       mmio_write32(gicc_v2_base + GICC_PMR, GICC_PMR_DEFAULT);
+       mmio_write32(gicd_v2_base + GICD_CTLR, GICD_CTLR_ENABLE);
 
        return 0;
 }
 
 static void gic_v2_write_eoi(u32 irqn)
 {
-       mmio_write32(GICC_V2_BASE + GICC_EOIR, irqn);
+       mmio_write32(gicc_v2_base + GICC_EOIR, irqn);
 }
 
 static u32 gic_v2_read_ack(void)
 {
-       return mmio_read32(GICC_V2_BASE + GICC_IAR) & 0x3ff;
+       return mmio_read32(gicc_v2_base + GICC_IAR) & 0x3ff;
 }
 
 const struct gic gic_v2 = {
diff --git a/inmates/lib/arm-common/gic-v3.c b/inmates/lib/arm-common/gic-v3.c
index f9278f71..530374c6 100644
--- a/inmates/lib/arm-common/gic-v3.c
+++ b/inmates/lib/arm-common/gic-v3.c
@@ -40,14 +40,18 @@
 #include <mach.h>
 #include <gic.h>
 
-#ifndef GICD_V3_BASE
-#define GICD_V3_BASE           ((void *)-1)
-#define GICR_V3_BASE           ((void *)-1)
-#endif
+static void *gicd_v3_base;
+static void *gicr_v3_base;
 
+#define GICR_TYPER              0x0008
+#define GICR_TYPER_Last         (1 << 4)
+#define GICR_PIDR2              0xffe8
 #define GICR_SGI_BASE          0x10000
 #define GICR_ISENABLER         GICD_ISENABLER
 
+#define GICD_PIDR2_ARCH(pidr)  (((pidr) & 0xf0) >> 4)
+#define GICR_PIDR2_ARCH                GICD_PIDR2_ARCH
+
 #define ICC_IAR1_EL1           SYSREG_32(0, c12, c12, 0)
 #define ICC_EOIR1_EL1          SYSREG_32(0, c12, c12, 1)
 #define ICC_PMR_EL1            SYSREG_32(0, c4, c6, 0)
@@ -59,15 +63,49 @@
 static void gic_v3_enable(unsigned int irqn)
 {
        if (is_sgi_ppi(irqn))
-               mmio_write32(GICR_V3_BASE + GICR_SGI_BASE + GICR_ISENABLER,
+               mmio_write32(gicr_v3_base + GICR_SGI_BASE + GICR_ISENABLER,
                             1 << irqn);
        else if (is_spi(irqn))
-               mmio_write32(GICD_V3_BASE + GICD_ISENABLER + irqn / 32,
+               mmio_write32(gicd_v3_base + GICD_ISENABLER + irqn / 32,
                             1 << (irqn % 32));
 }
 
 static int gic_v3_init(void)
 {
+       void *redist_addr = (void*)(unsigned long)comm_region->gicr_base;
+       unsigned long mpidr;
+       void *gicr = NULL;
+       u64 typer;
+       u32 pidr, aff;
+
+       gicd_v3_base = (void*)(unsigned long)comm_region->gicd_base;
+
+       arm_read_sysreg(MPIDR_EL1, mpidr);
+       aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
+               MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
+               MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
+               MPIDR_AFFINITY_LEVEL(mpidr, 0));
+
+       /* Find redistributor */
+       do {
+               pidr = mmio_read32(redist_addr + GICR_PIDR2);
+               if (GICR_PIDR2_ARCH(pidr) != 3)
+                       break;
+
+               typer = mmio_read64(redist_addr + GICR_TYPER);
+               if ((typer >> 32) == aff) {
+                       gicr = redist_addr;
+                       break;
+               }
+
+               redist_addr += 0x20000;
+       } while (!(typer & GICR_TYPER_Last));
+
+       if (!gicr)
+               return -1;
+
+       gicr_v3_base = gicr;
+
        arm_write_sysreg(ICC_CTLR_EL1, 0);
        arm_write_sysreg(ICC_PMR_EL1, 0xf0);
        arm_write_sysreg(ICC_IGRPEN1_EL1, ICC_IGRPEN1_EN);
-- 
2.17.0

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to