GICv3: Add support for mem-mapped CPU interface
authorLukas Humbel <lukas.humbel@inf.ethz.ch>
Mon, 20 Mar 2017 17:02:28 +0000 (18:02 +0100)
committerLukas Humbel <lukas.humbel@inf.ethz.ch>
Mon, 20 Mar 2017 17:02:28 +0000 (18:02 +0100)
Not clear if this is working, since we don't have a interrupt source yet.

Signed-off-by: Lukas Humbel <lukas.humbel@inf.ethz.ch>

devices/Hakefile
devices/gic_v3_cpu.dev [new file with mode: 0644]
kernel/Hakefile
kernel/arch/armv8/gic_v3_mmio.c [new file with mode: 0644]
kernel/arch/armv8/plat_apm88xxxx.c
kernel/arch/armv8/plat_apm88xxxx_consts.c

index b3278fc..67ac695 100644 (file)
@@ -41,6 +41,7 @@
            "fat_bpb",
            "fat_direntry",
            "gic_v3",
+           "gic_v3_cpu",
            "hpet",
            "ia32",
            "ixp2800_icp_pic0",
diff --git a/devices/gic_v3_cpu.dev b/devices/gic_v3_cpu.dev
new file mode 100644 (file)
index 0000000..532f95b
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Memory mapped GIC v3 CPU Interface. Sysreg mapped CPUs should
+ * definitions in armv8.dev.
+ * Source: ARM IHI 0069B, page 8-560
+ */
+device gic_v3_cpu msbfirst (addr cpuif) "MMIO mapped GIC CPU interface" {
+
+    register CTLR rw addr(cpuif, 0x0) "CPU Interface Control Register - secure" {
+        _               21 mbz;
+        EOImodeNS       1;
+        EOImodeS        1;
+        IRQBypDisGrp1   1;
+        FIQBypDisGrp1   1;
+        IRQBypDisGrp0   1;
+        FIQBypDisGrp0   1;
+        CBPR            1;
+        FIQEn           1;
+        _               1 mbz;
+        EnableGrp1      1;
+        EnableGrp0      1;
+    };
+
+    register CTLR_NS rw also addr(cpuif, 0x0) "CPU Interface Control Register - Non-secure" {
+        _              22 mbz;
+        EOImodeNS       1;
+        RES0            2;
+        IRQBypDisGrp1   1;
+        FIQBypDisGrp1   1;
+        _               4 mbz;
+        EnableGrp1      1;
+    };
+
+    register PMR rw addr(cpuif, 0x0004) "Interrupt Controller Interrupt Priority Mask Register" {
+        _          24;
+        priority    8 "Priority mask level";
+    };
+
+    register BPR rw addr(cpuif, 0x0008) "Interrupt Controller Binray Point Register" {
+        _            29;
+        binary_point  3;
+    };
+
+    register IAR rw addr(cpuif, 0x000C) "Interrupt Controller Interrupt Acknowledge Register" {
+        _            8;
+        intid       24 "INTID of the signaled interrupt";
+    };
+
+    register EOIR wo addr(cpuif, 0x0010) "Interrupt Controller End Of Interrupt Register"  {
+        _            8;
+        intid       24 "INTID from the corresponding ICC_IAR0_EL1 access";
+    };
+
+
+    register RPR ro addr(cpuif, 0x0014) "Running Priority Register" {
+
+        _          24;
+        priority    8 "Running priority";
+    };
+
+
+    register HPPIR ro addr(cpuif, 0x0018) "Highest Priority Pending Interrupt Register" {
+        _            8;
+        intid       24 "INTID of the highest priority pending interrupt";
+    };
+
+    register ABPR rw addr(cpuif, 0x001c) "Aliased Binary Point Register" {
+        _            29;
+        binary_point  3;
+    };
+    
+    register AIAR ro addr(cpuif, 0x0020) "Aliased Interrupt Acknowledge Register" {
+        _            8;
+        intid       24 "INTID of the signaled interrupt";
+    };
+
+    register AEOIR wo addr(cpuif, 0x0024) "Aliased End of Interrupt Register" {
+        _            8;
+        intid       24 "INTID from the corresponding ICC_IAR0_EL1 access";
+    };
+
+    register AHPPIR ro addr(cpuif, 0x0028) "Aliased Highest Priority Pending Interrupt Register" {
+        _            8;
+        intid       24 "INTID of the highest priority pending interrupt";
+    };
+
+    register STATUSR rw addr(cpuif, 0x002C) "Error Reporting Status Register" {
+        _           27;
+        asv         1 "Attempted security violation";
+        wrod        1 "Write to an RO location";
+        rwod        1 "Read of a WO location";
+        wrd         1 "Write to a reserved location";
+        rrd         1 "Read of a reserved location";
+    };
+
+    register APR1 rw addr(cpuif, 0x00D0) "CPU Interface Active Priorities Registers" {
+        impl    32;
+    };
+
+    register APR2 rw addr(cpuif, 0x00D4) "CPU Interface Active Priorities Registers" {
+        impl    32;
+    };
+
+    register APR3 rw addr(cpuif, 0x00D8) "CPU Interface Active Priorities Registers" {
+        impl    32;
+    };
+
+    register APR4 rw addr(cpuif, 0x00DC) "CPU Interface Active Priorities Registers" {
+        impl    32;
+    };
+
+    register NSAPR1 rw addr(cpuif, 0x00E0) "Non-secure CPU Interface Active Priorities Registers" {
+        impl    32;
+    };
+
+    register NSAPR2 rw addr(cpuif, 0x00E4) "Non-secure CPU Interface Active Priorities Registers" {
+        impl    32;
+    };
+
+    register NSAPR3 rw addr(cpuif, 0x00E8) "Non-secure CPU Interface Active Priorities Registers" {
+        impl    32;
+    };
+
+    register NSAPR4 rw addr(cpuif, 0x00EC) "Non-secure CPU Interface Active Priorities Registers" {
+        impl    32;
+    };
+
+    register IIDR ro addr(cpuif, 0x00FC) "CPU Interface Identification Register" {
+        ProductID    8 "Product identifier";
+        _            4 mbz;
+        Variant      4 "Variant number";
+        Revision     4 "Revision number";
+        Implementer 12 "JEP106 code of implementing company";
+    };
+
+    register DIR wo addr(cpuif, 0x1000) "Deactivate Interrupt Register" {
+        _            8;
+        intid       24 "INTID of the highest priority pending interrupt";
+    };
+
+};
index 936015a..d87aba9 100644 (file)
@@ -490,10 +490,9 @@ let
          "arch/arm/gdb_arch.c",
          "arch/armv8/plat_apm88xxxx.c",
          "arch/armv8/plat_apm88xxxx_consts.c",
