[GIC500v3][ARMv8][A72] Interrupt is not handled correctly after A72 change from EL3 to EL1

First Part  -  EL3 Group1 SGI issue

I successfully developed a validation test, which makes A72 trigger and handle non-secure group1 SGI number 0~15 at EL3.  

But I have some problem. At EL3. 

  • When SGI0~15 are generated by ICC_SGI1R_EL1, and be grouped as Secure Group1, only SGI15 can be handled
  • When SGI0~15 are generated by ICC_SGI1R_EL1, and be grouped as Non Secure Group1, only SGI0~14 can be handled
  • When SGI0~15 are generated by ICC_ASGI1R_EL1, and be grouped as Secure Group1, only SGI0~14 can be handled
  • When SGI0~15 are generated by ICC_ASGI1R_EL1, and be grouped as Non Secure Group1, only SGI15 can be handled

Why SGI0~15 are generated by same register, but can be handled only when assigned to different group? 

When I generate SGI by writing ICC_SGI1R_EL1 and ICC_ASGI1R_EL1 at EL3, how should I correctly group them?

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Second Part - Group1 SGI from EL3 to EL1

Now, ignoring this question, I want to let A72 trigger and handle Non-secure group1 SGI test at EL1 Non-secure state. 

But I after I configure register at EL3 as showed below, and change El3 to EL1, interrupt can't be handled. What step I still miss? 


uint32_t reg;
reg = get_SCR_EL3();
reg &= ~(1<<2);//clear fiq
reg &= ~(1<<1);//clear irq
set_SCR_EL3(reg);
reg = get_HCR_EL2();
reg &= ~(1<<4);//clear FMO
reg &= ~(1<<3);//clear IMO
set_HCR_EL2(reg);
el3_config_to_non_secure();
transition_to_lower_el(EL3, EL2);
transition_to_lower_el(EL2, EL1);

Parents
  • Dealing with the SGI question first.

    When we're talking about SGIs, you need to consider two things:

    • How has the target CPU has configured the INTID (GICR_IGROUR0 and GICR_IGRPMODR0)
    • How is the sending CPU generating the interrupt (ICC_SGIxR_EL1/ICC_ASGI1_EL1)

    There's a table (plus explanation) on this page: https://developer.arm.com/documentation/198123/0302/Sending-and-receiving-Software-Generated-Interrupts

    But in summary - the Sender and Receiver need to agree, otherwise the interrupt is dropped.

    For example:

    If SW at EL3 send INTID 0 using ICC_SGI0R_EL1, it's sending the SGI as G0.  If the receiver has INTID 0 configured as NSG1 or SG0, the interrupt will be dropped because of the mismatch between the sender and receiver.

    The most likely explanation for what you're seeing is that you have different values programmed for GICR_IGRPUPR0 and GICR_IGRPMODR0 for INTIDs 0:14 compared to INTID 15.

Reply
  • Dealing with the SGI question first.

    When we're talking about SGIs, you need to consider two things:

    • How has the target CPU has configured the INTID (GICR_IGROUR0 and GICR_IGRPMODR0)
    • How is the sending CPU generating the interrupt (ICC_SGIxR_EL1/ICC_ASGI1_EL1)

    There's a table (plus explanation) on this page: https://developer.arm.com/documentation/198123/0302/Sending-and-receiving-Software-Generated-Interrupts

    But in summary - the Sender and Receiver need to agree, otherwise the interrupt is dropped.

    For example:

    If SW at EL3 send INTID 0 using ICC_SGI0R_EL1, it's sending the SGI as G0.  If the receiver has INTID 0 configured as NSG1 or SG0, the interrupt will be dropped because of the mismatch between the sender and receiver.

    The most likely explanation for what you're seeing is that you have different values programmed for GICR_IGRPUPR0 and GICR_IGRPMODR0 for INTIDs 0:14 compared to INTID 15.

Children