[RFC PATCH 0/7] Enable GIC v3 with 64bit CPUs

47 views
Skip to first unread message

Nikhil Devshatwar

unread,
Jul 20, 2017, 5:27:58 AM7/20/17
to jan.k...@siemens.com, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com, Nikhil Devshatwar
This series is an attempt to get jailhouse working on systems with
64bit CPUs and non GIC v3 (non v2 compatible)

With my half knowledge, I have tried to get a few things working.
I might have fixed one and broke ten others.
Please scrutinize each change and point out issues.

ONLY tested with aarch64 and GICv3 config

Nikhil Devshatwar (7):
hypervisor: Move GIC v3 to arm-common
inmates: Move gic v3 to common
hypervisor: Fix sysreg macro definitions
hypervisor: Fix virt_id errors
hypervisor: Correct cpu_id bitfield in GIC TYPER register
hypervisor: Fix IROUTER register access
hypervisor: gicv3: Remove ICH_LRC from aarch64

hypervisor/arch/arm-common/Kbuild | 1 +
hypervisor/arch/arm-common/gic-v3.c | 461 ++++++++++++++++++++++++
hypervisor/arch/arm-common/include/asm/gic.h | 2 +-
hypervisor/arch/arm-common/include/asm/gic_v3.h | 267 ++++++++++++++
hypervisor/arch/arm/Kbuild | 1 -
hypervisor/arch/arm/gic-v3.c | 456 -----------------------
hypervisor/arch/arm/include/asm/gic_v3.h | 269 --------------
hypervisor/arch/arm64/include/asm/sysregs.h | 12 +-
inmates/lib/arm-common/Makefile.lib | 1 +
inmates/lib/arm-common/gic-v3.c | 58 +++
inmates/lib/arm/Makefile | 1 -
inmates/lib/arm/gic-v3.c | 58 ---
12 files changed, 798 insertions(+), 789 deletions(-)
create mode 100644 hypervisor/arch/arm-common/gic-v3.c
create mode 100644 hypervisor/arch/arm-common/include/asm/gic_v3.h
delete mode 100644 hypervisor/arch/arm/gic-v3.c
delete mode 100644 hypervisor/arch/arm/include/asm/gic_v3.h
create mode 100644 inmates/lib/arm-common/gic-v3.c
delete mode 100644 inmates/lib/arm/gic-v3.c

--
1.9.1

Nikhil Devshatwar

unread,
Jul 20, 2017, 5:28:00 AM7/20/17
to jan.k...@siemens.com, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com, Nikhil Devshatwar
Signed-off-by: Nikhil Devshatwar <nikh...@ti.com>
---
hypervisor/arch/arm-common/Kbuild | 1 +
hypervisor/arch/arm-common/gic-v3.c | 456 ++++++++++++++++++++++++
hypervisor/arch/arm-common/include/asm/gic_v3.h | 269 ++++++++++++++
hypervisor/arch/arm/Kbuild | 1 -
hypervisor/arch/arm/gic-v3.c | 456 ------------------------
hypervisor/arch/arm/include/asm/gic_v3.h | 269 --------------
6 files changed, 726 insertions(+), 726 deletions(-)
create mode 100644 hypervisor/arch/arm-common/gic-v3.c
create mode 100644 hypervisor/arch/arm-common/include/asm/gic_v3.h
delete mode 100644 hypervisor/arch/arm/gic-v3.c
delete mode 100644 hypervisor/arch/arm/include/asm/gic_v3.h

diff --git a/hypervisor/arch/arm-common/Kbuild b/hypervisor/arch/arm-common/Kbuild
index 7874b9e..779e204 100644
--- a/hypervisor/arch/arm-common/Kbuild
+++ b/hypervisor/arch/arm-common/Kbuild
@@ -16,5 +16,6 @@ ccflags-$(CONFIG_JAILHOUSE_GCOV) += -fprofile-arcs -ftest-coverage
OBJS-y += dbg-write.o lib.o psci.o control.o paging.o mmu_cell.o
OBJS-y += irqchip.o pci.o ivshmem.o uart-pl011.o uart-xuartps.o
OBJS-$(CONFIG_ARM_GIC_V2) += gic-v2.o
+OBJS-$(CONFIG_ARM_GIC_V3) += gic-v3.o

