From: Jan Kiszka <[email protected]>

Do not modify the MPIDR value that the cells see. VMPIDR is initialized
to the physical MPIDR on reset, and we can safely keep this, even while
the GICv2 IDs are still virtualized because they are unrelated.

We just need to adjust the GICv3 case because there we are in affinity
routing mode, and the MPIDR does play a role when dispatching SGIs.
GICR_TYPER can now be kept almost unmodified. Moreover, the
redistributors needs to be identity-mapped into the guests.

This also aligns arm with arm64 and will help introducing GICv3 to the
latter.

Signed-off-by: Jan Kiszka <[email protected]>
---
 configs/dts/inmate-bananapi.dts              |  4 +-
 configs/dts/inmate-jetson-tk1.dts            |  8 ++--
 configs/dts/inmate-orangepi0.dts             |  6 +--
 hypervisor/arch/arm-common/include/asm/gic.h |  2 +-
 hypervisor/arch/arm-common/irqchip.c         |  6 +--
 hypervisor/arch/arm/control.c                |  2 -
 hypervisor/arch/arm/gic-v3.c                 | 65 ++++++++++++----------------
 hypervisor/arch/arm/include/asm/sysregs.h    |  1 -
 hypervisor/arch/arm64/include/asm/sysregs.h  |  3 +-
 9 files changed, 41 insertions(+), 56 deletions(-)

diff --git a/configs/dts/inmate-bananapi.dts b/configs/dts/inmate-bananapi.dts
index 036650fd..e81ae350 100644
--- a/configs/dts/inmate-bananapi.dts
+++ b/configs/dts/inmate-bananapi.dts
@@ -29,10 +29,10 @@
                #address-cells = <1>;
                #size-cells = <0>;
 
-               cpu@0 {
+               cpu@1 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
-                       reg = <0>;
+                       reg = <1>;
                };
        };
 
diff --git a/configs/dts/inmate-jetson-tk1.dts 
b/configs/dts/inmate-jetson-tk1.dts
index c828b3e2..df60046d 100644
--- a/configs/dts/inmate-jetson-tk1.dts
+++ b/configs/dts/inmate-jetson-tk1.dts
@@ -29,17 +29,15 @@
                #address-cells = <1>;
                #size-cells = <0>;
 
