From: Antonios Motakis <[email protected]> Add hypervisor disable support to the Jailhouse firmware. Handle Jailhouse disable calls from the root cell, and also disable the hypervisor in case of an error during initialization.
Signed-off-by: Antonios Motakis <[email protected]> --- hypervisor/arch/arm64/control.c | 8 +++++-- hypervisor/arch/arm64/entry.S | 33 +++++++++++++++++++++++++++ hypervisor/arch/arm64/include/asm/percpu.h | 1 + hypervisor/arch/arm64/setup.c | 36 ++++++++++++++++++++++++++++-- hypervisor/arch/arm64/traps.c | 4 ++++ 5 files changed, 78 insertions(+), 4 deletions(-) diff --git a/hypervisor/arch/arm64/control.c b/hypervisor/arch/arm64/control.c index 4b6643a..0e1c780 100644 --- a/hypervisor/arch/arm64/control.c +++ b/hypervisor/arch/arm64/control.c @@ -124,8 +124,12 @@ void arch_config_commit(struct cell *cell_added_removed) void arch_shutdown(void) { - trace_error(-EINVAL); - while (1); + unsigned int cpu; + + /* turn off the hypervisor when we return from the exit handler */ + if (root_cell.cpu_set) + for_each_cpu(cpu, root_cell.cpu_set) + per_cpu(cpu)->shutdown = true; } void arch_suspend_cpu(unsigned int cpu_id) diff --git a/hypervisor/arch/arm64/entry.S b/hypervisor/arch/arm64/entry.S index 3cf9540..cab4810 100644 --- a/hypervisor/arch/arm64/entry.S +++ b/hypervisor/arch/arm64/entry.S @@ -110,6 +110,39 @@ el2_entry: bl entry b . + .globl arch_shutdown_mmu +arch_shutdown_mmu: + /* x0: struct percpu* */ + mov x19, x0 + + /* Note: no memory accesses must be done after turning MMU off. There + * is non-zero probability that cached data can be not syncronized with + * system memory. CPU can access data bypassing D-cache when MMU is off. + */ + + /* hand over control of EL2 back to Linux */ + add x1, x19, #PERCPU_LINUX_SAVED_VECTORS + ldr x2, [x1] + msr vbar_el2, x2 + + /* disable the hypervisor MMU */ + mrs x1, sctlr_el2 + ldr x2, =(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) + bic x1, x1, x2 + msr sctlr_el2, x1 + isb + + msr mair_el2, xzr + msr ttbr0_el2, xzr + msr tcr_el2, xzr + isb + + msr tpidr_el2, xzr + + /* Call vmreturn(guest_registers) */ + add x0, x19, #(PERCPU_STACK_END - 32 * 8) + b vmreturn + .globl enable_mmu_el2 enable_mmu_el2: /* diff --git a/hypervisor/arch/arm64/include/asm/percpu.h b/hypervisor/arch/arm64/include/asm/percpu.h index d168dd5..49a1d09 100644 --- a/hypervisor/arch/arm64/include/asm/percpu.h +++ b/hypervisor/arch/arm64/include/asm/percpu.h @@ -57,6 +57,7 @@ struct per_cpu { struct psci_mbox guest_mbox; unsigned long mpidr; + bool shutdown; } __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 55dda3e..be07395 100644 --- a/hypervisor/arch/arm64/setup.c +++ b/hypervisor/arch/arm64/setup.c @@ -87,8 +87,40 @@ int arch_unmap_device(void *vaddr, unsigned long size) PAGING_NON_COHERENT); } +/* disable the hypervisor on the current CPU */ +void arch_shutdown_self(struct per_cpu *cpu_data) +{ + irqchip_cpu_shutdown(cpu_data); + + /* Free the guest */ + arm_write_sysreg(HCR_EL2, HCR_RW_BIT); + arm_write_sysreg(VTCR_EL2, VTCR_RES1); + + /* Remove stage-2 mappings */ + arch_cpu_tlb_flush(cpu_data); + + /* TLB flush needs the cell's VMID */ + isb(); + arm_write_sysreg(VTTBR_EL2, 0); + + /* we will restore the root cell state with the MMU turned off, + * so we need to make sure it has been commited to memory */ + arch_paging_flush_cpu_caches(guest_regs(cpu_data), + sizeof(struct registers)); + dsb(ish); + + /* Return to EL1 */ + arch_shutdown_mmu(cpu_data); +} + void arch_cpu_restore(struct per_cpu *cpu_data, int return_code) { - trace_error(-EINVAL); - while (1); + struct registers *regs = guest_regs(cpu_data); + + /* Jailhouse initialization failed; return to the caller in EL1 */ + arm_write_sysreg(ELR_EL2, regs->usr[30]); + + regs->usr[0] = return_code; + + arch_shutdown_self(cpu_data); } diff --git a/hypervisor/arch/arm64/traps.c b/hypervisor/arch/arm64/traps.c index 45163fd..9c7f486 100644 --- a/hypervisor/arch/arm64/traps.c +++ b/hypervisor/arch/arm64/traps.c @@ -196,5 +196,9 @@ struct registers *arch_handle_exit(struct per_cpu *cpu_data, panic_stop(); } + if (cpu_data->shutdown) + /* Won't return here. */ + arch_shutdown_self(cpu_data); + vmreturn(regs); } -- 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.
