/* * Synchronous exception received while running in the hypervisor mode. * * While the exception could be executed with all the interrupts (e.g. * IRQ) unmasked, the interrupted context may have purposefully masked * some of them. So we want to inherit the state from the interrupted * context. */hyp_sync: entry hyp=1 /* Inherit interrupts */ mrs x0, SPSR_el2 and x0, x0, #(PSR_DBG_MASK | PSR_ABT_MASK | PSR_IRQ_MASK | PSR_FIQ_MASK) msr daif, x0 mov x0, sp bl do_trap_hyp_sync exit hyp=1
void do_trap_hyp_sync(struct cpu_user_regs *regs){ const union hsr hsr = { .bits = regs->hsr }; switch ( hsr.ec ) {#ifdef CONFIG_ARM_64 case HSR_EC_BRK: do_trap_brk(regs, hsr); break;#endif case HSR_EC_DATA_ABORT_CURR_EL: case HSR_EC_INSTR_ABORT_CURR_EL: { bool is_data = (hsr.ec == HSR_EC_DATA_ABORT_CURR_EL); const char *fault = (is_data) ? "Data Abort" : "Instruction Abort"; printk("%s Trap. Syndrome=%#x\n", fault, hsr.iss); /* * FAR may not be valid for a Synchronous External abort other * than translation table walk. */ if ( hsr.xabt.fsc == FSC_SEA && hsr.xabt.fnv ) printk("Invalid FAR, not walking the hypervisor tables\n"); else dump_hyp_walk(get_hfar(is_data)); do_unexpected_trap(fault, regs); break; } default: printk("Hypervisor Trap. HSR=%#"PRIregister" EC=0x%x IL=%x Syndrome=0x%"PRIx32"\n", hsr.bits, hsr.ec, hsr.len, hsr.iss); do_unexpected_trap("Hypervisor", regs); }}