This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Pending Interrupt is signaled even when interrupt is masked

Platform: FVP_Base_RevC-2xAEMvA

I set HCR_EL2.IMO/FMO to 1 to route interrupts to EL2 first for some check, and because I want this interrupt still be handled by EL1 kernel, I set interrupt mask in SPSR_EL2 and the corresponding EL1 vector entry to ELR_EL2.

However, by using signal instruction debug tool of Development Studio, I found after "eret" to EL1, and the PE trap to EL2 again, which looks like the mask is not effective and the pending interrupt is signaled again.

Thank you for any reply!

  • I set HCR_EL2.IMO/FMO to 1 to route interrupts to EL2 first for some check, and because I want this interrupt still be handled by EL1 kernel, I set interrupt mask in SPSR_EL2 and the corresponding EL1 vector entry to ELR_EL2.

    Hmm, I don't think that will work the way you want.

    In AArch64, exceptions routed to a higher Exception level (EL) cannot be masked(*).  Meaning that if IRQs/FIQs are routed to EL2, while in EL1 those exceptions are unmasked regardless of the value of PSTATE.I/F.  That's why you see a new exception straight after your ERET.

    Also, if you are using GICv3/4 then you'll have another problem.  If HCR_EL3.IMO/FMO are set, then EL1 accesses to GIC registers will be virtual - accesses go to the ICV variant instead of the ICC.  Therefore when EL1 tries to acknowledge the interrupt it thinks it has just taken, it'll be talking to the GIC's virtual interface - which won't know about the physical interrupt that belongs to EL2.

    If you don't mind me asking, what are you trying to do?

    A more typical flow for taking interrupts to EL2 and then delegating some back to EL1 looks like:

    • Configure HCR_EL2.xMO to route physical interrupts to EL2
    • EL2 takes physical interrupt
      • EL2 acknowledges physical interrupt in the GIC 
      • EL2 triages interrupt and determines that it should be handled by EL1
      • EL2 registers a virtual interrupt with the GIC, linked to the ack'ed physical interrupt
    • ERET to EL1
    • EL1 takes virtual interrupt exception
      • EL1 acknowledges the virtual interrupt in the GIC
      • <does something useful with the interrupt
      • Deactivates the virtual interrupt, which also deactivates the linked physical interrupt

    (*EL0 is something of special case)

  • Thank you very much for your detailed reply!

    I apologize for the incomplete information about my environment. I am using FVP (GICv3) and QEMU (GICv2), and it may transition to JUNO (GICv2) and N1 SDP (GICv3) in the future. The SCR_EL3.IRQ/FIQ are set to 0. 

    I am trying to implement something like process-level stage 2 page table management in the kernel, using a dedicated stage 2 page table for specific processes.

    In my EL2, there is a lightweight hypervisor that only handles HVC calls and stage 2 page table management, with no interrupt handlers implemented. Interrupts can be problematic for me since I have to switch the stage 2 page table for the interrupt handler when an interrupt occurs in specific processes. Therefore, I am trying to perform a check in EL2 if an IRQ/FIQ occurs and switch the stage 2 page table if necessary.

    Based on your detailed typical flow, I have summarized two plans for my work:

    1. Like KVM Guest:

    • Set HCR_EL2 .IMO/FMO to 1 to trap IRQs/FIQs to EL2 when running a guest in EL1/0
    • Set HCR_EL2.IMO/FMO to 0 and eret to host kernel for interrupt handling

    2. The Flow You Suggested

    Thank you again for your patience.