/*
 * Exception vectors.
 */
        .macro  ventry  label
        .align  7
        b       \label
        .endm
 
        .align  11
ENTRY(hyp_traps_vector)
        ventry  hyp_sync_invalid            /* Synchronous EL2t */
        ventry  hyp_irq_invalid             /* IRQ EL2t */
        ventry  hyp_fiq_invalid             /* FIQ EL2t */
        ventry  hyp_error_invalid           /* Error EL2t */
 
        ventry  hyp_sync                    /* Synchronous EL2h */
        ventry  hyp_irq                     /* IRQ EL2h */
        ventry  hyp_fiq_invalid             /* FIQ EL2h */
        ventry  hyp_error                   /* Error EL2h */
 
        ventry  guest_sync                  /* Synchronous 64-bit EL0/EL1 */
        ventry  guest_irq                   /* IRQ 64-bit EL0/EL1 */
        ventry  guest_fiq_invalid           /* FIQ 64-bit EL0/EL1 */
        ventry  guest_error                 /* Error 64-bit EL0/EL1 */
 
        ventry  guest_sync_compat           /* Synchronous 32-bit EL0/EL1 */
        ventry  guest_irq_compat            /* IRQ 32-bit EL0/EL1 */
        ventry  guest_fiq_invalid_compat    /* FIQ 32-bit EL0/EL1 */
        ventry  guest_error_compat          /* Error 32-bit EL0/EL1 */
/*
 * 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);
    }
}

🌱 Back to Garden