2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) ARM Limited, 2014
7 * Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
13 #include <asm/control.h>
14 #include <asm/traps.h>
15 #include <asm/sysregs.h>
16 #include <jailhouse/printk.h>
17 #include <jailhouse/control.h>
19 static void access_cell_reg(struct trap_context *ctx, u8 reg,
20 unsigned long *val, bool is_read)
22 unsigned long mode = ctx->cpsr & PSR_MODE_MASK;
26 access_usr_reg(ctx, reg, val, is_read);
29 if (mode == PSR_FIQ_MODE)
30 access_fiq_reg(reg, val, is_read);
32 access_usr_reg(ctx, reg, val, is_read);
39 * lr is saved on the stack, as it is not banked in HYP
40 * mode. sp is banked, so lr is at offset 13 in the USR
44 access_banked_reg(usr, reg, val, is_read);
46 access_usr_reg(ctx, 13, val, is_read);
49 access_banked_reg(svc, reg, val, is_read);
52 access_banked_reg(und, reg, val, is_read);
55 access_banked_reg(abt, reg, val, is_read);
58 access_banked_reg(irq, reg, val, is_read);
61 access_banked_reg(fiq, reg, val, is_read);
67 * A trapped instruction that accesses the PC? Probably a bug,
68 * but nothing seems to prevent it.
70 printk("WARNING: trapped instruction attempted to explicitly "
78 /* Programming error */
79 printk("ERROR: attempt to write register %d\n", reg);
84 static int arch_handle_hvc(struct per_cpu *cpu_data, struct trap_context *ctx)
86 unsigned long *regs = ctx->regs;
88 regs[0] = hypercall(regs[0], regs[1], regs[2]);
93 static const trap_handler trap_handlers[38] =
95 [ESR_EC_HVC] = arch_handle_hvc,
98 void arch_handle_trap(struct per_cpu *cpu_data, struct registers *guest_regs)
100 struct trap_context ctx;
102 int ret = TRAP_UNHANDLED;
104 arm_read_banked_reg(ELR_hyp, ctx.pc);
105 arm_read_banked_reg(SPSR_hyp, ctx.cpsr);
106 arm_read_sysreg(ESR_EL2, ctx.esr);
107 exception_class = ESR_EC(ctx.esr);
108 ctx.regs = guest_regs->usr;
110 if (trap_handlers[exception_class])
111 ret = trap_handlers[exception_class](cpu_data, &ctx);
113 if (ret != TRAP_HANDLED) {
114 panic_printk("CPU%d: Unhandled HYP trap, syndrome 0x%x\n",
115 cpu_data->cpu_id, ctx.esr);
119 arm_write_banked_reg(ELR_hyp, ctx.pc);