From: Antonios Motakis <[email protected]> We plug the irqchip handling code, and the GICv2 implementation from AArch32.
GICv3 is slightly trickier; it makes heavier use of the sysregs, so we will need to review more carefully that the sysregs macros do the right thing. Signed-off-by: Antonios Motakis <[email protected]> --- hypervisor/arch/arm64/Makefile | 2 ++ hypervisor/arch/arm64/control.c | 57 ++++++++++++++++++++++++++++++ hypervisor/arch/arm64/include/asm/cell.h | 2 ++ hypervisor/arch/arm64/include/asm/percpu.h | 27 ++++++++++++++ hypervisor/arch/arm64/mmio.c | 4 +-- hypervisor/arch/arm64/setup.c | 24 +++++++++++-- hypervisor/arch/arm64/traps.c | 5 +++ 7 files changed, 117 insertions(+), 4 deletions(-) diff --git a/hypervisor/arch/arm64/Makefile b/hypervisor/arch/arm64/Makefile index 603056e..540f7e3 100644 --- a/hypervisor/arch/arm64/Makefile +++ b/hypervisor/arch/arm64/Makefile @@ -19,5 +19,7 @@ always := built-in.o obj-y := entry.o setup.o control.o mmio.o caches.o obj-y += ../arm/mmu_cell.o ../arm/paging.o ../arm/dbg-write.o ../arm/lib.o obj-y += exception.o traps.o +obj-y += ../arm/irqchip.o ../arm/gic-common.o obj-$(CONFIG_SERIAL_AMBA_PL011) += ../arm/dbg-write-pl011.o +obj-$(CONFIG_ARM_GIC) += ../arm/gic-v2.o diff --git a/hypervisor/arch/arm64/control.c b/hypervisor/arch/arm64/control.c index a1c4774..f141e45 100644 --- a/hypervisor/arch/arm64/control.c +++ b/hypervisor/arch/arm64/control.c @@ -12,6 +12,10 @@ #include <jailhouse/control.h> #include <jailhouse/printk.h> +#include <asm/control.h> +#include <asm/irqchip.h> +#include <asm/platform.h> +#include <asm/traps.h> int arch_cell_create(struct cell *cell) { @@ -81,3 +85,56 @@ void arch_panic_park(void) trace_error(-EINVAL); while (1); } + +void arch_handle_sgi(struct per_cpu *cpu_data, u32 irqn) +{ + cpu_data->stats[JAILHOUSE_CPU_STAT_VMEXITS_MANAGEMENT]++; + + switch (irqn) { + case SGI_INJECT: + irqchip_inject_pending(cpu_data); + break; + default: + printk("WARN: unknown SGI received %d\n", irqn); + } +} + +/* + * Handle the maintenance interrupt, the rest is injected into the cell. + * Return true when the IRQ has been handled by the hyp. + */ +bool arch_handle_phys_irq(struct per_cpu *cpu_data, u32 irqn) +{ + if (irqn == MAINTENANCE_IRQ) { + cpu_data->stats[JAILHOUSE_CPU_STAT_VMEXITS_MAINTENANCE]++; + + irqchip_inject_pending(cpu_data); + return true; + } + + cpu_data->stats[JAILHOUSE_CPU_STAT_VMEXITS_VIRQ]++; + + irqchip_set_pending(cpu_data, irqn); + + return false; +} + +/* + * We get rid of the virt_id in the AArch64 implementation, since it + * doesn't really fit with the MPIDR CPU identification scheme on ARM. + * + * Until the GICv3 and ARMv7 code has been properly refactored to + * support this scheme, we stub this call so we can share the GICv2 + * code with ARMv7. + * + * TODO: implement MPIDR support in the GICv3 code, so it can be + * used on AArch64. + * TODO: refactor out virt_id from the AArch7 port as well. + */ +unsigned int arm_cpu_phys2virt(unsigned int cpu_id) +{ + panic_printk("FATAL: we shouldn't reach here\n"); + panic_stop(); + + return -EINVAL; +} diff --git a/hypervisor/arch/arm64/include/asm/cell.h b/hypervisor/arch/arm64/include/asm/cell.h index 4ba8224..9a9689e 100644 --- a/hypervisor/arch/arm64/include/asm/cell.h +++ b/hypervisor/arch/arm64/include/asm/cell.h @@ -26,6 +26,8 @@ struct arch_cell { struct paging_structures mm; spinlock_t caches_lock; bool needs_flush; + + u64 spis; }; extern struct cell root_cell; diff --git a/hypervisor/arch/arm64/include/asm/percpu.h b/hypervisor/arch/arm64/include/asm/percpu.h index 9d1b6ec..e9fa99b 100644 --- a/hypervisor/arch/arm64/include/asm/percpu.h +++ b/hypervisor/arch/arm64/include/asm/percpu.h @@ -23,9 +23,13 @@ #ifndef __ASSEMBLY__ +#include <jailhouse/printk.h> #include <asm/cell.h> +#include <asm/irqchip.h> #include <asm/spinlock.h> +struct pending_irq; + struct per_cpu { u8 stack[PAGE_SIZE]; unsigned long saved_vectors; @@ -37,6 +41,15 @@ struct per_cpu { int shutdown_state; bool failed; + /* synchronizes parallel insertions of SGIs into the pending ring */ + spinlock_t pending_irqs_lock; + u16 pending_irqs[MAX_PENDING_IRQS]; + unsigned int pending_irqs_head; + /* removal from the ring happens lockless, thus tail is volatile */ + volatile unsigned int pending_irqs_tail; + /* Only GICv3: redistributor base */ + void *gicr_base; + bool flush_vcpu_caches; unsigned long mpidr; } __attribute__((aligned(PAGE_SIZE))); @@ -72,6 +85,20 @@ static inline struct registers *guest_regs(struct per_cpu *cpu_data) - sizeof(struct registers)); } +/* + * We get rid of the virt_id in the AArch64 implementation, since it + * doesn't really fit with the MPIDR CPU identification scheme on ARM. + * + * Until the GICv3 and ARMv7 code has been properly refactored to + * support this scheme, we stub this call so we can share the GICv2 + * code with ARMv7. + * + * TODO: implement MPIDR support in the GICv3 code, so it can be + * used on AArch64. + * TODO: refactor out virt_id from the AArch7 port as well. + */ +unsigned int arm_cpu_phys2virt(unsigned int cpu_id); + /* Validate defines */ #define CHECK_ASSUMPTION(assume) ((void)sizeof(char[1 - 2*!(assume)])) diff --git a/hypervisor/arch/arm64/mmio.c b/hypervisor/arch/arm64/mmio.c index 0c43365..8888251 100644 --- a/hypervisor/arch/arm64/mmio.c +++ b/hypervisor/arch/arm64/mmio.c @@ -18,6 +18,7 @@ #include <jailhouse/mmio.h> #include <jailhouse/printk.h> #include <asm/bitops.h> +#include <asm/irqchip.h> #include <asm/percpu.h> #include <asm/sysregs.h> #include <asm/traps.h> @@ -26,8 +27,7 @@ unsigned int arch_mmio_count_regions(struct cell *cell) { - /* not entirely a lie :) */ - return 0; + return irqchip_mmio_count_regions(cell); } static void arch_inject_dabt(struct trap_context *ctx, unsigned long addr) diff --git a/hypervisor/arch/arm64/setup.c b/hypervisor/arch/arm64/setup.c index 13e6387..838c541 100644 --- a/hypervisor/arch/arm64/setup.c +++ b/hypervisor/arch/arm64/setup.c @@ -13,23 +13,43 @@ #include <jailhouse/entry.h> #include <jailhouse/printk.h> #include <asm/control.h> +#include <asm/irqchip.h> #include <asm/setup.h> int arch_init_early(void) { - return arch_mmu_cell_init(&root_cell); + int err = 0; + + err = arch_mmu_cell_init(&root_cell); + if (err) + return err; + + return irqchip_init(); } int arch_cpu_init(struct per_cpu *cpu_data) { + int err = 0; + /* switch to the permanent page tables */ enable_mmu_el2(hv_paging_structs.root_table); - return arch_mmu_cpu_cell_init(cpu_data); + err = arch_mmu_cpu_cell_init(cpu_data); + if (err) + return err; + + return irqchip_cpu_init(cpu_data); } int arch_init_late(void) { + int err; + + /* Setup the SPI bitmap */ + err = irqchip_cell_init(&root_cell); + if (err) + return err; + return map_root_memory_regions(); } diff --git a/hypervisor/arch/arm64/traps.c b/hypervisor/arch/arm64/traps.c index cc6fe6c..fec057d 100644 --- a/hypervisor/arch/arm64/traps.c +++ b/hypervisor/arch/arm64/traps.c @@ -21,6 +21,7 @@ #include <asm/sysregs.h> #include <asm/traps.h> #include <asm/processor.h> +#include <asm/irqchip.h> void arch_skip_instruction(struct trap_context *ctx) { @@ -143,6 +144,10 @@ struct registers *arch_handle_exit(struct per_cpu *cpu_data, cpu_data->stats[JAILHOUSE_CPU_STAT_VMEXITS_TOTAL]++; switch (regs->exit_reason) { + case EXIT_REASON_EL1_IRQ: + irqchip_handle_irq(cpu_data); + break; + case EXIT_REASON_EL1_ABORT: arch_handle_trap(cpu_data, regs); break; -- 2.8.0.rc3 -- 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.