-         "arch/armv8/plat_a57mpcore.c",
          "arch/armv8/init.c",
          "arch/armv8/gdb_arch.c",
-         "arch/armv8/gic_v3.c",
+         "arch/armv8/gic_v3_mmio.c",
          -----
          "arch/armv8/kernel_multiboot2.c",
          "arch/armv8/dispatch.c",
@@ -511,6 +510,8 @@ let
      mackerelDevices = [
         "arm",
         "armv8",
+        "gic_v3",
+        "gic_v3_cpu",
         "armv8/armv8_generic_timer",
         "armv8/armv8_cache_ctrl",
         "pl130_gic",
@@ -618,6 +619,8 @@ let
      mackerelDevices = [
         "arm",
         "armv8",
+        "gic_v3",
+        "gic_v3_cpu",
         "armv8/armv8_generic_timer",
         "armv8/armv8_cache_ctrl",
         "pl011_uart",
diff --git a/kernel/arch/armv8/gic_v3_mmio.c b/kernel/arch/armv8/gic_v3_mmio.c
new file mode 100644 (file)
index 0000000..8c01803
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2016, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetstr 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <kernel.h>
+#include <sysreg.h>
+#include <dev/armv8_dev.h>
+#include <dev/gic_v3_dev.h>
+#include <dev/gic_v3_cpu_dev.h>
+#include <platform.h>
+#include <paging_kernel_arch.h>
+#include <arch/armv8/gic_v3.h>
+
+static gic_v3_t gic_v3_dev;
+static gic_v3_cpu_t gic_v3_cpu_dev;
+
+/*
+ * Initialize the global interrupt controller
+ *
+ * There are three types of interrupts
+ * 1) Software generated Interrupts (SGI) - IDs 0-15
+ * 2) Private Peripheral Interrupts (PPI) - IDs 16-31
+ * 3) Shared Peripheral Interrups (SPI) - IDs 32...
+ */
+errval_t gicv3_init(void)
+{
+    printk(LOG_NOTE, "gicv3_init (mem-mapped CPU if) enter\n");
+
+    lvaddr_t gic_cpu = local_phys_to_mem(platform_get_gic_cpu_address());
+    gic_v3_initialize(&gic_v3_dev, (char *)gic_cpu);
+
+    lvaddr_t gic_dist = local_phys_to_mem(platform_get_distributor_address());
+    gic_v3_cpu_initialize(&gic_v3_cpu_dev, (char *)gic_dist);
+
+    printk(LOG_NOTE, "gicv3_init done\n");
+    return SYS_ERR_OK;
+}
+
+/*
+ * Returns active interrupt of group 1 
+ */
+uint32_t gicv3_get_active_irq(void)
+{
+    return gic_v3_cpu_IAR_intid_rdf(&gic_v3_cpu_dev);
+}
+
+/*
+ * ACKs group 1 interrupt
+ */
+void gicv3_ack_irq(uint32_t irq)
+{
+    gic_v3_cpu_EOIR_t reg = 0;
+    reg = gic_v3_cpu_EOIR_intid_insert(reg, irq);
+    gic_v3_cpu_EOIR_rawwr(&gic_v3_cpu_dev, irq);
+}
+
+/*
+ * Raise an SGI on a core. 
+ */
+void gicv3_raise_softirq(coreid_t cpuid, uint8_t irq)
+{
+    // assuming affinity routing DISABLED
+    assert(irq <= 15);
+    gic_v3_GICD_SGIR_t reg = 0;
+    reg = gic_v3_GICD_SGIR_INTID_insert(reg, irq);
+    reg = gic_v3_GICD_SGIR_CPUTargetList_insert(reg, 1<<(cpuid-1));
+    gic_v3_GICD_SGIR_wr(&gic_v3_dev, reg);
+    /*
+    armv8_ICC_SGI1R_EL1_t reg = 0;
+    reg = armv8_ICC_SGI1R_EL1_intid_insert(reg, 1);
+    // TODO: make that work for cpuids > 15
+    reg = armv8_ICC_SGI1R_EL1_target_insert(reg, 1<<(cpuid-1));
+    reg = armv8_ICC_SGI1R_EL1_aff3_insert(reg, 0);
+    reg = armv8_ICC_SGI1R_EL1_aff2_insert(reg, 0);
+    reg = armv8_ICC_SGI1R_EL1_aff1_insert(reg, 0);
+    armv8_ICC_SGI1R_EL1_wr(NULL, reg);
+    */
+}
+
+/*
+ * Enable GIC CPU-IF and local distributor
+ */
+errval_t gicv3_cpu_interface_enable(void)
+{
+    printk(LOG_NOTE, "gicv3_cpu_interface_enable: enabling group 1 int\n");
+
+    // Linux does: 
+    // sets priority mode: PMR to 0xf0
+    gic_v3_cpu_PMR_wr(&gic_v3_cpu_dev, 0xf0);
+    // Set binary point to 1, 6 group priority bits, 2 subpriority bits
+    gic_v3_cpu_BPR_wr(&gic_v3_cpu_dev, 1);
+
+    //Enable group 1
+    gic_v3_cpu_CTLR_NS_wr(&gic_v3_cpu_dev, 0x1);
+    printk(LOG_NOTE, "gicv3_cpu_interface_enable: group 1 int enabled\n");
+
+    printk(LOG_NOTE, "gicv3_cpu_interface_enable: configuring distributor\n");
+    printk(LOG_NOTE, "GICD IIDR "
+            "implementer=0x%x, revision=0x%x, variant=0x%x,prodid=0x%x\n",
+            gic_v3_GICD_IIDR_Implementer_rdf(&gic_v3_dev),
+            gic_v3_GICD_IIDR_Revision_rdf(&gic_v3_dev),
+            gic_v3_GICD_IIDR_Variant_rdf(&gic_v3_dev),
+            gic_v3_GICD_IIDR_ProductID_rdf(&gic_v3_dev)
+            );
+
+    gic_v3_GICD_CTLR_secure_t ctrl = 0;
+    // Set affinity routing
+    ctrl = gic_v3_GICD_CTLR_secure_ARE_NS_insert(ctrl, 1);
+    // Enable group 1 interrupts
+    ctrl = gic_v3_GICD_CTLR_secure_EnableGrp1NS_insert(ctrl, 1);
+    gic_v3_GICD_CTLR_secure_wr(&gic_v3_dev, ctrl);
+
+    return SYS_ERR_OK;
+}
+
+
index 24fba59..20938c2 100644 (file)
@@ -23,6 +23,8 @@
 #include <barrelfish_kpi/arm_core_data.h>
 #include <psci.h>
 #include <arch/armv8/global.h>
+#include <arch/armv8/gic_v3.h>
+#include <paging_kernel_arch.h>
 
 /* the maximum number of UARTS supported */
 #define MAX_NUM_UARTS 4
@@ -115,16 +117,39 @@ void armv8_get_info(struct arch_info_armv8 *ai)
 
 }
 
+/* GIC */
+
 errval_t platform_gic_init(void) {
-    gic_init();
+    gicv3_init();
     return SYS_ERR_OK;
 }
 
 errval_t platform_gic_cpu_interface_enable(void) {
-    gic_cpu_interface_enable();
+    gicv3_cpu_interface_enable();
     return SYS_ERR_OK;
 }
 
+/**
+ * @brief obtain the address of the GIC CPU interface
+ *
+ * @return physical address of the CBAR region
+ */
+lpaddr_t platform_get_gic_cpu_address(void) {
+    assert(paging_mmu_enabled());
+    return platform_gic_cpu_base;
+}
+
+/**
+ * @brief obtain the address of the GIC distributor interface
+ *
+ * @return physical address of the CBAR region
+ */
+lpaddr_t platform_get_distributor_address(void) {
+    assert(paging_mmu_enabled());
+    return platform_gic_dist_base;
+}
+
+
 errval_t platform_boot_core(hwid_t target, genpaddr_t gen_entry, genpaddr_t context)
 {
     printf("Invoking PSCI on: cpu=0x%lx, entry=0x%lx, context=0x%lx\n", target, gen_entry, context);
@@ -141,5 +166,9 @@ An FIQ interrupt, even if the PSTATE F-bit is set.
      *
      *
      */
+
+    gicv3_raise_softirq(target, 1);
+     
     return SYS_ERR_OK;
 }
+
index ee6caa7..4e2cfda 100644 (file)
@@ -24,8 +24,8 @@ lpaddr_t phys_memory_start= 0;
  * ----------------------------------------------------------------------------
  */
 
-lpaddr_t platform_gic_cpu_base  = 0x0000000078010000;
-lpaddr_t platform_gic_dist_base = 0x0000000078020000;
+lpaddr_t platform_gic_cpu_base  = 0x0000000078020000;
+lpaddr_t platform_gic_dist_base = 0x0000000078010000;
 
 
 /*