#include <jailhouse/control.h>
#include <jailhouse/printk.h>
+#include <jailhouse/processor.h>
#include <jailhouse/string.h>
#include <asm/control.h>
#include <asm/irqchip.h>
arch_cpu_tlb_flush(cpu_data);
}
+static void arch_dump_exit(const char *reason)
+{
+ unsigned long pc;
+
+ arm_read_banked_reg(ELR_hyp, pc);
+ printk("Unhandled HYP %s exit at 0x%x\n", reason, pc);
+}
+
+static void arch_dump_abt(bool is_data)
+{
+ u32 hxfar;
+ u32 esr;
+
+ arm_read_sysreg(ESR_EL2, esr);
+ if (is_data)
+ arm_read_sysreg(HDFAR, hxfar);
+ else
+ arm_read_sysreg(HIFAR, hxfar);
+
+ printk(" paddr=0x%lx esr=0x%x\n", hxfar, esr);
+}
+
struct registers* arch_handle_exit(struct per_cpu *cpu_data,
struct registers *regs)
{
case EXIT_REASON_TRAP:
arch_handle_trap(cpu_data, regs);
break;
+
+ case EXIT_REASON_UNDEF:
+ arch_dump_exit("undef");
+ panic_stop();
+ case EXIT_REASON_DABT:
+ arch_dump_exit("data abort");
+ arch_dump_abt(true);
+ panic_stop();
+ case EXIT_REASON_PABT:
+ arch_dump_exit("prefetch abort");
+ arch_dump_abt(false);
+ panic_stop();
+ case EXIT_REASON_HVC:
+ arch_dump_exit("hvc");
+ panic_stop();
+ case EXIT_REASON_FIQ:
+ arch_dump_exit("fiq");
+ panic_stop();
default:
- printk("Internal error: %d exit not implemented\n",
- regs->exit_reason);
- while(1);
+ arch_dump_exit("unknown");
+ panic_stop();
}
return regs;
void arch_config_commit(struct cell *cell_added_removed)
{
}
+
+void arch_panic_stop(void)
+{
+ psci_cpu_off(this_cpu_data());
+ __builtin_unreachable();
+}
+
+void arch_panic_park(void)
+{
+ /* Won't return to panic_park */
+ if (phys_processor_id() == panic_cpu)
+ panic_in_progress = 0;
+
+ psci_cpu_off(this_cpu_data());
+ __builtin_unreachable();
+}
.align 5
hyp_vectors:
b .
- b .
- b .
- b .
- b .
+ b hyp_undef
+ b hyp_hvc
+ b hyp_pabt
+ b hyp_dabt
b hyp_trap
b hyp_irq
- b .
+ b hyp_fiq
.macro handle_vmexit exit_reason
/* Fill the struct registers. Should comply with NUM_USR_REGS */
b vmexit_common
.endm
+hyp_undef:
+ handle_vmexit EXIT_REASON_UNDEF
+hyp_hvc:
+ handle_vmexit EXIT_REASON_HVC
+hyp_pabt:
+ handle_vmexit EXIT_REASON_PABT
+hyp_dabt:
+ handle_vmexit EXIT_REASON_DABT
+
hyp_irq:
handle_vmexit EXIT_REASON_IRQ
+hyp_fiq:
+ handle_vmexit EXIT_REASON_FIQ
hyp_trap:
handle_vmexit EXIT_REASON_TRAP
#define ESR_ICC_CV_BIT (1 << 24)
#define ESR_ICC_COND(icc) ((icc) >> 20 & 0xf)
-#define EXIT_REASON_TRAP 0x1
-#define EXIT_REASON_IRQ 0x2
+#define EXIT_REASON_UNDEF 0x1
+#define EXIT_REASON_HVC 0x2
+#define EXIT_REASON_PABT 0x3
+#define EXIT_REASON_DABT 0x4
+#define EXIT_REASON_TRAP 0x5
+#define EXIT_REASON_IRQ 0x6
+#define EXIT_REASON_FIQ 0x7
#define NUM_USR_REGS 14
#define VBAR SYSREG_32(0, c12, c0, 0)
#define HCR SYSREG_32(4, c1, c1, 0)
#define HCR2 SYSREG_32(4, c1, c1, 4)
+#define HDFAR SYSREG_32(4, c6, c0, 0)
+#define HIFAR SYSREG_32(4, c6, c0, 2)
+#define HPFAR SYSREG_32(4, c6, c0, 4)
#define HMAIR0 SYSREG_32(4, c10, c2, 0)
#define HMAIR1 SYSREG_32(4, c10, c2, 1)
#define HVBAR SYSREG_32(4, c12, c0, 0)
// catch missing symbols
void arch_shutdown_cpu(unsigned int cpu_id) {}
void arch_shutdown(void) {}
-void arch_panic_stop(void) {__builtin_unreachable();}
-void arch_panic_park(void) {}
}
}
+static void dump_guest_regs(struct per_cpu *cpu_data, struct trap_context *ctx)
+{
+ u8 reg;
+ unsigned long reg_val;
+
+ panic_printk("pc=0x%08x cpsr=0x%08x esr=0x%08x\n", ctx->pc, ctx->cpsr,
+ ctx->esr);
+ for (reg = 0; reg < 15; reg++) {
+ access_cell_reg(ctx, reg, ®_val, true);
+ panic_printk("r%d=0x%08x ", reg, reg_val);
+ if ((reg + 1) % 4 == 0)
+ panic_printk("\n");
+ }
+ panic_printk("\n");
+}
+
static int arch_handle_hvc(struct per_cpu *cpu_data, struct trap_context *ctx)
{
unsigned long *regs = ctx->regs;
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);
+ switch (ret) {
+ case TRAP_UNHANDLED:
+ case TRAP_FORBIDDEN:
+ panic_printk("FATAL: %s on CPU%d\n", (ret == TRAP_UNHANDLED ?
+ "unhandled trap" : "forbidden access"),
+ cpu_data->cpu_id);
+ dump_guest_regs(cpu_data, &ctx);
+ panic_park();
}
restore_context: