From: Antonios Motakis <[email protected]> Catch exceptions on the AArch64 target of Jailhouse. Catch and aborts from EL2 that might be caused by the hypervisor.
Signed-off-by: Antonios Motakis <[email protected]> Signed-off-by: Dmitry Voytik <[email protected]> --- hypervisor/arch/arm64/Makefile | 1 + hypervisor/arch/arm64/entry.S | 4 + hypervisor/arch/arm64/exception.S | 96 ++++++++++++++++++++++++ hypervisor/arch/arm64/include/asm/traps.h | 35 +++++++++ hypervisor/arch/arm64/traps.c | 119 ++++++++++++++++++++++++++++++ 5 files changed, 255 insertions(+) create mode 100644 hypervisor/arch/arm64/exception.S create mode 100644 hypervisor/arch/arm64/include/asm/traps.h create mode 100644 hypervisor/arch/arm64/traps.c diff --git a/hypervisor/arch/arm64/Makefile b/hypervisor/arch/arm64/Makefile index 0911ff3..603056e 100644 --- a/hypervisor/arch/arm64/Makefile +++ b/hypervisor/arch/arm64/Makefile @@ -18,5 +18,6 @@ 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-$(CONFIG_SERIAL_AMBA_PL011) += ../arm/dbg-write-pl011.o diff --git a/hypervisor/arch/arm64/entry.S b/hypervisor/arch/arm64/entry.S index aff1647..3cf9540 100644 --- a/hypervisor/arch/arm64/entry.S +++ b/hypervisor/arch/arm64/entry.S @@ -63,6 +63,10 @@ el2_entry: cmp x1, #0x16 b.ne . /* not hvc */ + /* install jailhouse vectors */ + adr x1, hyp_vectors + msr vbar_el2, x1 + /* init bootstrap page tables */ bl init_bootstrap_pt diff --git a/hypervisor/arch/arm64/exception.S b/hypervisor/arch/arm64/exception.S new file mode 100644 index 0000000..943be9b --- /dev/null +++ b/hypervisor/arch/arm64/exception.S @@ -0,0 +1,96 @@ +/* + * Jailhouse AArch64 support + * + * Copyright (C) 2015 Huawei Technologies Duesseldorf GmbH + * + * Authors: + * Antonios Motakis <[email protected]> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include <asm/head.h> +#include <asm/processor.h> +#include <asm/sysregs.h> + +.macro ventry label + .align 7 + b \label +.endm + +.macro handle_vmexit exit_reason + .align 7 + /* Fill the struct registers. Should comply with NUM_USR_REGS */ + stp x29, x30, [sp, #-16]! + stp x27, x28, [sp, #-16]! + stp x25, x26, [sp, #-16]! + stp x23, x24, [sp, #-16]! + stp x21, x22, [sp, #-16]! + stp x19, x20, [sp, #-16]! + stp x17, x18, [sp, #-16]! + stp x15, x16, [sp, #-16]! + stp x13, x14, [sp, #-16]! + stp x11, x12, [sp, #-16]! + stp x9, x10, [sp, #-16]! + stp x7, x8, [sp, #-16]! + stp x5, x6, [sp, #-16]! + stp x3, x4, [sp, #-16]! + stp x1, x2, [sp, #-16]! + + mov x1, #\exit_reason + stp x1, x0, [sp, #-16]! + + mov x29, xzr /* reset fp,lr */ + mov x30, xzr + mrs x0, tpidr_el2 + mov x1, sp + bl arch_handle_exit + b . +.endm + + .text + .globl hyp_vectors + .align 11 +hyp_vectors: + ventry . + ventry . + ventry . + ventry . + + handle_vmexit EXIT_REASON_EL2_ABORT + ventry . + ventry . + ventry . + + handle_vmexit EXIT_REASON_EL1_ABORT + handle_vmexit EXIT_REASON_EL1_IRQ + ventry . + ventry . + + ventry . + ventry . + ventry . + ventry . + + .globl vmreturn +vmreturn: + /* x0: struct registers* */ + mov sp, x0 + ldp x1, x0, [sp], #16 /* x1 is the exit_reason */ + ldp x1, x2, [sp], #16 + ldp x3, x4, [sp], #16 + ldp x5, x6, [sp], #16 + ldp x7, x8, [sp], #16 + ldp x9, x10, [sp], #16 + ldp x11, x12, [sp], #16 + ldp x13, x14, [sp], #16 + ldp x15, x16, [sp], #16 + ldp x17, x18, [sp], #16 + ldp x19, x20, [sp], #16 + ldp x21, x22, [sp], #16 + ldp x23, x24, [sp], #16 + ldp x25, x26, [sp], #16 + ldp x27, x28, [sp], #16 + ldp x29, x30, [sp], #16 + eret diff --git a/hypervisor/arch/arm64/include/asm/traps.h b/hypervisor/arch/arm64/include/asm/traps.h new file mode 100644 index 0000000..3a60e30 --- /dev/null +++ b/hypervisor/arch/arm64/include/asm/traps.h @@ -0,0 +1,35 @@ +/* + * Jailhouse AArch64 support + * + * Copyright (C) 2015 Huawei Technologies Duesseldorf GmbH + * + * Authors: + * Antonios Motakis <[email protected]> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#ifndef _JAILHOUSE_ASM_TRAPS_H +#define _JAILHOUSE_ASM_TRAPS_H + +#ifndef __ASSEMBLY__ + +enum trap_return { + TRAP_HANDLED = 1, + TRAP_UNHANDLED = 0, + TRAP_FORBIDDEN = -1, +}; + +struct trap_context { + unsigned long *regs; + u64 esr; + u64 spsr; + u64 pc; + u64 sp; +}; + +void arch_skip_instruction(struct trap_context *ctx); + +#endif /* !__ASSEMBLY__ */ +#endif /* !_JAILHOUSE_ASM_TRAPS_H */ diff --git a/hypervisor/arch/arm64/traps.c b/hypervisor/arch/arm64/traps.c new file mode 100644 index 0000000..b27bb2e --- /dev/null +++ b/hypervisor/arch/arm64/traps.c @@ -0,0 +1,119 @@ +/* + * Jailhouse AArch64 support + * + * Copyright (C) 2015 Huawei Technologies Duesseldorf GmbH + * + * Authors: + * Antonios Motakis <[email protected]> + * Dmitry Voytik <[email protected]> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include <jailhouse/control.h> +#include <jailhouse/printk.h> +#include <asm/control.h> +#include <asm/gic_common.h> +#include <asm/platform.h> +#include <asm/psci.h> +#include <asm/sysregs.h> +#include <asm/traps.h> +#include <asm/processor.h> + +void arch_skip_instruction(struct trap_context *ctx) +{ + trace_error(-EINVAL); + while(1); +} + +static void dump_regs(struct trap_context *ctx) +{ + unsigned char i; + + panic_printk(" pc: %016lx lr: %016lx spsr: %08lx EL%1d\n" + " sp: %016lx esr: %02x %01x %07lx\n", + ctx->pc, ctx->regs[30], ctx->spsr, SPSR_EL(ctx->spsr), + ctx->sp, ESR_EC(ctx->esr), ESR_IL(ctx->esr), + ESR_ISS(ctx->esr)); + for (i = 0; i < NUM_USR_REGS - 1; i++) + panic_printk("%sx%d: %016lx%s", i < 10 ? " " : "", i, + ctx->regs[i], i % 3 == 2 ? "\n" : " "); + panic_printk("\n"); +} + +static void fill_trap_context(struct trap_context *ctx, struct registers *regs) +{ + arm_read_sysreg(ELR_EL2, ctx->pc); + arm_read_sysreg(SPSR_EL2, ctx->spsr); + switch (SPSR_EL(ctx->spsr)) { /* exception level */ + case 0: + arm_read_sysreg(SP_EL0, ctx->sp); break; + case 1: + arm_read_sysreg(SP_EL1, ctx->sp); break; + case 2: + arm_read_sysreg(SP_EL2, ctx->sp); break; + default: + ctx->sp = 0; break; /* should never happen */ + } + arm_read_sysreg(ESR_EL2, ctx->esr); + ctx->regs = regs->usr; +} + +static void arch_handle_trap(struct per_cpu *cpu_data, + struct registers *guest_regs) +{ + struct trap_context ctx; + int ret; + + fill_trap_context(&ctx, guest_regs); + + /* exception class */ + switch (ESR_EC(ctx.esr)) { + default: + ret = TRAP_UNHANDLED; + } + + if (ret == TRAP_UNHANDLED || ret == TRAP_FORBIDDEN) { + panic_printk("\nFATAL: exception %s\n", (ret == TRAP_UNHANDLED ? + "unhandled trap" : + "forbidden access")); + panic_printk("Cell state before exception:\n"); + dump_regs(&ctx); + panic_park(); + } + + arm_write_sysreg(ELR_EL2, ctx.pc); +} + +static void arch_dump_exit(struct registers *regs, const char *reason) +{ + struct trap_context ctx; + + fill_trap_context(&ctx, regs); + panic_printk("\nFATAL: Unhandled HYP exception: %s\n", reason); + dump_regs(&ctx); +} + +struct registers *arch_handle_exit(struct per_cpu *cpu_data, + struct registers *regs) +{ + cpu_data->stats[JAILHOUSE_CPU_STAT_VMEXITS_TOTAL]++; + + switch (regs->exit_reason) { + case EXIT_REASON_EL1_ABORT: + arch_handle_trap(cpu_data, regs); + break; + + case EXIT_REASON_EL2_ABORT: + arch_dump_exit(regs, "synchronous abort from EL2"); + panic_stop(); + break; + + default: + arch_dump_exit(regs, "unexpected"); + panic_stop(); + } + + 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.
