This reuses the control.c module, shared with 32-bit ARM. There is more commodity in headers, setup.c etc. to be consolidated later on.
Signed-off-by: Jan Kiszka <jan.kis...@siemens.com> --- hypervisor/arch/arm64/Makefile | 1 + hypervisor/arch/arm64/control.c | 129 +++++++++++++--------------- hypervisor/arch/arm64/include/asm/control.h | 6 ++ hypervisor/arch/arm64/include/asm/percpu.h | 29 ++++++- hypervisor/arch/arm64/setup.c | 24 ++++++ 5 files changed, 119 insertions(+), 70 deletions(-) diff --git a/hypervisor/arch/arm64/Makefile b/hypervisor/arch/arm64/Makefile index e6c8e30..095212a 100644 --- a/hypervisor/arch/arm64/Makefile +++ b/hypervisor/arch/arm64/Makefile @@ -21,6 +21,7 @@ always := built-in.o obj-y := entry.o setup.o control.o mmio.o caches.o obj-y += exception.o traps.o obj-y += $(COMMON)/dbg-write.o $(COMMON)/lib.o +obj-y += $(COMMON)/control.o obj-y += $(COMMON)/mmu_cell.o $(COMMON)/paging.o obj-y += $(COMMON)/irqchip.o $(COMMON)/gic-common.o diff --git a/hypervisor/arch/arm64/control.c b/hypervisor/arch/arm64/control.c index fc0a8f3..289e382 100644 --- a/hypervisor/arch/arm64/control.c +++ b/hypervisor/arch/arm64/control.c @@ -12,19 +12,74 @@ #include <jailhouse/control.h> #include <jailhouse/printk.h> +#include <jailhouse/string.h> #include <asm/control.h> #include <asm/irqchip.h> #include <asm/traps.h> -int arch_cell_create(struct cell *cell) +void arm_cpu_reset(unsigned long pc) { - return trace_error(-EINVAL); + struct per_cpu *cpu_data = this_cpu_data(); + struct registers *regs = guest_regs(cpu_data); + + /* put the cpu in a reset state */ + /* AARCH64_TODO: handle big endian support */ + arm_write_sysreg(SPSR_EL2, RESET_PSR); + arm_write_sysreg(SCTLR_EL1, SCTLR_EL1_RES1); + arm_write_sysreg(CNTKCTL_EL1, 0); + arm_write_sysreg(PMCR_EL0, 0); + + /* wipe any other state to avoid leaking information accross cells */ + memset(regs, 0, sizeof(struct registers)); + + /* AARCH64_TODO: wipe floating point registers */ + + /* wipe special registers */ + arm_write_sysreg(SP_EL0, 0); + arm_write_sysreg(SP_EL1, 0); + arm_write_sysreg(SPSR_EL1, 0); + + /* wipe the system registers */ + arm_write_sysreg(AFSR0_EL1, 0); + arm_write_sysreg(AFSR1_EL1, 0); + arm_write_sysreg(AMAIR_EL1, 0); + arm_write_sysreg(CONTEXTIDR_EL1, 0); + arm_write_sysreg(CPACR_EL1, 0); + arm_write_sysreg(CSSELR_EL1, 0); + arm_write_sysreg(ESR_EL1, 0); + arm_write_sysreg(FAR_EL1, 0); + arm_write_sysreg(MAIR_EL1, 0); + arm_write_sysreg(PAR_EL1, 0); + arm_write_sysreg(TCR_EL1, 0); + arm_write_sysreg(TPIDRRO_EL0, 0); + arm_write_sysreg(TPIDR_EL0, 0); + arm_write_sysreg(TPIDR_EL1, 0); + arm_write_sysreg(TTBR0_EL1, 0); + arm_write_sysreg(TTBR1_EL1, 0); + arm_write_sysreg(VBAR_EL1, 0); + + /* wipe timer registers */ + arm_write_sysreg(CNTP_CTL_EL0, 0); + arm_write_sysreg(CNTP_CVAL_EL0, 0); + arm_write_sysreg(CNTP_TVAL_EL0, 0); + arm_write_sysreg(CNTV_CTL_EL0, 0); + arm_write_sysreg(CNTV_CVAL_EL0, 0); + arm_write_sysreg(CNTV_TVAL_EL0, 0); + + /* AARCH64_TODO: handle PMU registers */ + /* AARCH64_TODO: handle debug registers */ + /* AARCH64_TODO: handle system registers for AArch32 state */ + + arm_write_sysreg(ELR_EL2, pc); + + arm_paging_vcpu_init(&cpu_data->cell->arch.mm); + + irqchip_cpu_reset(cpu_data); } -void arch_flush_cell_vcpu_caches(struct cell *cell) +int arch_cell_create(struct cell *cell) { - /* AARCH64_TODO */ - trace_error(-EINVAL); + return trace_error(-EINVAL); } void arch_cell_destroy(struct cell *cell) @@ -33,70 +88,6 @@ void arch_cell_destroy(struct cell *cell) while (1); } -void arch_cell_reset(struct cell *cell) -{ -} - -void arch_config_commit(struct cell *cell_added_removed) -{ -} - -void arch_shutdown(void) -{ - trace_error(-EINVAL); - while (1); -} - -void arch_suspend_cpu(unsigned int cpu_id) -{ - trace_error(-EINVAL); - while (1); -} - -void arch_resume_cpu(unsigned int cpu_id) -{ - trace_error(-EINVAL); - while (1); -} - -void arch_reset_cpu(unsigned int cpu_id) -{ - trace_error(-EINVAL); - while (1); -} - -void arch_park_cpu(unsigned int cpu_id) -{ - trace_error(-EINVAL); - while (1); -} - -void __attribute__((noreturn)) arch_panic_stop(void) -{ - trace_error(-EINVAL); - while (1); -} - -void arch_panic_park(void) -{ - trace_error(-EINVAL); - while (1); -} - -void arch_handle_sgi(struct per_cpu *cpu_data, u32 irqn, - unsigned int count_event) -{ - trace_error(-EINVAL); - while (1); -} - -bool arch_handle_phys_irq(struct per_cpu *cpu_data, u32 irqn, - unsigned int count_event) -{ - trace_error(-EINVAL); - while (1); -} - /* * 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. diff --git a/hypervisor/arch/arm64/include/asm/control.h b/hypervisor/arch/arm64/include/asm/control.h index 93fdbbe..d7cd82c 100644 --- a/hypervisor/arch/arm64/include/asm/control.h +++ b/hypervisor/arch/arm64/include/asm/control.h @@ -18,6 +18,8 @@ #include <asm/percpu.h> +extern struct paging_structures parking_mm; + void arch_cpu_tlb_flush(struct per_cpu *cpu_data); void arch_cell_caches_flush(struct cell *cell); void arch_handle_sgi(struct per_cpu *cpu_data, u32 irqn, @@ -33,4 +35,8 @@ unsigned int arm_cpu_by_mpidr(struct cell *cell, unsigned long mpidr); void __attribute__((noreturn)) vmreturn(struct registers *guest_regs); void __attribute__((noreturn)) arch_shutdown_mmu(struct per_cpu *cpu_data); +void arm_cpu_reset(unsigned long pc); +void arm_cpu_park(void); +void arm_cpu_kick(unsigned int cpu_id); + #endif /* !_JAILHOUSE_ASM_CONTROL_H */ diff --git a/hypervisor/arch/arm64/include/asm/percpu.h b/hypervisor/arch/arm64/include/asm/percpu.h index 4b645d6..507d86d 100644 --- a/hypervisor/arch/arm64/include/asm/percpu.h +++ b/hypervisor/arch/arm64/include/asm/percpu.h @@ -45,8 +45,35 @@ struct per_cpu { /* Only GICv3: redistributor base */ void *gicr_base; - bool flush_vcpu_caches; unsigned long mpidr; + + /** + * Lock protecting CPU state changes done for control tasks. + * + * The lock protects the following fields (unless CPU is suspended): + * @li per_cpu::suspend_cpu + * @li per_cpu::cpu_suspended (except for spinning on it to become + * true) + * @li per_cpu::flush_vcpu_caches + */ + spinlock_t control_lock; + + /** Set to true for instructing the CPU to suspend. */ + volatile bool suspend_cpu; + /** True if CPU is waiting for power-on. */ + volatile bool wait_for_poweron; + /** True if CPU is suspended. */ + volatile bool cpu_suspended; + /** Set to true for pending reset. */ + bool reset; + /** Set to true for pending park. */ + bool park; + /** Set to true for a pending TLB flush for the paging layer that does + * host physical <-> guest physical memory mappings. */ + bool flush_vcpu_caches; + + unsigned long cpu_on_entry; + unsigned long cpu_on_context; } __attribute__((aligned(PAGE_SIZE))); static inline struct per_cpu *this_cpu_data(void) diff --git a/hypervisor/arch/arm64/setup.c b/hypervisor/arch/arm64/setup.c index 8f1fc69..78a245b 100644 --- a/hypervisor/arch/arm64/setup.c +++ b/hypervisor/arch/arm64/setup.c @@ -12,13 +12,37 @@ #include <jailhouse/cell.h> #include <jailhouse/entry.h> +#include <jailhouse/paging.h> #include <jailhouse/printk.h> #include <asm/control.h> #include <asm/irqchip.h> #include <asm/setup.h> +static u32 __attribute__((aligned(PAGE_SIZE))) parking_code[PAGE_SIZE / 4] = { + 0xd503207f, /* 1: wfi */ + 0x17ffffff, /* b 1b */ +}; + +struct paging_structures parking_mm; + int arch_init_early(void) { + int err; + + parking_mm.root_paging = cell_paging; + parking_mm.root_table = + page_alloc_aligned(&mem_pool, ARM_CELL_ROOT_PT_SZ); + if (!parking_mm.root_table) + return -ENOMEM; + + err = paging_create(&parking_mm, paging_hvirt2phys(parking_code), + PAGE_SIZE, 0, + (PTE_FLAG_VALID | PTE_ACCESS_FLAG | + S2_PTE_ACCESS_RO | S2_PTE_FLAG_NORMAL), + PAGING_COHERENT); + if (err) + return err; + return arm_paging_cell_init(&root_cell); } -- 2.1.4 -- 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 jailhouse-dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.