-               cpu@0 {
+               cpu@2 {
                        compatible = "arm,cortex-a15";
                        device_type = "cpu";
-                       /* Linux expects a CPU 0 to be present */
-                       reg = <0x0>;
+                       reg = <0x2>;
                };
 
-               cpu@1 {
+               cpu@3 {
                        compatible = "arm,cortex-a15";
                        device_type = "cpu";
-                       /* this has to reflect the real ID */
                        reg = <0x3>;
                };
        };
diff --git a/configs/dts/inmate-orangepi0.dts b/configs/dts/inmate-orangepi0.dts
index effbabe1..54ea4827 100644
--- a/configs/dts/inmate-orangepi0.dts
+++ b/configs/dts/inmate-orangepi0.dts
@@ -29,13 +29,13 @@
                #address-cells = <1>;
                #size-cells = <0>;
 
-               cpu@0 {
+               cpu@2 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
-                       reg = <0>;
+                       reg = <2>;
                };
 
-               cpu@1 {
+               cpu@3 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <3>;
diff --git a/hypervisor/arch/arm-common/include/asm/gic.h 
b/hypervisor/arch/arm-common/include/asm/gic.h
index 35f48dcc..d6d02390 100644
--- a/hypervisor/arch/arm-common/include/asm/gic.h
+++ b/hypervisor/arch/arm-common/include/asm/gic.h
@@ -56,6 +56,6 @@ extern spinlock_t dist_lock;
 
 enum mmio_result gic_handle_irq_route(struct mmio_access *mmio,
                                      unsigned int irq);
-void gic_handle_sgir_write(struct sgi *sgi, bool virt_input);
+void gic_handle_sgir_write(struct sgi *sgi, bool affinity_routing);
 #endif /* !__ASSEMBLY__ */
 #endif /* !_JAILHOUSE_ASM_GIC_COMMON_H */
diff --git a/hypervisor/arch/arm-common/irqchip.c 
b/hypervisor/arch/arm-common/irqchip.c
index 6ce56b21..3c86a10a 100644
--- a/hypervisor/arch/arm-common/irqchip.c
+++ b/hypervisor/arch/arm-common/irqchip.c
@@ -127,7 +127,7 @@ static enum mmio_result handle_sgir_access(struct 
mmio_access *mmio)
        return MMIO_HANDLED;
 }
 
-void gic_handle_sgir_write(struct sgi *sgi, bool virt_input)
+void gic_handle_sgir_write(struct sgi *sgi, bool affinity_routing)
 {
        struct per_cpu *cpu_data = this_cpu_data();
        unsigned long targets = sgi->targets;
@@ -144,8 +144,8 @@ void gic_handle_sgir_write(struct sgi *sgi, bool virt_input)
                                /* Route to all (cell) CPUs but the caller. */
                                if (cpu == cpu_data->cpu_id)
                                        continue;
-                       } else if (virt_input) {
-                               if (!test_bit(arm_cpu_phys2virt(cpu),
+                       } else if (affinity_routing) {
+                               if (!test_bit(cpu_data->mpidr & MPIDR_AFF0_MASK,
                                              &targets))
                                        continue;
                        } else {
diff --git a/hypervisor/arch/arm/control.c b/hypervisor/arch/arm/control.c
index b930bc83..1dfd6169 100644
--- a/hypervisor/arch/arm/control.c
+++ b/hypervisor/arch/arm/control.c
@@ -94,8 +94,6 @@ void arm_cpu_reset(unsigned long pc)
        /* transfer the context that may have been passed to PSCI_CPU_ON */
        regs->usr[1] = cpu_data->cpu_on_context;
 
-       arm_write_sysreg(VMPIDR_EL2, cpu_data->virt_id | MPIDR_MP_BIT);
-
        arm_paging_vcpu_init(&cell->arch.mm);
 
        irqchip_cpu_reset(cpu_data);
diff --git a/hypervisor/arch/arm/gic-v3.c b/hypervisor/arch/arm/gic-v3.c
index d529128c..8d7c9aad 100644
--- a/hypervisor/arch/arm/gic-v3.c
+++ b/hypervisor/arch/arm/gic-v3.c
@@ -216,43 +216,27 @@ static enum mmio_result gic_handle_redist_access(void 
*arg,
 {
        struct per_cpu *cpu_data = arg;
 
-       /* Change the ID register, all other accesses are allowed. */
-       if (!mmio->is_write) {
-               switch (mmio->address) {
-               case GICR_TYPER:
-                       /*
-                        * Declare each redistributor region to be last. This
-                        * avoids that we miss one and cause the guest to
-                        * overscan while matching redistributors in a
-                        * partitioned region.
-                        */
-                       mmio->value = GICR_TYPER_Last;
-
-                       /* AArch64 can use a writeq for this register */
-                       if (mmio->size == 8)
-                               mmio->value |= (u64)cpu_data->virt_id << 32;
-
-                       return MMIO_HANDLED;
-               case GICR_TYPER + 4:
-                       /* Upper bits contain the affinity */
-                       mmio->value = cpu_data->virt_id;
-                       return MMIO_HANDLED;
-               }
-       }
        mmio_perform_access(cpu_data->gicr.base, mmio);
+
+       /*
+        * Declare each redistributor region to be last. This avoids that we
+        * miss one and cause the guest to overscan while matching
+        * redistributors in a partitioned region.
+        */
+       if (mmio->address == GICR_TYPER && !mmio->is_write)
+               mmio->value |= GICR_TYPER_Last;
+
        return MMIO_HANDLED;
 }
 
 static int gic_cell_init(struct cell *cell)
 {
-       unsigned long redist_base = system_config->platform_info.arm.gicr_base;
-       unsigned long redist_size = gic_version == 4 ? 0x40000 : 0x20000;
        unsigned int cpu;
 
        for_each_cpu(cpu, cell->cpu_set)
-               mmio_region_register(cell,
-                       redist_base + per_cpu(cpu)->virt_id * redist_size,
-                       redist_size, gic_handle_redist_access, per_cpu(cpu));
+               mmio_region_register(cell, per_cpu(cpu)->gicr.phys_addr,
+                                    gic_version == 4 ? 0x40000 : 0x20000,
+                                    gic_handle_redist_access, per_cpu(cpu));
 
        return 0;
 }
@@ -330,19 +314,24 @@ enum mmio_result gic_handle_irq_route(struct mmio_access 
*mmio,
        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);
+               /*
+                * Validate that the target CPU is part of the cell.
+                * Note that we do not support Interrupt Routing Mode = 1.
+                */
+               for_each_cpu(cpu, cell->cpu_set)
+                       if ((per_cpu(cpu)->mpidr & MPIDR_CPUID_MASK) ==
+                           mmio->value) {
+                               mmio_perform_access(gicd_base, mmio);
+                               return MMIO_HANDLED;
+                       }
+
+               printk("Attempt to route IRQ%d outside of cell\n", irq);
+               return MMIO_ERROR;
        } else {
-               cpu = mmio_read32(gicd_base + GICD_IROUTER + 8 * irq);
-               mmio->value = arm_cpu_phys2virt(cpu);
+               mmio->value = mmio_read32(gicd_base + GICD_IROUTER + 8 * irq);
+               return MMIO_HANDLED;
        }
-       return MMIO_HANDLED;
 }
 
 static void gic_eoi_irq(u32 irq_id, bool deactivate)
diff --git a/hypervisor/arch/arm/include/asm/sysregs.h 
b/hypervisor/arch/arm/include/asm/sysregs.h
index a6266586..d6e2bb79 100644
--- a/hypervisor/arch/arm/include/asm/sysregs.h
+++ b/hypervisor/arch/arm/include/asm/sysregs.h
@@ -95,7 +95,6 @@
 #define CSSIDR_EL1     SYSREG_32(1, c0, c0, 0)
 #define CLIDR_EL1      SYSREG_32(1, c0, c0, 1)
 #define CSSELR_EL1     SYSREG_32(2, c0, c0, 0)
-#define VMPIDR_EL2     SYSREG_32(4, c0, c0, 5)
 #define SCTLR_EL2      SYSREG_32(4, c1, c0, 0)
 #define ESR_EL2                SYSREG_32(4, c5, c2, 0)
 #define HSR            ESR_EL2 /* AArch32 name */
diff --git a/hypervisor/arch/arm64/include/asm/sysregs.h 
b/hypervisor/arch/arm64/include/asm/sysregs.h
index d0f8fa37..923055f0 100644
--- a/hypervisor/arch/arm64/include/asm/sysregs.h
+++ b/hypervisor/arch/arm64/include/asm/sysregs.h
@@ -30,8 +30,9 @@
                        | PSR_MODE_EL1h)
 
 #define MPIDR_CPUID_MASK       0xff00ffffff
-#define MPIDR_MP_BIT           (1 << 31)
+#define MPIDR_AFF0_MASK                0x00000000ff
 #define MPIDR_U_BIT            (1 << 30)
+#define MPIDR_MP_BIT           (1 << 31)
 
 #define SCTLR_M_BIT    (1 << 0)
 #define SCTLR_A_BIT    (1 << 1)
-- 
2.12.3

-- 
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