COMMON_OBJECTS = $(addprefix ../arm-common/,$(OBJS-y))
diff --git a/hypervisor/arch/arm-common/gic-v3.c b/hypervisor/arch/arm-common/gic-v3.c
new file mode 100644
index 0000000..2ea947f
--- /dev/null
+++ b/hypervisor/arch/arm-common/gic-v3.c
@@ -0,0 +1,456 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) ARM Limited, 2014
+ *
+ * Authors:
+ * Jean-Philippe Brucker <jean-phili...@arm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <jailhouse/control.h>
+#include <jailhouse/mmio.h>
+#include <jailhouse/printk.h>
+#include <jailhouse/processor.h>
+#include <jailhouse/types.h>
+#include <asm/control.h>
+#include <asm/gic.h>
+#include <asm/irqchip.h>
+#include <asm/setup.h>
+#include <asm/traps.h>
+
+/*
+ * This implementation assumes that the kernel driver already initialised most
+ * of the GIC.
+ * There is almost no instruction barrier, since IRQs are always disabled in the
+ * hyp, and ERET serves as the context synchronization event.
+ */
+
+static unsigned int gic_num_lr;
+static unsigned int gic_num_priority_bits;
+static u32 gic_version;
+
+static void *gicr_base;
+
+static int gic_init(void)
+{
+ /* TODO: need to validate more? */
+ if (!(mmio_read32(gicd_base + GICD_CTLR) & GICD_CTLR_ARE_NS))
+ return trace_error(-EIO);
+
+ /* Let the per-cpu code access the redistributors */
+ gicr_base = paging_map_device(
+ system_config->platform_info.arm.gicr_base, GICR_SIZE);
+ if (!gicr_base)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void gic_clear_pending_irqs(void)
+{
+ unsigned int n;
+
+ /* Clear list registers. */
+ for (n = 0; n < gic_num_lr; n++)
+ gic_write_lr(n, 0);
+
+ /* Clear active priority bits */
+ if (gic_num_priority_bits >= 5)
+ arm_write_sysreg(ICH_AP1R0_EL2, 0);
+ if (gic_num_priority_bits >= 6)
+ arm_write_sysreg(ICH_AP1R1_EL2, 0);
+ if (gic_num_priority_bits > 6) {
+ arm_write_sysreg(ICH_AP1R2_EL2, 0);
+ arm_write_sysreg(ICH_AP1R3_EL2, 0);
+ }
+}
+
+static void gic_cpu_reset(struct per_cpu *cpu_data)
+{
+ unsigned int mnt_irq = system_config->platform_info.arm.maintenance_irq;
+ void *gicr = cpu_data->gicr_base + GICR_SGI_BASE;
+
+ gic_clear_pending_irqs();
+
+ /* Ensure all IPIs and the maintenance PPI are enabled. */
+ mmio_write32(gicr + GICR_ISENABLER, 0x0000ffff | (1 << mnt_irq));
+
+ /* Disable PPIs, except for the maintenance interrupt. */
+ mmio_write32(gicr + GICR_ICENABLER, 0xffff0000 & ~(1 << mnt_irq));
+
+ /* Deactivate all active PPIs */
+ mmio_write32(gicr + GICR_ICACTIVER, 0xffff0000);
+
+ arm_write_sysreg(ICH_VMCR_EL2, 0);
+}
+
+static int gic_cpu_init(struct per_cpu *cpu_data)
+{
+ unsigned int mnt_irq = system_config->platform_info.arm.maintenance_irq;
+ u64 typer;
+ u32 pidr;
+ u32 cell_icc_ctlr, cell_icc_pmr, cell_icc_igrpen1;
+ u32 ich_vtr;
+ u32 ich_vmcr;
+ void *redist_base = gicr_base;
+
+ /* Find redistributor */
+ do {
+ pidr = mmio_read32(redist_base + GICR_PIDR2);
+ gic_version = GICR_PIDR2_ARCH(pidr);
+ if (gic_version != 3 && gic_version != 4)
+ break;
+
+ typer = mmio_read64(redist_base + GICR_TYPER);
+ if ((typer >> 32) == cpu_data->cpu_id) {
+ cpu_data->gicr_base = redist_base;
+ break;
+ }
+
+ redist_base += gic_version == 4 ? 0x40000 : 0x20000;
+ } while (!(typer & GICR_TYPER_Last));
+
+ if (!cpu_data->gicr_base) {
+ printk("GIC: No redist found for CPU%d\n", cpu_data->cpu_id);
+ return -ENODEV;
+ }
+
+ /* Ensure all IPIs and the maintenance PPI are enabled. */
+ mmio_write32(redist_base + GICR_SGI_BASE + GICR_ISENABLER,
+ 0x0000ffff | (1 << mnt_irq));
+
+ /*
+ * Set EOIMode to 1
+ * This allow to drop the priority of level-triggered interrupts without
+ * deactivating them, and thus ensure that they won't be immediately
+ * re-triggered. (e.g. timer)
+ * They can then be injected into the guest using the LR.HW bit, and
+ * will be deactivated once the guest does an EOI after handling the
+ * interrupt source.
+ */
+ arm_read_sysreg(ICC_CTLR_EL1, cell_icc_ctlr);
+ arm_write_sysreg(ICC_CTLR_EL1, ICC_CTLR_EOImode);
+
+ arm_read_sysreg(ICC_PMR_EL1, cell_icc_pmr);
+ arm_write_sysreg(ICC_PMR_EL1, ICC_PMR_DEFAULT);
+
+ arm_read_sysreg(ICC_IGRPEN1_EL1, cell_icc_igrpen1);
+ arm_write_sysreg(ICC_IGRPEN1_EL1, ICC_IGRPEN1_EN);
+
+ arm_read_sysreg(ICH_VTR_EL2, ich_vtr);
+ gic_num_lr = (ich_vtr & 0xf) + 1;
+ gic_num_priority_bits = (ich_vtr >> 29) + 1;
+
+ /*
+ * Clear pending virtual IRQs in case anything is left from previous
+ * use. Physically pending IRQs will be forwarded to Linux once we
+ * enable interrupts for the hypervisor.
+ */
+ gic_clear_pending_irqs();
+
+ ich_vmcr = (cell_icc_pmr & ICC_PMR_MASK) << ICH_VMCR_VPMR_SHIFT;
+ if (cell_icc_igrpen1 & ICC_IGRPEN1_EN)
+ ich_vmcr |= ICH_VMCR_VENG1;
+ if (cell_icc_ctlr & ICC_CTLR_EOImode)
+ ich_vmcr |= ICH_VMCR_VEOIM;
+ arm_write_sysreg(ICH_VMCR_EL2, ich_vmcr);
+
+ /* After this, the cells access the virtual interface of the GIC. */
+ arm_write_sysreg(ICH_HCR_EL2, ICH_HCR_EN);
+
+ return 0;
+}
+
+static void gic_cpu_shutdown(struct per_cpu *cpu_data)
+{
+ u32 ich_vmcr, icc_ctlr, cell_icc_igrpen1;
+
+ if (!cpu_data->gicr_base)
+ return;
+
+ arm_write_sysreg(ICH_HCR_EL2, 0);
+
+ /* Disable the maintenance interrupt - not used by Linux. */
+ mmio_write32(cpu_data->gicr_base + GICR_SGI_BASE + GICR_ICENABLER,
+ 1 << system_config->platform_info.arm.maintenance_irq);
+
+ /* Restore the root config */
+ arm_read_sysreg(ICH_VMCR_EL2, ich_vmcr);
+
+ if (!(ich_vmcr & ICH_VMCR_VEOIM)) {
+ arm_read_sysreg(ICC_CTLR_EL1, icc_ctlr);
+ icc_ctlr &= ~ICC_CTLR_EOImode;
+ arm_write_sysreg(ICC_CTLR_EL1, icc_ctlr);
+ }
+ if (!(ich_vmcr & ICH_VMCR_VENG1)) {
+ arm_read_sysreg(ICC_IGRPEN1_EL1, cell_icc_igrpen1);
+ cell_icc_igrpen1 &= ~ICC_IGRPEN1_EN;
+ arm_write_sysreg(ICC_IGRPEN1_EL1, cell_icc_igrpen1);
+ }
+}
+
+static void gic_adjust_irq_target(struct cell *cell, u16 irq_id)
+{
+ void *irouter = gicd_base + GICD_IROUTER + irq_id;
+ u32 route = mmio_read32(irouter);
+
+ if (!cell_owns_cpu(cell, route))
+ mmio_write32(irouter, first_cpu(cell->cpu_set));
+}
+
+static enum mmio_result gic_handle_redist_access(void *arg,
+ struct mmio_access *mmio)
+{
+ struct cell *cell = this_cell();
+ unsigned int cpu;
+ unsigned int virt_id;
+ unsigned int redist_size = (gic_version == 4) ? 0x40000 : 0x20000;
+ void *phys_redist = NULL;
+ unsigned long offs;
+
+ /*
+ * The redistributor accessed by the cell is not the one stored in these
+ * cpu_datas, but the one associated to its virtual id. So we first
+ * need to translate the redistributor address.
+ */
+ for_each_cpu(cpu, cell->cpu_set) {
+ virt_id = arm_cpu_phys2virt(cpu);
+ offs = per_cpu(virt_id)->gicr_base - gicr_base;
+ if (mmio->address >= offs &&
+ mmio->address < offs + redist_size) {
+ phys_redist = per_cpu(cpu)->gicr_base;
+ break;
+ }
+ }
+
+ if (phys_redist == NULL)
+ return MMIO_ERROR;
+
+ mmio->address -= offs;
+
+ /* Change the ID register, all other accesses are allowed. */
+ if (!mmio->is_write) {
+ switch (mmio->address) {
+ case GICR_TYPER:
+ if (virt_id == cell->arch.last_virt_id)
+ mmio->value = GICR_TYPER_Last;
+ else
+ mmio->value = 0;
+ /* AArch64 can use a writeq for this register */
+ if (mmio->size == 8)
+ mmio->value |= (u64)virt_id << 32;
+
+ return MMIO_HANDLED;
+ case GICR_TYPER + 4:
+ /* Upper bits contain the affinity */
+ mmio->value = virt_id;
+ return MMIO_HANDLED;
+ }
+ }
+ mmio_perform_access(phys_redist, mmio);
+ return MMIO_HANDLED;
+}
+
+static int gic_cell_init(struct cell *cell)
+{
+ mmio_region_register(cell, system_config->platform_info.arm.gicr_base,
+ GICR_SIZE, gic_handle_redist_access, NULL);
+
+ return 0;
+}
+
+static int gic_send_sgi(struct sgi *sgi)
+{
+ u64 val;
+ u16 targets = sgi->targets;
+
+ if (!is_sgi(sgi->id))
+ return -EINVAL;
+
+ if (sgi->routing_mode == 2)
+ targets = 1 << phys_processor_id();
+
+ val = (u64)sgi->aff3 << ICC_SGIR_AFF3_SHIFT
+ | (u64)sgi->aff2 << ICC_SGIR_AFF2_SHIFT
+ | sgi->aff1 << ICC_SGIR_AFF1_SHIFT
+ | (targets & ICC_SGIR_TARGET_MASK)
+ | (sgi->id & 0xf) << ICC_SGIR_IRQN_SHIFT;
+
+ if (sgi->routing_mode == 1)
+ val |= ICC_SGIR_ROUTING_BIT;
+
+ /*
+ * Ensure the targets see our modifications to their per-cpu
+ * structures.
+ */
+ dsb(ish);
+
+ arm_write_sysreg(ICC_SGI1R_EL1, val);
+ isb();
+
+ return 0;
+}
+
+void gicv3_handle_sgir_write(u64 sgir)
+{
+ struct sgi sgi;
+ unsigned long routing_mode = !!(sgir & ICC_SGIR_ROUTING_BIT);
+
+ /* FIXME: clusters are not supported yet. */
+ sgi.targets = sgir & ICC_SGIR_TARGET_MASK;
+ sgi.routing_mode = routing_mode;
+ sgi.aff1 = sgir >> ICC_SGIR_AFF1_SHIFT & 0xff;
+ sgi.aff2 = sgir >> ICC_SGIR_AFF2_SHIFT & 0xff;
+ sgi.aff3 = sgir >> ICC_SGIR_AFF3_SHIFT & 0xff;
+ sgi.id = sgir >> ICC_SGIR_IRQN_SHIFT & 0xf;
+
+ gic_handle_sgir_write(&sgi, true);
+}
+
+/*
+ * GICv3 uses a 64bit register IROUTER for each IRQ
+ */
+enum mmio_result gic_handle_irq_route(struct mmio_access *mmio,
+ unsigned int irq)
+{
+ struct cell *cell = this_cell();
+ unsigned int cpu;
+
+ /* Ignore aff3 on AArch32 (return 0) */
+ if (mmio->size == 4 && (mmio->address % 8))
+ return MMIO_HANDLED;
+
+ /* SGIs and PPIs are res0 */
+ if (!is_spi(irq))
+ return MMIO_HANDLED;
+
+ /*
+ * Ignore accesses to SPIs that do not belong to the cell. This isn't
+ * forbidden, because the guest driver may simply iterate over all
+ * registers at initialisation
+ */
+ if (!irqchip_irq_in_cell(cell, irq))
+ return MMIO_HANDLED;
+
+ /* Translate the virtual cpu id into the physical one */
+ if (mmio->is_write) {
+ mmio->value = arm_cpu_virt2phys(cell, mmio->value);
+ if (mmio->value == -1) {
+ printk("Attempt to route IRQ%d outside of cell\n", irq);
+ return MMIO_ERROR;
+ }
+ mmio_perform_access(gicd_base, mmio);
+ } else {
+ cpu = mmio_read32(gicd_base + GICD_IROUTER + 8 * irq);
+ mmio->value = arm_cpu_phys2virt(cpu);
+ }
+ return MMIO_HANDLED;
+}
+
+static void gic_eoi_irq(u32 irq_id, bool deactivate)
+{
+ arm_write_sysreg(ICC_EOIR1_EL1, irq_id);
+ if (deactivate)
+ arm_write_sysreg(ICC_DIR_EL1, irq_id);
+}
+
+static int gic_inject_irq(struct per_cpu *cpu_data, u16 irq_id)
+{
+ int i;
+ int free_lr = -1;
+ u32 elsr;
+ u64 lr;
+
+ arm_read_sysreg(ICH_ELSR_EL2, elsr);
+ for (i = 0; i < gic_num_lr; i++) {
+ if ((elsr >> i) & 1) {
+ /* Entry is invalid, candidate for injection */
+ if (free_lr == -1)
+ free_lr = i;
+ continue;
+ }
+
+ /*
+ * Entry is in use, check that it doesn't match the one we want
+ * to inject.
+ */
+ lr = gic_read_lr(i);
+
+ /*
+ * A strict phys->virt id mapping is used for SPIs, so this test
+ * should be sufficient.
+ */
+ if ((u32)lr == irq_id)
+ return -EEXIST;
+ }
+
+ if (free_lr == -1)
+ /* All list registers are in use */
+ return -EBUSY;
+
+ lr = irq_id;
+ /* Only group 1 interrupts */
+ lr |= ICH_LR_GROUP_BIT;
+ lr |= ICH_LR_PENDING;
+ if (!is_sgi(irq_id)) {
+ lr |= ICH_LR_HW_BIT;
+ lr |= (u64)irq_id << ICH_LR_PHYS_ID_SHIFT;
+ }
+
+ gic_write_lr(free_lr, lr);
+
+ return 0;
+}
+
+static void gicv3_enable_maint_irq(bool enable)
+{
+ u32 hcr;
+
+ arm_read_sysreg(ICH_HCR_EL2, hcr);
+ if (enable)
+ hcr |= ICH_HCR_UIE;
+ else
+ hcr &= ~ICH_HCR_UIE;
+ arm_write_sysreg(ICH_HCR_EL2, hcr);
+}
+
+static bool gicv3_has_pending_irqs(void)
+{
+ unsigned int n;
+
+ for (n = 0; n < gic_num_lr; n++)
+ if (gic_read_lr(n) & ICH_LR_PENDING)
+ return true;
+
+ return false;
+}
+
+static enum mmio_result gicv3_handle_irq_target(struct mmio_access *mmio,
+ unsigned int irq)
+{
+ /* ignore writes, we are in affinity routing mode */
+ return MMIO_HANDLED;
+}
+
+unsigned int irqchip_mmio_count_regions(struct cell *cell)
+{
+ return 2;
+}
+
+struct irqchip_ops irqchip = {
+ .init = gic_init,
+ .cpu_init = gic_cpu_init,
+ .cpu_reset = gic_cpu_reset,
+ .cpu_shutdown = gic_cpu_shutdown,
+ .cell_init = gic_cell_init,
+ .adjust_irq_target = gic_adjust_irq_target,
+ .send_sgi = gic_send_sgi,
+ .inject_irq = gic_inject_irq,
+ .enable_maint_irq = gicv3_enable_maint_irq,
+ .has_pending_irqs = gicv3_has_pending_irqs,
+ .eoi_irq = gic_eoi_irq,
+ .handle_irq_target = gicv3_handle_irq_target,
+};
diff --git a/hypervisor/arch/arm-common/include/asm/gic_v3.h b/hypervisor/arch/arm-common/include/asm/gic_v3.h
new file mode 100644
index 0000000..d1b9346
--- /dev/null
+++ b/hypervisor/arch/arm-common/include/asm/gic_v3.h
@@ -0,0 +1,269 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) ARM Limited, 2014
+ *
+ * Authors:
+ * Jean-Philippe Brucker <jean-phili...@arm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef _JAILHOUSE_ASM_GIC_V3_H
+#define _JAILHOUSE_ASM_GIC_V3_H
+
+#include <asm/sysregs.h>
+
+#define GICD_SIZE 0x10000
+#define GICR_SIZE 0x100000
+
+#define GICD_CIDR0 0xfff0
+#define GICD_CIDR1 0xfff4
+#define GICD_CIDR2 0xfff8
+#define GICD_CIDR3 0xfffc
+
+#define GICD_PIDR0 0xffe0
+#define GICD_PIDR1 0xffe4
+#define GICD_PIDR2 0xffe8
+#define GICD_PIDR3 0xffec
+#define GICD_PIDR4 0xffd0
+#define GICD_PIDR5 0xffd4
+#define GICD_PIDR6 0xffd8
+#define GICD_PIDR7 0xffdc
+
+#define GICR_CTLR GICD_CTLR
+#define GICR_TYPER 0x0008
+#define GICR_WAKER 0x0014
+#define GICR_CIDR0 GICD_CIDR0
+#define GICR_CIDR1 GICD_CIDR1
+#define GICR_CIDR2 GICD_CIDR2
+#define GICR_CIDR3 GICD_CIDR3
+#define GICR_PIDR0 GICD_PIDR0
+#define GICR_PIDR1 GICD_PIDR1
+#define GICR_PIDR2 GICD_PIDR2
+#define GICR_PIDR3 GICD_PIDR3
+#define GICR_PIDR4 GICD_PIDR4
+#define GICR_PIDR5 GICD_PIDR5
+#define GICR_PIDR6 GICD_PIDR6
+#define GICR_PIDR7 GICD_PIDR7
+
+#define GICR_SGI_BASE 0x10000
+#define GICR_IGROUPR GICD_IGROUPR
+#define GICR_ISENABLER GICD_ISENABLER
+#define GICR_ICENABLER GICD_ICENABLER
+#define GICR_ISACTIVER GICD_ISACTIVER
+#define GICR_ICACTIVER GICD_ICACTIVER
+#define GICR_IPRIORITY GICD_IPRIORITY
+
+#define GICR_TYPER_Last (1 << 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_HPPIR1_EL1 SYSREG_32(0, c12, c12, 2)
+#define ICC_BPR1_EL1 SYSREG_32(0, c12, c12, 3)
+#define ICC_DIR_EL1 SYSREG_32(0, c12, c11, 1)
+#define ICC_PMR_EL1 SYSREG_32(0, c4, c6, 0)
+#define ICC_RPR_EL1 SYSREG_32(0, c12, c11, 3)
+#define ICC_CTLR_EL1 SYSREG_32(0, c12, c12, 4)
+#define ICC_SRE_EL1 SYSREG_32(0, c12, c12, 5)
+#define ICC_SRE_EL2 SYSREG_32(4, c12, c9, 5)
+#define ICC_IGRPEN1_EL1 SYSREG_32(0, c12, c12, 7)
+#define ICC_SGI1R_EL1 SYSREG_64(0, c12)
+#define ICC_AP1R0_EL1 SYSREG_32(0, c12, c9, 0)
+#define ICC_AP1R1_EL1 SYSREG_32(0, c12, c9, 1)
+#define ICC_AP1R2_EL1 SYSREG_32(0, c12, c9, 2)
+#define ICC_AP1R3_EL1 SYSREG_32(0, c12, c9, 3)
+
+#define ICH_HCR_EL2 SYSREG_32(4, c12, c11, 0)
+#define ICH_VTR_EL2 SYSREG_32(4, c12, c11, 1)
+#define ICH_MISR_EL2 SYSREG_32(4, c12, c11, 2)
+#define ICH_EISR_EL2 SYSREG_32(4, c12, c11, 3)
+#define ICH_ELSR_EL2 SYSREG_32(4, c12, c11, 5)
+#define ICH_VMCR_EL2 SYSREG_32(4, c12, c11, 7)
+#define ICH_AP1R0_EL2 SYSREG_32(4, c12, c9, 0)
+#define ICH_AP1R1_EL2 SYSREG_32(4, c12, c9, 1)
+#define ICH_AP1R2_EL2 SYSREG_32(4, c12, c9, 2)
+#define ICH_AP1R3_EL2 SYSREG_32(4, c12, c9, 3)
+
+/* Different on AArch32 and AArch64... */
+#define __ICH_LR0(x) SYSREG_32(4, c12, c12, x)
+#define __ICH_LR8(x) SYSREG_32(4, c12, c13, x)
+#define __ICH_LRC0(x) SYSREG_32(4, c12, c14, x)
+#define __ICH_LRC8(x) SYSREG_32(4, c12, c15, x)
+
+#define ICH_LR0 __ICH_LR0(0)
+#define ICH_LR1 __ICH_LR0(1)
+#define ICH_LR2 __ICH_LR0(2)
+#define ICH_LR3 __ICH_LR0(3)
+#define ICH_LR4 __ICH_LR0(4)
+#define ICH_LR5 __ICH_LR0(5)
+#define ICH_LR6 __ICH_LR0(6)
+#define ICH_LR7 __ICH_LR0(7)
+#define ICH_LR8 __ICH_LR8(0)
+#define ICH_LR9 __ICH_LR8(1)
+#define ICH_LR10 __ICH_LR8(2)
+#define ICH_LR11 __ICH_LR8(3)
+#define ICH_LR12 __ICH_LR8(4)
+#define ICH_LR13 __ICH_LR8(5)
+#define ICH_LR14 __ICH_LR8(6)
+#define ICH_LR15 __ICH_LR8(7)
+#define ICH_LRC0 __ICH_LRC0(0)
+#define ICH_LRC1 __ICH_LRC0(1)
+#define ICH_LRC2 __ICH_LRC0(2)
+#define ICH_LRC3 __ICH_LRC0(3)
+#define ICH_LRC4 __ICH_LRC0(4)
+#define ICH_LRC5 __ICH_LRC0(5)
+#define ICH_LRC6 __ICH_LRC0(6)
+#define ICH_LRC7 __ICH_LRC0(7)
+#define ICH_LRC8 __ICH_LRC8(0)
+#define ICH_LRC9 __ICH_LRC8(1)
+#define ICH_LRC10 __ICH_LRC8(2)
+#define ICH_LRC11 __ICH_LRC8(3)
+#define ICH_LRC12 __ICH_LRC8(4)
+#define ICH_LRC13 __ICH_LRC8(5)
+#define ICH_LRC14 __ICH_LRC8(6)
+#define ICH_LRC15 __ICH_LRC8(7)
+
+#define ICC_CTLR_EOImode 0x2
+#define ICC_PMR_MASK 0xff
+#define ICC_PMR_DEFAULT 0xf0
+#define ICC_IGRPEN1_EN 0x1
+
+#define ICC_SGIR_AFF3_SHIFT 48
+#define ICC_SGIR_AFF2_SHIFT 32
+#define ICC_SGIR_AFF1_SHIFT 16
+#define ICC_SGIR_TARGET_MASK 0xffff
+#define ICC_SGIR_IRQN_SHIFT 24
+#define ICC_SGIR_ROUTING_BIT (1ULL << 40)
+
+#define ICH_HCR_EN (1 << 0)
+#define ICH_HCR_UIE (1 << 1)
+#define ICH_HCR_LRENPIE (1 << 2)
+#define ICH_HCR_NPIE (1 << 3)
+#define ICH_HCR_VGRP0EIE (1 << 4)
+#define ICH_HCR_VGRP0DIE (1 << 5)
+#define ICH_HCR_VGRP1EIE (1 << 6)
+#define ICH_HCR_VGRP1DIE (1 << 7)
+#define ICH_HCR_VARE (1 << 9)
+#define ICH_HCR_TC (1 << 10)
+#define ICH_HCR_TALL0 (1 << 11)
+#define ICH_HCR_TALL1 (1 << 12)
+#define ICH_HCR_TSEI (1 << 13)
+#define ICH_HCR_EOICount (0x1f << 27)
+
+#define ICH_MISR_EOI (1 << 0)
+#define ICH_MISR_U (1 << 1)
+#define ICH_MISR_LRENP (1 << 2)
+#define ICH_MISR_NP (1 << 3)
+#define ICH_MISR_VGRP0E (1 << 4)
+#define ICH_MISR_VGRP0D (1 << 5)
+#define ICH_MISR_VGRP1E (1 << 6)
+#define ICH_MISR_VGRP1D (1 << 7)
+
+#define ICH_VMCR_VENG0 (1 << 0)
+#define ICH_VMCR_VENG1 (1 << 1)
+#define ICH_VMCR_VACKCTL (1 << 2)
+#define ICH_VMCR_VFIQEN (1 << 3)
+#define ICH_VMCR_VCBPR (1 << 4)
+#define ICH_VMCR_VEOIM (1 << 9)
+#define ICH_VMCR_VBPR1_SHIFT 18
+#define ICH_VMCR_VBPR0_SHIFT 21
+#define ICH_VMCR_VPMR_SHIFT 24
+
+/* List registers upper bits */
+#define ICH_LR_INVALID (0x0ULL << 62)
+#define ICH_LR_PENDING (0x1ULL << 62)
+#define ICH_LR_ACTIVE (0x2ULL << 62)
+#define ICH_LR_PENDACTIVE (0x3ULL << 62)
+#define ICH_LR_HW_BIT (0x1ULL << 61)
+#define ICH_LR_GROUP_BIT (0x1ULL << 60)
+#define ICH_LR_PRIORITY_SHIFT 48
+#define ICH_LR_SGI_EOI (0x1ULL << 41)
+#define ICH_LR_PHYS_ID_SHIFT 32
+
+#ifndef __ASSEMBLY__
+
+#include <jailhouse/types.h>
+
+static inline u64 gic_read_lr(unsigned int n)
+{
+ u32 lr, lrc;
+
+ switch (n) {
+#define __READ_LR(n) \
+ case n: \
+ arm_read_sysreg(ICH_LR##n, lr); \
+ arm_read_sysreg(ICH_LRC##n, lrc); \
+ break;
+
+ __READ_LR(0)
+ __READ_LR(1)
+ __READ_LR(2)
+ __READ_LR(3)
+ __READ_LR(4)
+ __READ_LR(5)
+ __READ_LR(6)
+ __READ_LR(7)
+ __READ_LR(8)
+ __READ_LR(9)
+ __READ_LR(10)
+ __READ_LR(11)
+ __READ_LR(12)
+ __READ_LR(13)
+ __READ_LR(14)
+ __READ_LR(15)
+#undef __READ_LR
+
+ default:
+ return (u64)(-1);
+ }
+
+ return (u64)lrc << 32 | lr;
+}
+
+static inline void gic_write_lr(unsigned int n, u64 val)
+{
+ u32 lr = (u32)val;
+ u32 lrc = val >> 32;
+
+ switch (n) {
+#define __WRITE_LR(n) \
+ case n: \
+ arm_write_sysreg(ICH_LR##n, lr); \
+ arm_write_sysreg(ICH_LRC##n, lrc); \
+ break;
+
+ __WRITE_LR(0)
+ __WRITE_LR(1)
+ __WRITE_LR(2)
+ __WRITE_LR(3)
+ __WRITE_LR(4)
+ __WRITE_LR(5)
+ __WRITE_LR(6)
+ __WRITE_LR(7)
+ __WRITE_LR(8)
+ __WRITE_LR(9)
+ __WRITE_LR(10)
+ __WRITE_LR(11)
+ __WRITE_LR(12)
+ __WRITE_LR(13)
+ __WRITE_LR(14)
+ __WRITE_LR(15)
+#undef __WRITE_LR
+ }
+}
+
+static inline u32 gic_read_iar(void)
+{
+ u32 irq_id;
+
+ arm_read_sysreg(ICC_IAR1_EL1, irq_id);
+ return irq_id;
+}
+
+void gicv3_handle_sgir_write(u64 sgir);
+
+#endif /* __ASSEMBLY__ */
+#endif /* _JAILHOUSE_ASM_GIC_V3_H */
diff --git a/hypervisor/arch/arm/Kbuild b/hypervisor/arch/arm/Kbuild
index b996871..04e835c 100644
--- a/hypervisor/arch/arm/Kbuild
+++ b/hypervisor/arch/arm/Kbuild
@@ -26,5 +26,4 @@ obj-y += mmu_hyp.o caches.o mach-stubs.o
# should switch to that for higher granularity, but gcc7 is not even there
CFLAGS_mmu_hyp.o += -fno-profile-arcs -fno-test-coverage

-obj-$(CONFIG_ARM_GIC_V3) += gic-v3.o
obj-$(CONFIG_MACH_VEXPRESS) += mach-vexpress.o
diff --git a/hypervisor/arch/arm/gic-v3.c b/hypervisor/arch/arm/gic-v3.c
deleted file mode 100644
index 2ea947f..0000000
--- a/hypervisor/arch/arm/gic-v3.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * Jailhouse, a Linux-based partitioning hypervisor
- *
- * Copyright (c) ARM Limited, 2014
- *
- * Authors:
- * Jean-Philippe Brucker <jean-phili...@arm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- */
-
-#include <jailhouse/control.h>
-#include <jailhouse/mmio.h>
-#include <jailhouse/printk.h>
-#include <jailhouse/processor.h>
-#include <jailhouse/types.h>
-#include <asm/control.h>
-#include <asm/gic.h>
-#include <asm/irqchip.h>
-#include <asm/setup.h>
-#include <asm/traps.h>
-
-/*
- * This implementation assumes that the kernel driver already initialised most
- * of the GIC.
- * There is almost no instruction barrier, since IRQs are always disabled in the
- * hyp, and ERET serves as the context synchronization event.
- */
-
-static unsigned int gic_num_lr;
-static unsigned int gic_num_priority_bits;
-static u32 gic_version;
-
-static void *gicr_base;
-
-static int gic_init(void)
-{
- /* TODO: need to validate more? */
- if (!(mmio_read32(gicd_base + GICD_CTLR) & GICD_CTLR_ARE_NS))
- return trace_error(-EIO);
-
- /* Let the per-cpu code access the redistributors */
- gicr_base = paging_map_device(
- system_config->platform_info.arm.gicr_base, GICR_SIZE);
- if (!gicr_base)
- return -ENOMEM;
-
- return 0;
-}
-
-static void gic_clear_pending_irqs(void)
-{
- unsigned int n;
-
- /* Clear list registers. */
- for (n = 0; n < gic_num_lr; n++)
- gic_write_lr(n, 0);
-
- /* Clear active priority bits */
- if (gic_num_priority_bits >= 5)
- arm_write_sysreg(ICH_AP1R0_EL2, 0);
- if (gic_num_priority_bits >= 6)
- arm_write_sysreg(ICH_AP1R1_EL2, 0);
- if (gic_num_priority_bits > 6) {
- arm_write_sysreg(ICH_AP1R2_EL2, 0);
- arm_write_sysreg(ICH_AP1R3_EL2, 0);
- }
-}
-
-static void gic_cpu_reset(struct per_cpu *cpu_data)
-{
- unsigned int mnt_irq = system_config->platform_info.arm.maintenance_irq;
- void *gicr = cpu_data->gicr_base + GICR_SGI_BASE;
-
- gic_clear_pending_irqs();
-
- /* Ensure all IPIs and the maintenance PPI are enabled. */
- mmio_write32(gicr + GICR_ISENABLER, 0x0000ffff | (1 << mnt_irq));
-
- /* Disable PPIs, except for the maintenance interrupt. */
- mmio_write32(gicr + GICR_ICENABLER, 0xffff0000 & ~(1 << mnt_irq));
-
- /* Deactivate all active PPIs */
- mmio_write32(gicr + GICR_ICACTIVER, 0xffff0000);
-
- arm_write_sysreg(ICH_VMCR_EL2, 0);
-}
-
-static int gic_cpu_init(struct per_cpu *cpu_data)
-{
- unsigned int mnt_irq = system_config->platform_info.arm.maintenance_irq;
- u64 typer;
- u32 pidr;
- u32 cell_icc_ctlr, cell_icc_pmr, cell_icc_igrpen1;
- u32 ich_vtr;
- u32 ich_vmcr;
- void *redist_base = gicr_base;
-
- /* Find redistributor */
- do {
- pidr = mmio_read32(redist_base + GICR_PIDR2);
- gic_version = GICR_PIDR2_ARCH(pidr);
- if (gic_version != 3 && gic_version != 4)
- break;
-
- typer = mmio_read64(redist_base + GICR_TYPER);
- if ((typer >> 32) == cpu_data->cpu_id) {
- cpu_data->gicr_base = redist_base;
- break;
- }
-
- redist_base += gic_version == 4 ? 0x40000 : 0x20000;
- } while (!(typer & GICR_TYPER_Last));
-
- if (!cpu_data->gicr_base) {
- printk("GIC: No redist found for CPU%d\n", cpu_data->cpu_id);
- return -ENODEV;
- }
-
- /* Ensure all IPIs and the maintenance PPI are enabled. */
- mmio_write32(redist_base + GICR_SGI_BASE + GICR_ISENABLER,
- 0x0000ffff | (1 << mnt_irq));
-
- /*
- * Set EOIMode to 1
- * This allow to drop the priority of level-triggered interrupts without
- * deactivating them, and thus ensure that they won't be immediately
- * re-triggered. (e.g. timer)
- * They can then be injected into the guest using the LR.HW bit, and
- * will be deactivated once the guest does an EOI after handling the
- * interrupt source.
- */
- arm_read_sysreg(ICC_CTLR_EL1, cell_icc_ctlr);
- arm_write_sysreg(ICC_CTLR_EL1, ICC_CTLR_EOImode);
-
- arm_read_sysreg(ICC_PMR_EL1, cell_icc_pmr);
- arm_write_sysreg(ICC_PMR_EL1, ICC_PMR_DEFAULT);
-
- arm_read_sysreg(ICC_IGRPEN1_EL1, cell_icc_igrpen1);
- arm_write_sysreg(ICC_IGRPEN1_EL1, ICC_IGRPEN1_EN);
-
- arm_read_sysreg(ICH_VTR_EL2, ich_vtr);
- gic_num_lr = (ich_vtr & 0xf) + 1;
- gic_num_priority_bits = (ich_vtr >> 29) + 1;
-
- /*
- * Clear pending virtual IRQs in case anything is left from previous
- * use. Physically pending IRQs will be forwarded to Linux once we
- * enable interrupts for the hypervisor.
- */
- gic_clear_pending_irqs();
-
- ich_vmcr = (cell_icc_pmr & ICC_PMR_MASK) << ICH_VMCR_VPMR_SHIFT;
- if (cell_icc_igrpen1 & ICC_IGRPEN1_EN)
- ich_vmcr |= ICH_VMCR_VENG1;
- if (cell_icc_ctlr & ICC_CTLR_EOImode)
- ich_vmcr |= ICH_VMCR_VEOIM;
- arm_write_sysreg(ICH_VMCR_EL2, ich_vmcr);
-
- /* After this, the cells access the virtual interface of the GIC. */
- arm_write_sysreg(ICH_HCR_EL2, ICH_HCR_EN);
-
- return 0;
-}
-
-static void gic_cpu_shutdown(struct per_cpu *cpu_data)
-{
- u32 ich_vmcr, icc_ctlr, cell_icc_igrpen1;
-
- if (!cpu_data->gicr_base)
- return;
-
- arm_write_sysreg(ICH_HCR_EL2, 0);
-
- /* Disable the maintenance interrupt - not used by Linux. */
- mmio_write32(cpu_data->gicr_base + GICR_SGI_BASE + GICR_ICENABLER,
- 1 << system_config->platform_info.arm.maintenance_irq);
-
- /* Restore the root config */
- arm_read_sysreg(ICH_VMCR_EL2, ich_vmcr);
-
- if (!(ich_vmcr & ICH_VMCR_VEOIM)) {
- arm_read_sysreg(ICC_CTLR_EL1, icc_ctlr);
- icc_ctlr &= ~ICC_CTLR_EOImode;
- arm_write_sysreg(ICC_CTLR_EL1, icc_ctlr);
- }
- if (!(ich_vmcr & ICH_VMCR_VENG1)) {
- arm_read_sysreg(ICC_IGRPEN1_EL1, cell_icc_igrpen1);
- cell_icc_igrpen1 &= ~ICC_IGRPEN1_EN;
- arm_write_sysreg(ICC_IGRPEN1_EL1, cell_icc_igrpen1);
- }
-}
-
-static void gic_adjust_irq_target(struct cell *cell, u16 irq_id)
-{
- void *irouter = gicd_base + GICD_IROUTER + irq_id;
- u32 route = mmio_read32(irouter);
-
- if (!cell_owns_cpu(cell, route))
- mmio_write32(irouter, first_cpu(cell->cpu_set));
-}
-
-static enum mmio_result gic_handle_redist_access(void *arg,
- struct mmio_access *mmio)
-{
- struct cell *cell = this_cell();
- unsigned int cpu;
- unsigned int virt_id;
- unsigned int redist_size = (gic_version == 4) ? 0x40000 : 0x20000;
- void *phys_redist = NULL;
- unsigned long offs;
-
- /*
- * The redistributor accessed by the cell is not the one stored in these
- * cpu_datas, but the one associated to its virtual id. So we first
- * need to translate the redistributor address.
- */
- for_each_cpu(cpu, cell->cpu_set) {
- virt_id = arm_cpu_phys2virt(cpu);
- offs = per_cpu(virt_id)->gicr_base - gicr_base;
- if (mmio->address >= offs &&
- mmio->address < offs + redist_size) {
- phys_redist = per_cpu(cpu)->gicr_base;
- break;
- }
- }
-
- if (phys_redist == NULL)
- return MMIO_ERROR;
-
- mmio->address -= offs;
-
- /* Change the ID register, all other accesses are allowed. */
- if (!mmio->is_write) {
- switch (mmio->address) {
- case GICR_TYPER:
- if (virt_id == cell->arch.last_virt_id)
- mmio->value = GICR_TYPER_Last;
- else
- mmio->value = 0;
- /* AArch64 can use a writeq for this register */
- if (mmio->size == 8)
- mmio->value |= (u64)virt_id << 32;
-
- return MMIO_HANDLED;
- case GICR_TYPER + 4:
- /* Upper bits contain the affinity */
- mmio->value = virt_id;
- return MMIO_HANDLED;
- }
- }
- mmio_perform_access(phys_redist, mmio);
- return MMIO_HANDLED;
-}
-
-static int gic_cell_init(struct cell *cell)
-{
- mmio_region_register(cell, system_config->platform_info.arm.gicr_base,
- GICR_SIZE, gic_handle_redist_access, NULL);
-
- return 0;
-}
-
-static int gic_send_sgi(struct sgi *sgi)
-{
- u64 val;
- u16 targets = sgi->targets;
-
- if (!is_sgi(sgi->id))
- return -EINVAL;
-
- if (sgi->routing_mode == 2)
- targets = 1 << phys_processor_id();
-
- val = (u64)sgi->aff3 << ICC_SGIR_AFF3_SHIFT
- | (u64)sgi->aff2 << ICC_SGIR_AFF2_SHIFT
- | sgi->aff1 << ICC_SGIR_AFF1_SHIFT
- | (targets & ICC_SGIR_TARGET_MASK)
- | (sgi->id & 0xf) << ICC_SGIR_IRQN_SHIFT;
-
- if (sgi->routing_mode == 1)
- val |= ICC_SGIR_ROUTING_BIT;
-
- /*
- * Ensure the targets see our modifications to their per-cpu
- * structures.
- */
- dsb(ish);
-
- arm_write_sysreg(ICC_SGI1R_EL1, val);
- isb();
-
- return 0;
-}
-
-void gicv3_handle_sgir_write(u64 sgir)
-{
- struct sgi sgi;
- unsigned long routing_mode = !!(sgir & ICC_SGIR_ROUTING_BIT);
-
- /* FIXME: clusters are not supported yet. */
- sgi.targets = sgir & ICC_SGIR_TARGET_MASK;
- sgi.routing_mode = routing_mode;
- sgi.aff1 = sgir >> ICC_SGIR_AFF1_SHIFT & 0xff;
- sgi.aff2 = sgir >> ICC_SGIR_AFF2_SHIFT & 0xff;
- sgi.aff3 = sgir >> ICC_SGIR_AFF3_SHIFT & 0xff;
- sgi.id = sgir >> ICC_SGIR_IRQN_SHIFT & 0xf;
-
- gic_handle_sgir_write(&sgi, true);
-}
-
-/*
- * GICv3 uses a 64bit register IROUTER for each IRQ
- */
-enum mmio_result gic_handle_irq_route(struct mmio_access *mmio,
- unsigned int irq)
-{
- struct cell *cell = this_cell();
- unsigned int cpu;
-
- /* Ignore aff3 on AArch32 (return 0) */
- if (mmio->size == 4 && (mmio->address % 8))
- return MMIO_HANDLED;
-
- /* SGIs and PPIs are res0 */
- if (!is_spi(irq))
- return MMIO_HANDLED;
-
- /*
- * Ignore accesses to SPIs that do not belong to the cell. This isn't
- * forbidden, because the guest driver may simply iterate over all
- * registers at initialisation
- */
- if (!irqchip_irq_in_cell(cell, irq))
- return MMIO_HANDLED;
-
- /* Translate the virtual cpu id into the physical one */
- if (mmio->is_write) {
- mmio->value = arm_cpu_virt2phys(cell, mmio->value);
- if (mmio->value == -1) {
- printk("Attempt to route IRQ%d outside of cell\n", irq);
- return MMIO_ERROR;
- }
- mmio_perform_access(gicd_base, mmio);
- } else {
- cpu = mmio_read32(gicd_base + GICD_IROUTER + 8 * irq);
- mmio->value = arm_cpu_phys2virt(cpu);
- }
- return MMIO_HANDLED;
-}
-
-static void gic_eoi_irq(u32 irq_id, bool deactivate)
-{
- arm_write_sysreg(ICC_EOIR1_EL1, irq_id);
- if (deactivate)
- arm_write_sysreg(ICC_DIR_EL1, irq_id);
-}
-
-static int gic_inject_irq(struct per_cpu *cpu_data, u16 irq_id)
-{
- int i;
- int free_lr = -1;
- u32 elsr;
- u64 lr;
-
- arm_read_sysreg(ICH_ELSR_EL2, elsr);
- for (i = 0; i < gic_num_lr; i++) {
- if ((elsr >> i) & 1) {
- /* Entry is invalid, candidate for injection */
- if (free_lr == -1)
- free_lr = i;
- continue;
- }
-
- /*
- * Entry is in use, check that it doesn't match the one we want
- * to inject.
- */
- lr = gic_read_lr(i);
-
- /*
- * A strict phys->virt id mapping is used for SPIs, so this test
- * should be sufficient.
- */
- if ((u32)lr == irq_id)
- return -EEXIST;
- }
-
- if (free_lr == -1)
- /* All list registers are in use */
- return -EBUSY;
-
- lr = irq_id;
- /* Only group 1 interrupts */
- lr |= ICH_LR_GROUP_BIT;
- lr |= ICH_LR_PENDING;
- if (!is_sgi(irq_id)) {
- lr |= ICH_LR_HW_BIT;
- lr |= (u64)irq_id << ICH_LR_PHYS_ID_SHIFT;
- }
-
- gic_write_lr(free_lr, lr);
-
- return 0;
-}
-
-static void gicv3_enable_maint_irq(bool enable)
-{
- u32 hcr;
-
- arm_read_sysreg(ICH_HCR_EL2, hcr);
- if (enable)
- hcr |= ICH_HCR_UIE;
- else
- hcr &= ~ICH_HCR_UIE;
- arm_write_sysreg(ICH_HCR_EL2, hcr);
-}
-
-static bool gicv3_has_pending_irqs(void)
-{
- unsigned int n;
-
- for (n = 0; n < gic_num_lr; n++)
- if (gic_read_lr(n) & ICH_LR_PENDING)
- return true;
-
- return false;
-}
-
-static enum mmio_result gicv3_handle_irq_target(struct mmio_access *mmio,
- unsigned int irq)
-{
- /* ignore writes, we are in affinity routing mode */
- return MMIO_HANDLED;
-}
-
-unsigned int irqchip_mmio_count_regions(struct cell *cell)
-{
- return 2;
-}
-
-struct irqchip_ops irqchip = {
- .init = gic_init,
- .cpu_init = gic_cpu_init,
- .cpu_reset = gic_cpu_reset,
- .cpu_shutdown = gic_cpu_shutdown,
- .cell_init = gic_cell_init,
- .adjust_irq_target = gic_adjust_irq_target,
- .send_sgi = gic_send_sgi,
- .inject_irq = gic_inject_irq,
- .enable_maint_irq = gicv3_enable_maint_irq,
- .has_pending_irqs = gicv3_has_pending_irqs,
- .eoi_irq = gic_eoi_irq,
- .handle_irq_target = gicv3_handle_irq_target,
-};
diff --git a/hypervisor/arch/arm/include/asm/gic_v3.h b/hypervisor/arch/arm/include/asm/gic_v3.h
deleted file mode 100644
index d1b9346..0000000
--- a/hypervisor/arch/arm/include/asm/gic_v3.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Jailhouse, a Linux-based partitioning hypervisor
- *
- * Copyright (c) ARM Limited, 2014
- *
- * Authors:
- * Jean-Philippe Brucker <jean-phili...@arm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- */
-
-#ifndef _JAILHOUSE_ASM_GIC_V3_H
-#define _JAILHOUSE_ASM_GIC_V3_H
-
-#include <asm/sysregs.h>
-
-#define GICD_SIZE 0x10000
-#define GICR_SIZE 0x100000
-
-#define GICD_CIDR0 0xfff0
-#define GICD_CIDR1 0xfff4
-#define GICD_CIDR2 0xfff8
-#define GICD_CIDR3 0xfffc
-
-#define GICD_PIDR0 0xffe0
-#define GICD_PIDR1 0xffe4
-#define GICD_PIDR2 0xffe8
-#define GICD_PIDR3 0xffec
-#define GICD_PIDR4 0xffd0
-#define GICD_PIDR5 0xffd4
-#define GICD_PIDR6 0xffd8
-#define GICD_PIDR7 0xffdc
-
-#define GICR_CTLR GICD_CTLR
-#define GICR_TYPER 0x0008
-#define GICR_WAKER 0x0014
-#define GICR_CIDR0 GICD_CIDR0
-#define GICR_CIDR1 GICD_CIDR1
-#define GICR_CIDR2 GICD_CIDR2
-#define GICR_CIDR3 GICD_CIDR3
-#define GICR_PIDR0 GICD_PIDR0
-#define GICR_PIDR1 GICD_PIDR1
-#define GICR_PIDR2 GICD_PIDR2
-#define GICR_PIDR3 GICD_PIDR3
-#define GICR_PIDR4 GICD_PIDR4
-#define GICR_PIDR5 GICD_PIDR5
-#define GICR_PIDR6 GICD_PIDR6
-#define GICR_PIDR7 GICD_PIDR7
-
-#define GICR_SGI_BASE 0x10000
-#define GICR_IGROUPR GICD_IGROUPR
-#define GICR_ISENABLER GICD_ISENABLER
-#define GICR_ICENABLER GICD_ICENABLER
-#define GICR_ISACTIVER GICD_ISACTIVER
-#define GICR_ICACTIVER GICD_ICACTIVER
-#define GICR_IPRIORITY GICD_IPRIORITY
-
-#define GICR_TYPER_Last (1 << 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_HPPIR1_EL1 SYSREG_32(0, c12, c12, 2)
-#define ICC_BPR1_EL1 SYSREG_32(0, c12, c12, 3)
-#define ICC_DIR_EL1 SYSREG_32(0, c12, c11, 1)
-#define ICC_PMR_EL1 SYSREG_32(0, c4, c6, 0)
-#define ICC_RPR_EL1 SYSREG_32(0, c12, c11, 3)
-#define ICC_CTLR_EL1 SYSREG_32(0, c12, c12, 4)
-#define ICC_SRE_EL1 SYSREG_32(0, c12, c12, 5)
-#define ICC_SRE_EL2 SYSREG_32(4, c12, c9, 5)
-#define ICC_IGRPEN1_EL1 SYSREG_32(0, c12, c12, 7)
-#define ICC_SGI1R_EL1 SYSREG_64(0, c12)
-#define ICC_AP1R0_EL1 SYSREG_32(0, c12, c9, 0)
-#define ICC_AP1R1_EL1 SYSREG_32(0, c12, c9, 1)
-#define ICC_AP1R2_EL1 SYSREG_32(0, c12, c9, 2)
-#define ICC_AP1R3_EL1 SYSREG_32(0, c12, c9, 3)
-
-#define ICH_HCR_EL2 SYSREG_32(4, c12, c11, 0)
-#define ICH_VTR_EL2 SYSREG_32(4, c12, c11, 1)
-#define ICH_MISR_EL2 SYSREG_32(4, c12, c11, 2)
-#define ICH_EISR_EL2 SYSREG_32(4, c12, c11, 3)
-#define ICH_ELSR_EL2 SYSREG_32(4, c12, c11, 5)
-#define ICH_VMCR_EL2 SYSREG_32(4, c12, c11, 7)
-#define ICH_AP1R0_EL2 SYSREG_32(4, c12, c9, 0)
-#define ICH_AP1R1_EL2 SYSREG_32(4, c12, c9, 1)
-#define ICH_AP1R2_EL2 SYSREG_32(4, c12, c9, 2)
-#define ICH_AP1R3_EL2 SYSREG_32(4, c12, c9, 3)
-
-/* Different on AArch32 and AArch64... */
-#define __ICH_LR0(x) SYSREG_32(4, c12, c12, x)
-#define __ICH_LR8(x) SYSREG_32(4, c12, c13, x)
-#define __ICH_LRC0(x) SYSREG_32(4, c12, c14, x)
-#define __ICH_LRC8(x) SYSREG_32(4, c12, c15, x)
-
-#define ICH_LR0 __ICH_LR0(0)
-#define ICH_LR1 __ICH_LR0(1)
-#define ICH_LR2 __ICH_LR0(2)
-#define ICH_LR3 __ICH_LR0(3)
-#define ICH_LR4 __ICH_LR0(4)
-#define ICH_LR5 __ICH_LR0(5)
-#define ICH_LR6 __ICH_LR0(6)
-#define ICH_LR7 __ICH_LR0(7)
-#define ICH_LR8 __ICH_LR8(0)
-#define ICH_LR9 __ICH_LR8(1)
-#define ICH_LR10 __ICH_LR8(2)
-#define ICH_LR11 __ICH_LR8(3)
-#define ICH_LR12 __ICH_LR8(4)
-#define ICH_LR13 __ICH_LR8(5)
-#define ICH_LR14 __ICH_LR8(6)
-#define ICH_LR15 __ICH_LR8(7)
-#define ICH_LRC0 __ICH_LRC0(0)
-#define ICH_LRC1 __ICH_LRC0(1)
-#define ICH_LRC2 __ICH_LRC0(2)
-#define ICH_LRC3 __ICH_LRC0(3)
-#define ICH_LRC4 __ICH_LRC0(4)
-#define ICH_LRC5 __ICH_LRC0(5)
-#define ICH_LRC6 __ICH_LRC0(6)
-#define ICH_LRC7 __ICH_LRC0(7)
-#define ICH_LRC8 __ICH_LRC8(0)
-#define ICH_LRC9 __ICH_LRC8(1)
-#define ICH_LRC10 __ICH_LRC8(2)
-#define ICH_LRC11 __ICH_LRC8(3)
-#define ICH_LRC12 __ICH_LRC8(4)
-#define ICH_LRC13 __ICH_LRC8(5)
-#define ICH_LRC14 __ICH_LRC8(6)
-#define ICH_LRC15 __ICH_LRC8(7)
-
-#define ICC_CTLR_EOImode 0x2
-#define ICC_PMR_MASK 0xff
-#define ICC_PMR_DEFAULT 0xf0
-#define ICC_IGRPEN1_EN 0x1
-
-#define ICC_SGIR_AFF3_SHIFT 48
-#define ICC_SGIR_AFF2_SHIFT 32
-#define ICC_SGIR_AFF1_SHIFT 16
-#define ICC_SGIR_TARGET_MASK 0xffff
-#define ICC_SGIR_IRQN_SHIFT 24
-#define ICC_SGIR_ROUTING_BIT (1ULL << 40)
-
-#define ICH_HCR_EN (1 << 0)
-#define ICH_HCR_UIE (1 << 1)
-#define ICH_HCR_LRENPIE (1 << 2)
-#define ICH_HCR_NPIE (1 << 3)
-#define ICH_HCR_VGRP0EIE (1 << 4)
-#define ICH_HCR_VGRP0DIE (1 << 5)
-#define ICH_HCR_VGRP1EIE (1 << 6)
-#define ICH_HCR_VGRP1DIE (1 << 7)
-#define ICH_HCR_VARE (1 << 9)
-#define ICH_HCR_TC (1 << 10)
-#define ICH_HCR_TALL0 (1 << 11)
-#define ICH_HCR_TALL1 (1 << 12)
-#define ICH_HCR_TSEI (1 << 13)
-#define ICH_HCR_EOICount (0x1f << 27)
-
-#define ICH_MISR_EOI (1 << 0)
-#define ICH_MISR_U (1 << 1)
-#define ICH_MISR_LRENP (1 << 2)
-#define ICH_MISR_NP (1 << 3)
-#define ICH_MISR_VGRP0E (1 << 4)
-#define ICH_MISR_VGRP0D (1 << 5)
-#define ICH_MISR_VGRP1E (1 << 6)
-#define ICH_MISR_VGRP1D (1 << 7)
-
-#define ICH_VMCR_VENG0 (1 << 0)
-#define ICH_VMCR_VENG1 (1 << 1)
-#define ICH_VMCR_VACKCTL (1 << 2)
-#define ICH_VMCR_VFIQEN (1 << 3)
-#define ICH_VMCR_VCBPR (1 << 4)
-#define ICH_VMCR_VEOIM (1 << 9)
-#define ICH_VMCR_VBPR1_SHIFT 18
-#define ICH_VMCR_VBPR0_SHIFT 21
-#define ICH_VMCR_VPMR_SHIFT 24
-
-/* List registers upper bits */
-#define ICH_LR_INVALID (0x0ULL << 62)
-#define ICH_LR_PENDING (0x1ULL << 62)
-#define ICH_LR_ACTIVE (0x2ULL << 62)
-#define ICH_LR_PENDACTIVE (0x3ULL << 62)
-#define ICH_LR_HW_BIT (0x1ULL << 61)
-#define ICH_LR_GROUP_BIT (0x1ULL << 60)
-#define ICH_LR_PRIORITY_SHIFT 48
-#define ICH_LR_SGI_EOI (0x1ULL << 41)
-#define ICH_LR_PHYS_ID_SHIFT 32
-
-#ifndef __ASSEMBLY__
-
-#include <jailhouse/types.h>
-
-static inline u64 gic_read_lr(unsigned int n)
-{
- u32 lr, lrc;
-
- switch (n) {
-#define __READ_LR(n) \
- case n: \
- arm_read_sysreg(ICH_LR##n, lr); \
- arm_read_sysreg(ICH_LRC##n, lrc); \
- break;
-
- __READ_LR(0)
- __READ_LR(1)
- __READ_LR(2)
- __READ_LR(3)
- __READ_LR(4)
- __READ_LR(5)
- __READ_LR(6)
- __READ_LR(7)
- __READ_LR(8)
- __READ_LR(9)
- __READ_LR(10)
- __READ_LR(11)
- __READ_LR(12)
- __READ_LR(13)
- __READ_LR(14)
- __READ_LR(15)
-#undef __READ_LR
-
- default:
- return (u64)(-1);
- }
-
- return (u64)lrc << 32 | lr;
-}
-
-static inline void gic_write_lr(unsigned int n, u64 val)
-{
- u32 lr = (u32)val;
- u32 lrc = val >> 32;
-
- switch (n) {
-#define __WRITE_LR(n) \
- case n: \
- arm_write_sysreg(ICH_LR##n, lr); \
- arm_write_sysreg(ICH_LRC##n, lrc); \
- break;
-
- __WRITE_LR(0)
- __WRITE_LR(1)
- __WRITE_LR(2)
- __WRITE_LR(3)
- __WRITE_LR(4)
- __WRITE_LR(5)
- __WRITE_LR(6)
- __WRITE_LR(7)
- __WRITE_LR(8)
- __WRITE_LR(9)
- __WRITE_LR(10)
- __WRITE_LR(11)
- __WRITE_LR(12)
- __WRITE_LR(13)
- __WRITE_LR(14)
- __WRITE_LR(15)
-#undef __WRITE_LR
- }
-}
-
-static inline u32 gic_read_iar(void)
-{
- u32 irq_id;
-
- arm_read_sysreg(ICC_IAR1_EL1, irq_id);
- return irq_id;
-}
-
-void gicv3_handle_sgir_write(u64 sgir);
-
-#endif /* __ASSEMBLY__ */
-#endif /* _JAILHOUSE_ASM_GIC_V3_H */
--
1.9.1

Nikhil Devshatwar

unread,
Jul 20, 2017, 5:28:01 AM7/20/17
to jan.k...@siemens.com, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com, Nikhil Devshatwar
Signed-off-by: Nikhil Devshatwar <nikh...@ti.com>
---
inmates/lib/arm-common/Makefile.lib | 1 +
inmates/lib/arm-common/gic-v3.c | 58 +++++++++++++++++++++++++++++++++++++
inmates/lib/arm/Makefile | 1 -
inmates/lib/arm/gic-v3.c | 58 -------------------------------------
4 files changed, 59 insertions(+), 59 deletions(-)
create mode 100644 inmates/lib/arm-common/gic-v3.c
delete mode 100644 inmates/lib/arm/gic-v3.c

diff --git a/inmates/lib/arm-common/Makefile.lib b/inmates/lib/arm-common/Makefile.lib
index f66f452..31c0855 100644
--- a/inmates/lib/arm-common/Makefile.lib
+++ b/inmates/lib/arm-common/Makefile.lib
@@ -16,5 +16,6 @@ OBJS-y := ../string.o ../cmdline.o
OBJS-y += printk.o gic.o timer.o
OBJS-y += uart-jailhouse.o uart-pl011.o uart-8250.o uart-xuartps.o
OBJS-$(CONFIG_ARM_GIC_V2) += gic-v2.o
+OBJS-$(CONFIG_ARM_GIC_V3) += gic-v3.o

COMMON_OBJECTS = $(addprefix ../arm-common/,$(OBJS-y))
diff --git a/inmates/lib/arm-common/gic-v3.c b/inmates/lib/arm-common/gic-v3.c
new file mode 100644
index 0000000..6831597
--- /dev/null
+++ b/inmates/lib/arm-common/gic-v3.c
@@ -0,0 +1,58 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) ARM Limited, 2014
+ *
+ * Authors:
+ * Jean-Philippe Brucker <jean-phili...@arm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <asm/sysregs.h>
+#include <mach.h>
+#include <gic.h>
+
+#define GICR_SGI_BASE 0x10000
+#define GICR_ISENABLER GICD_ISENABLER
+
+#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)
+#define ICC_CTLR_EL1 SYSREG_32(0, c12, c12, 4)
+#define ICC_IGRPEN1_EL1 SYSREG_32(0, c12, c12, 7)
+
+#define ICC_IGRPEN1_EN 0x1
+
+void gic_enable(unsigned int irqn)
+{
+ if (is_sgi_ppi(irqn))
+ 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,
+ 1 << (irqn % 32));
+}
+
+int gic_init(void)
+{
+ arm_write_sysreg(ICC_CTLR_EL1, 0);
+ arm_write_sysreg(ICC_PMR_EL1, 0xf0);
+ arm_write_sysreg(ICC_IGRPEN1_EL1, ICC_IGRPEN1_EN);
+
+ return 0;
+}
+
+void gic_write_eoi(u32 irqn)
+{
+ arm_write_sysreg(ICC_EOIR1_EL1, irqn);
+}
+
+u32 gic_read_ack(void)
+{
+ u32 val;
+
+ arm_read_sysreg(ICC_IAR1_EL1, val);
+ return val;
+}
diff --git a/inmates/lib/arm/Makefile b/inmates/lib/arm/Makefile
index 7326c32..bc17e07 100644
--- a/inmates/lib/arm/Makefile
+++ b/inmates/lib/arm/Makefile
@@ -19,4 +19,3 @@ ccflags-y := -ffunction-sections

lib-y := $(COMMON_OBJECTS)
lib-y += header.o
-lib-$(CONFIG_ARM_GIC_V3) += gic-v3.o
diff --git a/inmates/lib/arm/gic-v3.c b/inmates/lib/arm/gic-v3.c
deleted file mode 100644
index 6831597..0000000
--- a/inmates/lib/arm/gic-v3.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Jailhouse, a Linux-based partitioning hypervisor
- *
- * Copyright (c) ARM Limited, 2014
- *
- * Authors:
- * Jean-Philippe Brucker <jean-phili...@arm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- */
-
-#include <asm/sysregs.h>
-#include <mach.h>
-#include <gic.h>
-
-#define GICR_SGI_BASE 0x10000
-#define GICR_ISENABLER GICD_ISENABLER
-
-#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)
-#define ICC_CTLR_EL1 SYSREG_32(0, c12, c12, 4)
-#define ICC_IGRPEN1_EL1 SYSREG_32(0, c12, c12, 7)
-
-#define ICC_IGRPEN1_EN 0x1
-
-void gic_enable(unsigned int irqn)
-{
- if (is_sgi_ppi(irqn))
- 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,
- 1 << (irqn % 32));
-}
-
-int gic_init(void)
-{
- arm_write_sysreg(ICC_CTLR_EL1, 0);
- arm_write_sysreg(ICC_PMR_EL1, 0xf0);
- arm_write_sysreg(ICC_IGRPEN1_EL1, ICC_IGRPEN1_EN);
-
- return 0;
-}
-
-void gic_write_eoi(u32 irqn)
-{
- arm_write_sysreg(ICC_EOIR1_EL1, irqn);
-}
-
-u32 gic_read_ack(void)
-{
- u32 val;
-
- arm_read_sysreg(ICC_IAR1_EL1, val);
- return val;
-}
--
1.9.1

Nikhil Devshatwar

unread,
Jul 20, 2017, 5:28:03 AM7/20/17
to jan.k...@siemens.com, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com, Nikhil Devshatwar
Getting compiler issues when using GIC V3 in 64bit mode
Update the sysreg macros to solve these compiler issues

Signed-off-by: Nikhil Devshatwar <nikh...@ti.com>
---
hypervisor/arch/arm-common/include/asm/gic_v3.h | 2 +-
hypervisor/arch/arm64/include/asm/sysregs.h | 12 +++++++++---
2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/hypervisor/arch/arm-common/include/asm/gic_v3.h b/hypervisor/arch/arm-common/include/asm/gic_v3.h
index d1b9346..1fcd5a4 100644
--- a/hypervisor/arch/arm-common/include/asm/gic_v3.h
+++ b/hypervisor/arch/arm-common/include/asm/gic_v3.h
@@ -70,7 +70,7 @@
#define ICC_SRE_EL1 SYSREG_32(0, c12, c12, 5)
#define ICC_SRE_EL2 SYSREG_32(4, c12, c9, 5)
#define ICC_IGRPEN1_EL1 SYSREG_32(0, c12, c12, 7)
-#define ICC_SGI1R_EL1 SYSREG_64(0, c12)
+#define ICC_SGI1R_EL1 SYSREG_64(0, c12, c11, 5)
#define ICC_AP1R0_EL1 SYSREG_32(0, c12, c9, 0)
#define ICC_AP1R1_EL1 SYSREG_32(0, c12, c9, 1)
#define ICC_AP1R2_EL1 SYSREG_32(0, c12, c9, 2)
diff --git a/hypervisor/arch/arm64/include/asm/sysregs.h b/hypervisor/arch/arm64/include/asm/sysregs.h
index d0f8fa3..565012b 100644
--- a/hypervisor/arch/arm64/include/asm/sysregs.h
+++ b/hypervisor/arch/arm64/include/asm/sysregs.h
@@ -146,11 +146,17 @@

#ifndef __ASSEMBLY__

-#define arm_write_sysreg(sysreg, val) \
+#define SYSREG_32(a, b, c, d) s3_##a ##_##b ##_##c ##_##d
+#define SYSREG_64(a, b, c, d) s3_##a ##_##b ##_##c ##_##d
+
+
+#define arm_write_sysreg1(sysreg, val) \
asm volatile ("msr "#sysreg", %0\n" : : "r"((u64)(val)))
+#define arm_write_sysreg(a , b) arm_write_sysreg1( a, b)

-#define arm_read_sysreg(sysreg, val) \
- asm volatile ("mrs %0, "#sysreg"\n" : "=r"((u64)(val)))
+#define arm_read_sysreg1(sysreg, val) \
+ asm volatile ("mrs %0, "#sysreg"\n" : "=r"((val)))
+#define arm_read_sysreg(a , b) arm_read_sysreg1( a, b)

#endif /* __ASSEMBLY__ */

--
1.9.1

Nikhil Devshatwar

unread,
Jul 20, 2017, 5:28:05 AM7/20/17
to jan.k...@siemens.com, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com, Nikhil Devshatwar
virt_id is not available when working with GIC v3
It needs to be properly supported later
For now, disable using virt_id

Signed-off-by: Nikhil Devshatwar <nikh...@ti.com>
---
hypervisor/arch/arm-common/gic-v3.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/hypervisor/arch/arm-common/gic-v3.c b/hypervisor/arch/arm-common/gic-v3.c
index 2ea947f..5f9c6e7 100644
--- a/hypervisor/arch/arm-common/gic-v3.c
+++ b/hypervisor/arch/arm-common/gic-v3.c
@@ -217,7 +217,8 @@ static enum mmio_result gic_handle_redist_access(void *arg,
* need to translate the redistributor address.
*/
for_each_cpu(cpu, cell->cpu_set) {
- virt_id = arm_cpu_phys2virt(cpu);
+ //virt_id = arm_cpu_phys2virt(cpu);
+ virt_id = cpu;
offs = per_cpu(virt_id)->gicr_base - gicr_base;
if (mmio->address >= offs &&
mmio->address < offs + redist_size) {
@@ -235,9 +236,11 @@ static enum mmio_result gic_handle_redist_access(void *arg,
if (!mmio->is_write) {
switch (mmio->address) {
case GICR_TYPER:
+#if 0
if (virt_id == cell->arch.last_virt_id)
mmio->value = GICR_TYPER_Last;
else
+#endif
mmio->value = 0;
/* AArch64 can use a writeq for this register */
if (mmio->size == 8)
@@ -337,7 +340,8 @@ enum mmio_result gic_handle_irq_route(struct mmio_access *mmio,

/* Translate the virtual cpu id into the physical one */
if (mmio->is_write) {
- mmio->value = arm_cpu_virt2phys(cell, mmio->value);
+ //mmio->value = arm_cpu_virt2phys(cell, mmio->value);
+ mmio->value = mmio->value;
if (mmio->value == -1) {
printk("Attempt to route IRQ%d outside of cell\n", irq);
return MMIO_ERROR;
@@ -345,7 +349,8 @@ enum mmio_result gic_handle_irq_route(struct mmio_access *mmio,
mmio_perform_access(gicd_base, mmio);
} else {
cpu = mmio_read32(gicd_base + GICD_IROUTER + 8 * irq);
- mmio->value = arm_cpu_phys2virt(cpu);
+ //mmio->value = arm_cpu_phys2virt(cpu);
+ mmio->value = cpu;
}
return MMIO_HANDLED;
}
--
1.9.1

Nikhil Devshatwar

unread,
Jul 20, 2017, 5:28:11 AM7/20/17
to jan.k...@siemens.com, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com, Nikhil Devshatwar
ICH_LRC is available in aarch32 state
In aarch64 state, ICH_LR is a 64bit system register
Writing to ICH_LRC generates exception, remove it

Signed-off-by: Nikhil Devshatwar <nikh...@ti.com>
---
hypervisor/arch/arm-common/include/asm/gic_v3.h | 2 --
1 file changed, 2 deletions(-)

diff --git a/hypervisor/arch/arm-common/include/asm/gic_v3.h b/hypervisor/arch/arm-common/include/asm/gic_v3.h
index 1fcd5a4..cac47db 100644
--- a/hypervisor/arch/arm-common/include/asm/gic_v3.h
+++ b/hypervisor/arch/arm-common/include/asm/gic_v3.h
@@ -226,13 +226,11 @@ static inline u64 gic_read_lr(unsigned int n)
static inline void gic_write_lr(unsigned int n, u64 val)
{
u32 lr = (u32)val;
- u32 lrc = val >> 32;

switch (n) {
#define __WRITE_LR(n) \
case n: \
arm_write_sysreg(ICH_LR##n, lr); \
- arm_write_sysreg(ICH_LRC##n, lrc); \
break;

__WRITE_LR(0)
--
1.9.1

Nikhil Devshatwar

unread,
Jul 20, 2017, 5:28:27 AM7/20/17
to jan.k...@siemens.com, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com, Nikhil Devshatwar
I am not sure if the code is wrong or the
config file does not correctly map the cpu_set

Currently, the cpu_id is passed as logical CPU number (0,1,2,3..)
But the TYPER register affinity is (0, 1, 100, 101...)

Correct this to look for a different bitfield in TYPER which
matches the logical numbering.
---
hypervisor/arch/arm-common/gic-v3.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hypervisor/arch/arm-common/gic-v3.c b/hypervisor/arch/arm-common/gic-v3.c
index 5f9c6e7..af51632 100644
--- a/hypervisor/arch/arm-common/gic-v3.c
+++ b/hypervisor/arch/arm-common/gic-v3.c
@@ -105,7 +105,7 @@ static int gic_cpu_init(struct per_cpu *cpu_data)
break;

typer = mmio_read64(redist_base + GICR_TYPER);
- if ((typer >> 32) == cpu_data->cpu_id) {
+ if (((typer >> 8) & 0xf) == cpu_data->cpu_id) {
cpu_data->gicr_base = redist_base;
break;
}
--
1.9.1

Nikhil Devshatwar

unread,
Jul 20, 2017, 5:28:29 AM7/20/17
to jan.k...@siemens.com, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com, Nikhil Devshatwar
Correct IROUTER base address
Using void pointer for IROUTER register address
Correct pointer arithmatic considering 32bit register per IRQ

Signed-off-by: Nikhil Devshatwar <nikh...@ti.com>
---
hypervisor/arch/arm-common/gic-v3.c | 2 +-
hypervisor/arch/arm-common/include/asm/gic.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hypervisor/arch/arm-common/gic-v3.c b/hypervisor/arch/arm-common/gic-v3.c
index af51632..5a2b9bc 100644
--- a/hypervisor/arch/arm-common/gic-v3.c
+++ b/hypervisor/arch/arm-common/gic-v3.c
@@ -194,7 +194,7 @@ static void gic_cpu_shutdown(struct per_cpu *cpu_data)

static void gic_adjust_irq_target(struct cell *cell, u16 irq_id)
{
- void *irouter = gicd_base + GICD_IROUTER + irq_id;
+ void *irouter = gicd_base + GICD_IROUTER - 32 + irq_id * 4;
u32 route = mmio_read32(irouter);

if (!cell_owns_cpu(cell, route))
diff --git a/hypervisor/arch/arm-common/include/asm/gic.h b/hypervisor/arch/arm-common/include/asm/gic.h
index 35f48dc..2490042 100644
--- a/hypervisor/arch/arm-common/include/asm/gic.h
+++ b/hypervisor/arch/arm-common/include/asm/gic.h
@@ -38,7 +38,7 @@
#define GICD_SGIR 0x0f00
#define GICD_CPENDSGIR 0x0f10
#define GICD_SPENDSGIR 0x0f20
-#define GICD_IROUTER 0x6000
+#define GICD_IROUTER 0x6100

#define GICD_PIDR2_ARCH(pidr) (((pidr) & 0xf0) >> 4)

--
1.9.1

Jan Kiszka

unread,
Jul 20, 2017, 5:59:54 AM7/20/17
to Nikhil Devshatwar, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com
On 2017-07-20 11:19, Nikhil Devshatwar wrote:
> This series is an attempt to get jailhouse working on systems with
> 64bit CPUs and non GIC v3 (non v2 compatible)
>
> With my half knowledge, I have tried to get a few things working.
> I might have fixed one and broke ten others.
> Please scrutinize each change and point out issues.
>
> ONLY tested with aarch64 and GICv3 config

Great, just in time! I've received an Espressobin board these days, just
to have any silicon with GICv3 in hands. Now I have a compelling reason
to bootstrap it ;).

What board were you testing on? Or was it an emulator? We may get QEMU
working this way as well...

Jan

--
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux

Nikhil Devshatwar

unread,
Jul 20, 2017, 7:34:42 AM7/20/17
to Jan Kiszka, Nikhil Devshatwar, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com
On Thursday 20 July 2017 03:29 PM, Jan Kiszka wrote:
> On 2017-07-20 11:19, Nikhil Devshatwar wrote:
>> This series is an attempt to get jailhouse working on systems with
>> 64bit CPUs and non GIC v3 (non v2 compatible)
>>
>> With my half knowledge, I have tried to get a few things working.
>> I might have fixed one and broke ten others.
>> Please scrutinize each change and point out issues.
>>
>> ONLY tested with aarch64 and GICv3 config
> Great, just in time! I've received an Espressobin board these days, just
> to have any silicon with GICv3 in hands. Now I have a compelling reason
> to bootstrap it ;).
>
> What board were you testing on? Or was it an emulator? We may get QEMU
> working this way as well...
>
I don't have any board.
This is all tested on a simulator platform.
btw, I have ordered the same EspressoBin board
We can be on the same page now

Nikhil D

Jan Kiszka

unread,
Jul 22, 2017, 4:55:49 PM7/22/17
to Nikhil Devshatwar, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com
On 2017-07-20 11:19, 'Nikhil Devshatwar' via Jailhouse wrote:
> This series is an attempt to get jailhouse working on systems with
> 64bit CPUs and non GIC v3 (non v2 compatible)
>
> With my half knowledge, I have tried to get a few things working.
> I might have fixed one and broke ten others.
> Please scrutinize each change and point out issues.
>
> ONLY tested with aarch64 and GICv3 config
>

Umm, did this really work in the simulator?

SMP is broken because the access that gicv3_handle_sgir_write handles is
not forwarded out. Consequently, I'm getting unhandled traps on "msr
s3_0_c12_c11_5, x25".

But even when I disable SMP (taking one core offline, configuring only
the remaining one), the ESPRESSObin freezes after enabling. I can't
exclude a board-specific issue yet, need to debug.

I'll push my patches to bootstrap that board tomorrow.

Jan

Devshatwar, Nikhil

unread,
Jul 23, 2017, 3:54:42 AM7/23/17
to Jan Kiszka, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com
> > This series is an attempt to get jailhouse working on systems with
> > 64bit CPUs and non GIC v3 (non v2 compatible)
> >
> > With my half knowledge, I have tried to get a few things working.
> > I might have fixed one and broke ten others.
> > Please scrutinize each change and point out issues.
> >
> > ONLY tested with aarch64 and GICv3 config
> >
>
> Umm, did this really work in the simulator?
>
> SMP is broken because the access that gicv3_handle_sgir_write handles is not
> forwarded out. Consequently, I'm getting unhandled traps on "msr
> s3_0_c12_c11_5, x25".
>
> But even when I disable SMP (taking one core offline, configuring only the
> remaining one), the ESPRESSObin freezes after enabling. I can't exclude a board-
> specific issue yet, need to debug.

Yes, this is exactly the problems I am currently debugging.
With SMP, I am getting unhandled traps for SGI writes issued by kernel
Without SMP, none of the IRQs are getting delivered to kernel, hence kernel is waiting for WFI forever.
Even UART IRQs are not getting forwarded.

I'll try to use the gicv3_handle_sgir_write and see if it helps

>
> I'll push my patches to bootstrap that board tomorrow.
>

Thanks
Nikhil D


Jan Kiszka

unread,
Jul 23, 2017, 5:44:11 AM7/23/17
to Devshatwar, Nikhil, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com
On 2017-07-23 09:54, Devshatwar, Nikhil wrote:
>>> This series is an attempt to get jailhouse working on systems with
>>> 64bit CPUs and non GIC v3 (non v2 compatible)
>>>
>>> With my half knowledge, I have tried to get a few things working.
>>> I might have fixed one and broke ten others.
>>> Please scrutinize each change and point out issues.
>>>
>>> ONLY tested with aarch64 and GICv3 config
>>>
>>
>> Umm, did this really work in the simulator?
>>
>> SMP is broken because the access that gicv3_handle_sgir_write handles is not
>> forwarded out. Consequently, I'm getting unhandled traps on "msr
>> s3_0_c12_c11_5, x25".
>>
>> But even when I disable SMP (taking one core offline, configuring only the
>> remaining one), the ESPRESSObin freezes after enabling. I can't exclude a board-
>> specific issue yet, need to debug.
>
> Yes, this is exactly the problems I am currently debugging.
> With SMP, I am getting unhandled traps for SGI writes issued by kernel
> Without SMP, none of the IRQs are getting delivered to kernel, hence kernel is waiting for WFI forever.
> Even UART IRQs are not getting forwarded.

That's fixed now, but I need to cross-check if 32-bit ARM still builds
at least:

diff --git a/hypervisor/arch/arm-common/include/asm/gic_v3.h
b/hypervisor/arch/arm-common/include/asm/gic_v3.h
index 1fcd5a41..ade80cde 100644
--- a/hypervisor/arch/arm-common/include/asm/gic_v3.h
+++ b/hypervisor/arch/arm-common/include/asm/gic_v3.h
@@ -189,13 +189,12 @@

static inline u64 gic_read_lr(unsigned int n)
{
- u32 lr, lrc;
+ u64 lr;

switch (n) {
#define __READ_LR(n) \
case n: \
arm_read_sysreg(ICH_LR##n, lr); \
- arm_read_sysreg(ICH_LRC##n, lrc); \
break;

__READ_LR(0)
@@ -220,19 +219,15 @@ static inline u64 gic_read_lr(unsigned int n)
return (u64)(-1);
}

- return (u64)lrc << 32 | lr;
+ return lr;
}

static inline void gic_write_lr(unsigned int n, u64 val)
{
- u32 lr = (u32)val;
- u32 lrc = val >> 32;
-
switch (n) {
#define __WRITE_LR(n) \
case n: \
- arm_write_sysreg(ICH_LR##n, lr); \
- arm_write_sysreg(ICH_LRC##n, lrc); \
+ arm_write_sysreg(ICH_LR##n, val); \
break;

__WRITE_LR(0)

>
> I'll try to use the gicv3_handle_sgir_write and see if it helps

That should address the SMP issue. And then we would be able to start a
non-root cell as well.

Preparing my changes for next right now.

Jan

Jan Kiszka

unread,
Jul 23, 2017, 5:57:25 AM7/23/17
to Nikhil Devshatwar, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com
Even if obvious for the writer, a commit log is always welcome. This one
could state that it prepares for reuse on arm64 but will not work yet.

On 2017-07-20 11:19, 'Nikhil Devshatwar' via Jailhouse wrote:
> Signed-off-by: Nikhil Devshatwar <nikh...@ti.com>
> ---
> hypervisor/arch/arm-common/Kbuild | 1 +
> hypervisor/arch/arm-common/gic-v3.c | 456 ++++++++++++++++++++++++
> hypervisor/arch/arm-common/include/asm/gic_v3.h | 269 ++++++++++++++
> hypervisor/arch/arm/Kbuild | 1 -
> hypervisor/arch/arm/gic-v3.c | 456 ------------------------
> hypervisor/arch/arm/include/asm/gic_v3.h | 269 --------------
> 6 files changed, 726 insertions(+), 726 deletions(-)
> create mode 100644 hypervisor/arch/arm-common/gic-v3.c
> create mode 100644 hypervisor/arch/arm-common/include/asm/gic_v3.h
> delete mode 100644 hypervisor/arch/arm/gic-v3.c
> delete mode 100644 hypervisor/arch/arm/include/asm/gic_v3.h
>

...
These two ICH_LR accessors need to stay arch-specific. Please make sure
they are pulled from an arm or arm64 header, respectively.

Jan

Jan Kiszka

unread,
Jul 23, 2017, 5:59:28 AM7/23/17
to Nikhil Devshatwar, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com
Here you could state that all register accesses are valid for both arm
and arm64 - provided you checked that they are.

Jan

On 2017-07-20 11:19, 'Nikhil Devshatwar' via Jailhouse wrote:

Jan Kiszka

unread,
Sep 3, 2017, 12:31:16 PM9/3/17
to Nikhil Devshatwar, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com
On 2017-07-20 11:19, 'Nikhil Devshatwar' via Jailhouse wrote:
This is definitely not correct, even when removing virt_id (which I'm
planning to do, first tests look promising). Guests (at least Linux)
expect to find each region terminated by GICR_TYPER_Last. So the problem
will surface when we first use a SoC with multiple redist regions.

If we no longer virtualize the redist regions so that they are always
consecutive from guest POV, we have to identify and mark the terminating
ones - or declare each region non-consecutive, even if it is. The latter
is simple but will require some more work when created device trees for
non-root cells.

Jan

Ralf Ramsauer

unread,
Sep 3, 2017, 4:57:50 PM9/3/17
to Jan Kiszka, Nikhil Devshatwar, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com
Apropos removing virt_id: I sent a bunch of RFC patches a couple of
weeks ago (PSCI support for arm and arm64 inmates). One patch removed
virt ids and introduced id-mapped CPU ids. I think I was just missing
GICv3 support, as I'm lacking hardware.

Ralf

Jan Kiszka

unread,
Sep 3, 2017, 5:21:53 PM9/3/17
to Ralf Ramsauer, Nikhil Devshatwar, jailho...@googlegroups.com
Thanks, for reminding - "couple of weeks" was actually May, and I'm
finally at the point to look into them seriously.

The patch in question goes in the right direction, but there is more
work needed, even beyond GICv3. Also, the patch series does a lot of
things in one. I'll follow up on it.

Jan

Jan Kiszka

unread,
Sep 5, 2017, 2:22:42 AM9/5/17
to Nikhil Devshatwar, jan.k...@siemens.com, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com
On 2017-07-20 11:19, 'Nikhil Devshatwar' via Jailhouse wrote:
> Getting compiler issues when using GIC V3 in 64bit mode
> Update the sysreg macros to solve these compiler issues
>
> Signed-off-by: Nikhil Devshatwar <nikh...@ti.com>
> ---
> hypervisor/arch/arm-common/include/asm/gic_v3.h | 2 +-
> hypervisor/arch/arm64/include/asm/sysregs.h | 12 +++++++++---
> 2 files changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/hypervisor/arch/arm-common/include/asm/gic_v3.h b/hypervisor/arch/arm-common/include/asm/gic_v3.h
> index d1b9346..1fcd5a4 100644
> --- a/hypervisor/arch/arm-common/include/asm/gic_v3.h
> +++ b/hypervisor/arch/arm-common/include/asm/gic_v3.h
> @@ -70,7 +70,7 @@
> #define ICC_SRE_EL1 SYSREG_32(0, c12, c12, 5)
> #define ICC_SRE_EL2 SYSREG_32(4, c12, c9, 5)
> #define ICC_IGRPEN1_EL1 SYSREG_32(0, c12, c12, 7)
> -#define ICC_SGI1R_EL1 SYSREG_64(0, c12)
> +#define ICC_SGI1R_EL1 SYSREG_64(0, c12, c11, 5)

This one is differently defined for ARM vs. ARM64. You need to account
for that.

Jan

> #define ICC_AP1R0_EL1 SYSREG_32(0, c12, c9, 0)
> #define ICC_AP1R1_EL1 SYSREG_32(0, c12, c9, 1)
> #define ICC_AP1R2_EL1 SYSREG_32(0, c12, c9, 2)
> diff --git a/hypervisor/arch/arm64/include/asm/sysregs.h b/hypervisor/arch/arm64/include/asm/sysregs.h
> index d0f8fa3..565012b 100644
> --- a/hypervisor/arch/arm64/include/asm/sysregs.h
> +++ b/hypervisor/arch/arm64/include/asm/sysregs.h
> @@ -146,11 +146,17 @@
>
> #ifndef __ASSEMBLY__
>
> -#define arm_write_sysreg(sysreg, val) \
> +#define SYSREG_32(a, b, c, d) s3_##a ##_##b ##_##c ##_##d
> +#define SYSREG_64(a, b, c, d) s3_##a ##_##b ##_##c ##_##d
> +
> +
> +#define arm_write_sysreg1(sysreg, val) \
> asm volatile ("msr "#sysreg", %0\n" : : "r"((u64)(val)))
> +#define arm_write_sysreg(a , b) arm_write_sysreg1( a, b)
>
> -#define arm_read_sysreg(sysreg, val) \
> - asm volatile ("mrs %0, "#sysreg"\n" : "=r"((u64)(val)))
> +#define arm_read_sysreg1(sysreg, val) \
> + asm volatile ("mrs %0, "#sysreg"\n" : "=r"((val)))
> +#define arm_read_sysreg(a , b) arm_read_sysreg1( a, b)
>
> #endif /* __ASSEMBLY__ */
>
>

--

Ralf Ramsauer

unread,
Sep 15, 2017, 6:31:08 PM9/15/17
to Jan Kiszka, Nikhil Devshatwar, ralf.r...@oth-regensburg.de, jailho...@googlegroups.com
Hi,

just realised that this patch breaks my inmate-decouple series after
rebasing it to next.

Reason for that is that gic-v3 is now available for ARM64, and my
decouple series misses SYSREG_32 definition for that architecture, as I
only provided a minimum set of definitions. In addition to that, I also
need strings.h, as sysregs.h now uses __stringify. Maybe I can get
around that somehow...

As Tony didn't give his signed-off yet, I'll provide a new patch for that.

Ralf
Reply all
Reply to author
Forward
0 new messages