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.
12 * Condition check code is copied from Linux's
13 * - arch/arm/kernel/opcodes.c
14 * - arch/arm/kvm/emulate.c
17 #include <asm/control.h>
18 #include <asm/gic_common.h>
19 #include <asm/platform.h>
20 #include <asm/traps.h>
21 #include <asm/sysregs.h>
22 #include <jailhouse/printk.h>
23 #include <jailhouse/control.h>
26 * condition code lookup table
27 * index into the table is test code: EQ, NE, ... LT, GT, AL, NV
29 * bit position in short is condition code: NZCV
31 static const unsigned short cc_map[16] = {
32 0xF0F0, /* EQ == Z set */
34 0xCCCC, /* CS == C set */
36 0xFF00, /* MI == N set */
38 0xAAAA, /* VS == V set */
40 0x0C0C, /* HI == C set && Z clear */
41 0xF3F3, /* LS == C clear || Z set */
42 0xAA55, /* GE == (N==V) */
43 0x55AA, /* LT == (N!=V) */
44 0x0A05, /* GT == (!Z && (N==V)) */
45 0xF5FA, /* LE == (Z || (N!=V)) */
46 0xFFFF, /* AL always */
50 /* Check condition field either from ESR or from SPSR in thumb mode */
51 static bool arch_failed_condition(struct trap_context *ctx)
53 u32 class = ESR_EC(ctx->esr);
54 u32 icc = ESR_ICC(ctx->esr);
56 u32 flags = cpsr >> 28;
59 * Trapped instruction is unconditional, already passed the condition
60 * check, or is invalid
62 if (class & 0x30 || class == 0)
65 /* Is condition field valid? */
66 if (icc & ESR_ICC_CV_BIT) {
67 cond = ESR_ICC_COND(icc);
69 /* This can happen in Thumb mode: examine IT state. */
70 unsigned long it = PSR_IT(cpsr);
72 /* it == 0 => unconditional. */
76 /* The cond for this insn works out as the top 4 bits. */
80 /* Compare the apsr flags with the condition code */
81 if ((cc_map[cond] >> flags) & 1)
88 * When exceptions occur while instructions are executed in Thumb IF-THEN
89 * blocks, the ITSTATE field of the CPSR is not advanced (updated), so we have
90 * to do this little bit of work manually. The fields map like this:
92 * IT[7:0] -> CPSR[26:25],CPSR[15:10]
94 static void arch_advance_itstate(struct trap_context *ctx)
96 unsigned long itbits, cond;
97 unsigned long cpsr = ctx->cpsr;
99 if (!(cpsr & PSR_IT_MASK(0xff)))
102 itbits = PSR_IT(cpsr);
105 if ((itbits & 0x7) == 0)
106 /* One instruction left in the block, next itstate is 0 */
109 itbits = (itbits << 1) & 0x1f;
111 itbits |= (cond << 5);
112 cpsr &= ~PSR_IT_MASK(0xff);
113 cpsr |= PSR_IT_MASK(itbits);
118 static void arch_skip_instruction(struct trap_context *ctx)
120 u32 instruction_length = ESR_IL(ctx->esr);
122 ctx->pc += (instruction_length ? 4 : 2);
123 arch_advance_itstate(ctx);
126 static void access_cell_reg(struct trap_context *ctx, u8 reg,
127 unsigned long *val, bool is_read)
129 unsigned long mode = ctx->cpsr & PSR_MODE_MASK;
133 access_usr_reg(ctx, reg, val, is_read);
136 if (mode == PSR_FIQ_MODE)
137 access_fiq_reg(reg, val, is_read);
139 access_usr_reg(ctx, reg, val, is_read);
146 * lr is saved on the stack, as it is not banked in HYP
147 * mode. sp is banked, so lr is at offset 13 in the USR
151 access_banked_reg(usr, reg, val, is_read);
153 access_usr_reg(ctx, 13, val, is_read);
156 access_banked_reg(svc, reg, val, is_read);
159 access_banked_reg(und, reg, val, is_read);
162 access_banked_reg(abt, reg, val, is_read);
165 access_banked_reg(irq, reg, val, is_read);
168 access_banked_reg(fiq, reg, val, is_read);
174 * A trapped instruction that accesses the PC? Probably a bug,
175 * but nothing seems to prevent it.
177 printk("WARNING: trapped instruction attempted to explicitly "
185 /* Programming error */
186 printk("ERROR: attempt to write register %d\n", reg);
191 static int arch_handle_hvc(struct per_cpu *cpu_data, struct trap_context *ctx)
193 unsigned long *regs = ctx->regs;
195 regs[0] = hypercall(regs[0], regs[1], regs[2]);
200 static int arch_handle_cp15_64(struct per_cpu *cpu_data, struct trap_context *ctx)
202 unsigned long rt_val, rt2_val;
203 u32 opc1 = ctx->esr >> 16 & 0x7;
204 u32 rt2 = ctx->esr >> 10 & 0xf;
205 u32 rt = ctx->esr >> 5 & 0xf;
206 u32 crm = ctx->esr >> 1 & 0xf;
207 u32 read = ctx->esr & 1;
210 access_cell_reg(ctx, rt, &rt_val, true);
211 access_cell_reg(ctx, rt2, &rt2_val, true);
214 #ifdef CONFIG_ARM_GIC_V3
215 /* Trapped ICC_SGI1R write */
216 if (!read && opc1 == 0 && crm == 12) {
217 arch_skip_instruction(ctx);
218 return gicv3_handle_sgir_write(cpu_data,
219 (u64)rt2_val << 32 | rt_val);
222 /* Avoid `unused' warning... */
227 return TRAP_UNHANDLED;
230 static const trap_handler trap_handlers[38] =
232 [ESR_EC_CP15_64] = arch_handle_cp15_64,
233 [ESR_EC_HVC] = arch_handle_hvc,
236 void arch_handle_trap(struct per_cpu *cpu_data, struct registers *guest_regs)
238 struct trap_context ctx;
240 int ret = TRAP_UNHANDLED;
242 arm_read_banked_reg(ELR_hyp, ctx.pc);
243 arm_read_banked_reg(SPSR_hyp, ctx.cpsr);
244 arm_read_sysreg(ESR_EL2, ctx.esr);
245 exception_class = ESR_EC(ctx.esr);
246 ctx.regs = guest_regs->usr;
249 * On some implementations, instructions that fail their condition check
252 if (arch_failed_condition(&ctx)) {
253 arch_skip_instruction(&ctx);
254 goto restore_context;
257 if (trap_handlers[exception_class])
258 ret = trap_handlers[exception_class](cpu_data, &ctx);
260 if (ret != TRAP_HANDLED) {
261 panic_printk("CPU%d: Unhandled HYP trap, syndrome 0x%x\n",
262 cpu_data->cpu_id, ctx.esr);
267 arm_write_banked_reg(SPSR_hyp, ctx.cpsr);
268 arm_write_banked_reg(ELR_hyp, ctx.pc);