From bdcdd89e2e4f4aa439935539bb62e0c9fbaf824d Mon Sep 17 00:00:00 2001 From: Antonios Motakis Date: Tue, 14 Jun 2016 14:16:44 +0200 Subject: [PATCH] arm: move the handle_irq_route function to the GICv3 module The handle_irq_route function is not needed with the GICv2. On the ARMv8 port we will not assign a virt_id to each CPU, opting to use the MPIDR as much as we can from the start. GICv3 will need heavier refactoring for this purpose; by moving this function we can reuse the GICv2 code on ARMv8. Signed-off-by: Antonios Motakis [Jan: implement stub in v2 to reduce #ifdefs] Signed-off-by: Jan Kiszka --- hypervisor/arch/arm/gic-common.c | 42 +------------------- hypervisor/arch/arm/gic-v2.c | 7 ++++ hypervisor/arch/arm/gic-v3.c | 40 +++++++++++++++++++ hypervisor/arch/arm/include/asm/gic_common.h | 2 + 4 files changed, 50 insertions(+), 41 deletions(-) diff --git a/hypervisor/arch/arm/gic-common.c b/hypervisor/arch/arm/gic-common.c index 51f6bee..45805c1 100644 --- a/hypervisor/arch/arm/gic-common.c +++ b/hypervisor/arch/arm/gic-common.c @@ -100,46 +100,6 @@ restrict_bitmask_access(struct mmio_access *mmio, unsigned int reg_index, return MMIO_HANDLED; } -/* - * GICv3 uses a 64bit register IROUTER for each IRQ - */ -static enum mmio_result 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 (!spi_in_cell(cell, irq - 32)) - 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; -} - /* * GICv2 uses 8bit values for each IRQ in the ITARGETRs registers */ @@ -304,7 +264,7 @@ enum mmio_result gic_handle_dist_access(void *arg, struct mmio_access *mmio) switch (reg) { case REG_RANGE(GICD_IROUTER, 1024, 8): - ret = handle_irq_route(mmio, (reg - GICD_IROUTER) / 8); + ret = gic_handle_irq_route(mmio, (reg - GICD_IROUTER) / 8); break; case REG_RANGE(GICD_ITARGETSR, 1024, 1): diff --git a/hypervisor/arch/arm/gic-v2.c b/hypervisor/arch/arm/gic-v2.c index ff0036b..c53e58a 100644 --- a/hypervisor/arch/arm/gic-v2.c +++ b/hypervisor/arch/arm/gic-v2.c @@ -288,6 +288,13 @@ static void gic_enable_maint_irq(bool enable) mmio_write32(gich_base + GICH_HCR, hcr); } +enum mmio_result gic_handle_irq_route(struct mmio_access *mmio, + unsigned int irq) +{ + /* doesn't exist in v2 - ignore access */ + return MMIO_HANDLED; +} + unsigned int irqchip_mmio_count_regions(struct cell *cell) { return 1; diff --git a/hypervisor/arch/arm/gic-v3.c b/hypervisor/arch/arm/gic-v3.c index b422200..e7d5e66 100644 --- a/hypervisor/arch/arm/gic-v3.c +++ b/hypervisor/arch/arm/gic-v3.c @@ -338,6 +338,46 @@ void gicv3_handle_sgir_write(u64 sgir) 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 (!spi_in_cell(cell, irq - 32)) + 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); diff --git a/hypervisor/arch/arm/include/asm/gic_common.h b/hypervisor/arch/arm/include/asm/gic_common.h index 0381194..4c58933 100644 --- a/hypervisor/arch/arm/include/asm/gic_common.h +++ b/hypervisor/arch/arm/include/asm/gic_common.h @@ -50,6 +50,8 @@ struct sgi; int gic_probe_cpu_id(unsigned int cpu); enum mmio_result gic_handle_dist_access(void *arg, struct mmio_access *mmio); +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_irq(struct per_cpu *cpu_data); void gic_target_spis(struct cell *config_cell, struct cell *dest_cell); -- 2.39.2