From: Antonios Motakis <antonios.mota...@huawei.com>

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 <antonios.mota...@huawei.com>
Signed-off-by: Dmitry Voytik <dmitry.voy...@huawei.com>
[Jan: adjust includes, remove pc from trap_context, Makefile update]
Signed-off-by: Jan Kiszka <jan.kis...@siemens.com>
---
 hypervisor/arch/arm64/Makefile            |   1 +
 hypervisor/arch/arm64/entry.S             |   4 +
 hypervisor/arch/arm64/exception.S         |  95 ++++++++++++++++++++++++
 hypervisor/arch/arm64/include/asm/traps.h |  33 +++++++++
 hypervisor/arch/arm64/traps.c             | 117 ++++++++++++++++++++++++++++++
 5 files changed, 250 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 3de96b1..c1cbae4 100644
--- a/hypervisor/arch/arm64/Makefile
+++ b/hypervisor/arch/arm64/Makefile
@@ -19,6 +19,7 @@ COMMON := ../arm-common
 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)/mmu_cell.o $(COMMON)/paging.o
 
diff --git a/hypervisor/arch/arm64/entry.S b/hypervisor/arch/arm64/entry.S
index e42cab5..16d52f4 100644
--- a/hypervisor/arch/arm64/entry.S
+++ b/hypervisor/arch/arm64/entry.S
@@ -71,6 +71,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..7164b3f
--- /dev/null
+++ b/hypervisor/arch/arm64/exception.S
@@ -0,0 +1,95 @@
+/*
+ * Jailhouse AArch64 support
+ *
+ * Copyright (C) 2015 Huawei Technologies Duesseldorf GmbH
+ *
+ * Authors:
+ *  Antonios Motakis <antonios.mota...@huawei.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#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..1ce21d9
--- /dev/null
+++ b/hypervisor/arch/arm64/include/asm/traps.h
@@ -0,0 +1,33 @@
+/*
+ * Jailhouse AArch64 support
+ *
+ * Copyright (C) 2015 Huawei Technologies Duesseldorf GmbH
+ *
+ * Authors:
+ *  Antonios Motakis <antonios.mota...@huawei.com>
+ *
+ * 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
+
+#include <jailhouse/types.h>
+
+enum trap_return {
+       TRAP_HANDLED            = 1,
+       TRAP_UNHANDLED          = 0,
+       TRAP_FORBIDDEN          = -1,
+};
+
+struct trap_context {
+       unsigned long *regs;
+       u64 esr;
+       u64 spsr;
+       u64 sp;
+};
+
+void arch_skip_instruction(struct trap_context *ctx);
+
+#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..26bdc2e
--- /dev/null
+++ b/hypervisor/arch/arm64/traps.c
@@ -0,0 +1,117 @@
+/*
+ * Jailhouse AArch64 support
+ *
+ * Copyright (C) 2015 Huawei Technologies Duesseldorf GmbH
+ *
+ * Authors:
+ *  Antonios Motakis <antonios.mota...@huawei.com>
+ *  Dmitry Voytik <dmitry.voy...@huawei.com>
+ *
+ * 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.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;
+       u64 pc;
+
+       arm_read_sysreg(ELR_EL2, pc);
+       panic_printk(" pc: %016lx   lr: %016lx spsr: %08lx     EL%1d\n"
+                    " sp: %016lx  esr: %02x %01x %07lx\n",
+                    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(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();
+       }
+}
+
+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.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.

Reply via email to