always := built-in.o
-obj-y := entry.o dbg-write.o exception.o setup.o lib.o
+obj-y := entry.o dbg-write.o exception.o setup.o lib.o traps.o
obj-y += paging.o mmu_hyp.o mmu_cell.o
obj-$(CONFIG_SERIAL_AMBA_PL011) += dbg-write-pl011.o
*/
#include <asm/head.h>
+#include <asm/sysregs.h>
.text
.globl hyp_vectors
b .
b .
b .
+ b hyp_trap
b .
b .
- b .
+
+hyp_trap:
+ /* Fill the struct registers. Should comply with NUM_USR_REGS */
+ push {r0-r12, lr}
+
+ arm_read_sysreg(TPIDR_EL2, r0)
+ mov r1, sp
+ bl arch_handle_trap
+
+ /* Restore usr regs */
+ pop {r0-r12, lr}
+ eret
int arch_mmu_cell_init(struct cell *cell);
int arch_mmu_cpu_cell_init(struct per_cpu *cpu_data);
+void arch_handle_trap(struct per_cpu *cpu_data, struct registers *guest_regs);
#endif /* !__ASSEMBLY__ */
#define PAR_ATTR_SHIFT 56
#define PAR_ATTR_MASK 0xff
+/* exception class */
+#define ESR_EC_SHIFT 26
+#define ESR_EC(hsr) ((hsr) >> ESR_EC_SHIFT & 0x3f)
+/* instruction length */
+#define ESR_IL_SHIFT 25
+#define ESR_IL(hsr) ((hsr) >> ESR_IL_SHIFT & 0x1)
+/* Instruction specific */
+#define ESR_ICC_MASK 0x1ffffff
+#define ESR_ICC(hsr) ((hsr) & ESR_ICC_MASK)
+/* Exception classes values */
+#define ESR_EC_UNK 0x00
+#define ESR_EC_WFI 0x01
+#define ESR_EC_CP15_32 0x03
+#define ESR_EC_CP15_64 0x04
+#define ESR_EC_CP14_32 0x05
+#define ESR_EC_CP14_LC 0x06
+#define ESR_EC_HCPTR 0x07
+#define ESR_EC_CP10 0x08
+#define ESR_EC_CP14_64 0x0c
+#define ESR_EC_SVC_HYP 0x11
+#define ESR_EC_HVC 0x12
+#define ESR_EC_SMC 0x13
+#define ESR_EC_IABT 0x20
+#define ESR_EC_IABT_HYP 0x21
+#define ESR_EC_PCALIGN 0x22
+#define ESR_EC_DABT 0x24
+#define ESR_EC_DABT_HYP 0x25
+
+#define NUM_USR_REGS 14
+
#ifndef __ASSEMBLY__
struct registers {
+ /* r0 - r12 and lr. The other registers are banked. */
+ unsigned long usr[NUM_USR_REGS];
};
#define dmb(domain) asm volatile("dmb " #domain "\n" ::: "memory")
#define ID_PFR0_EL1 SYSREG_32(0, c0, c1, 0)
#define ID_PFR1_EL1 SYSREG_32(0, c0, c1, 1)
#define SCTLR_EL2 SYSREG_32(4, c1, c0, 0)
+#define ESR_EL2 SYSREG_32(4, c5, c2, 0)
#define TPIDR_EL2 SYSREG_32(4, c13, c0, 2)
#define TTBR0_EL2 SYSREG_64(4, c2)
#define TCR_EL2 SYSREG_32(4, c2, c0, 2)
--- /dev/null
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) ARM Limited, 2014
+ *
+ * Authors:
+ * Jean-Philippe Brucker <jean-philippe.brucker@arm.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>
+#include <asm/head.h>
+#include <asm/percpu.h>
+
+#ifndef __ASSEMBLY__
+
+enum trap_return {
+ TRAP_HANDLED = 1,
+ TRAP_UNHANDLED = 0,
+};
+
+struct trap_context {
+ unsigned long *regs;
+ u32 esr;
+ u32 cpsr;
+};
+
+typedef int (*trap_handler)(struct per_cpu *cpu_data,
+ struct trap_context *ctx);
+
+#define arm_read_banked_reg(reg, val) \
+ asm volatile ("mrs %0, " #reg "\n" : "=r" (val))
+
+#define arm_write_banked_reg(reg, val) \
+ asm volatile ("msr " #reg ", %0\n" : : "r" (val))
+
+#endif /* !__ASSEMBLY__ */
+#endif /* !_JAILHOUSE_ASM_TRAPS_H */
--- /dev/null
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) ARM Limited, 2014
+ *
+ * Authors:
+ * Jean-Philippe Brucker <jean-philippe.brucker@arm.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/control.h>
+#include <asm/traps.h>
+#include <asm/sysregs.h>
+#include <jailhouse/printk.h>
+#include <jailhouse/control.h>
+
+static int arch_handle_hvc(struct per_cpu *cpu_data, struct trap_context *ctx)
+{
+ unsigned long *regs = ctx->regs;
+
+ regs[0] = hypercall(regs[0], regs[1], regs[2]);
+
+ return TRAP_HANDLED;
+}
+
+static const trap_handler trap_handlers[38] =
+{
+ [ESR_EC_HVC] = arch_handle_hvc,
+};
+
+void arch_handle_trap(struct per_cpu *cpu_data, struct registers *guest_regs)
+{
+ struct trap_context ctx;
+ u32 exception_class;
+ int ret = TRAP_UNHANDLED;
+
+ arm_read_banked_reg(SPSR_hyp, ctx.cpsr);
+ arm_read_sysreg(ESR_EL2, ctx.esr);
+ exception_class = ESR_EC(ctx.esr);
+ ctx.regs = guest_regs->usr;
+
+ if (trap_handlers[exception_class])
+ ret = trap_handlers[exception_class](cpu_data, &ctx);
+
+ if (ret != TRAP_HANDLED) {
+ panic_printk("CPU%d: Unhandled HYP trap, syndrome 0x%x\n",
+ cpu_data->cpu_id, ctx.esr);
+ while(1);
+ }
+}