[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
  • There's unfortunately not enough information in code snippet you shared to answer.  Here are some things that I would check:

    • Have you set ARE_NS and ARE_S in GICD_CTLR?
    • Have you set ICC_SRE_EL2.SRE? (requires that SCR_EL3.NS is set to 1)
    • Have you set ICC_SRE_EL1.SRE in _both_ banked copies of ICC_SRE_EL1?  (easy point to forget)
    • While in EL3, did you remember to use an ISB after changing SCR_EL3.NS? (if not, you might not be accessing the banked copy of a register you think you are)
    • Did you set the NS.G1 enable in the CPU? (remember ICC_IGRPEN1_EL1 is banked)
    • Did you set the NS.G1 enable in the Distributor?
    • Before leaving EL3, did you program ICC_PMR_EL1 to a value in the NS range?
    • Before leaving EL3, did you use GICx_IGROUPRn/GICx_IGRPMODn to make the appropriate interrupts NS.G1?
    • Before leaving EL3, did you do the GICR_WAKER sequence?  (in your case "yes", as you've been getting interrupts in EL3)
    • Did you remember to clear PSTATE.I/F for the EL/Security state being entered?  (I always kick myself if I've forgotten)

    Assuming all of that checks out, when you think you should be getting an interrupt:

    • Do you see the interrupt as pending in GICx_ISPENDRn? (if not, there's no interrupt to be sent)
    • Do you see the interrupt as NOT active in GICx_ISACTIVERn? (if the interrupt is Active, or Active&Pending, it won't be signalled)
    • Have you checked the individual enable, group, priority and target configuration?
    • What do ICC_HPPIR0_EL1 and ICC_HPPIR1_EL1 report? (these will tell you if the interrupt was forwarded to the CPU and aren't effected the PMR or RPR)
    • What does ICC_RPR_EL1 report?  (if not "idle", then a new interrupt will only be signalled if it meets the pre-emption rules)
    • If the interrupt is reported in one of the HPPIs, will its priority beat the PMR? (remember, must be numerically lower than PMR)

    Also... you probably don't want SCR_EL3.FIQ cleared while in Non-secure state.  In GICv3, FIQ is used for G0 interrupts and interrupts for the "other" Security state.  Meaning in NS state, FIQs will either be G0 interrupts or SG1 interrupts - neither of which you can really manage in Non-secure state.

Reply
  • There's unfortunately not enough information in code snippet you shared to answer.  Here are some things that I would check:

    • Have you set ARE_NS and ARE_S in GICD_CTLR?
    • Have you set ICC_SRE_EL2.SRE? (requires that SCR_EL3.NS is set to 1)
    • Have you set ICC_SRE_EL1.SRE in _both_ banked copies of ICC_SRE_EL1?  (easy point to forget)
    • While in EL3, did you remember to use an ISB after changing SCR_EL3.NS? (if not, you might not be accessing the banked copy of a register you think you are)
    • Did you set the NS.G1 enable in the CPU? (remember ICC_IGRPEN1_EL1 is banked)
    • Did you set the NS.G1 enable in the Distributor?
    • Before leaving EL3, did you program ICC_PMR_EL1 to a value in the NS range?
    • Before leaving EL3, did you use GICx_IGROUPRn/GICx_IGRPMODn to make the appropriate interrupts NS.G1?
    • Before leaving EL3, did you do the GICR_WAKER sequence?  (in your case "yes", as you've been getting interrupts in EL3)
    • Did you remember to clear PSTATE.I/F for the EL/Security state being entered?  (I always kick myself if I've forgotten)

    Assuming all of that checks out, when you think you should be getting an interrupt:

    • Do you see the interrupt as pending in GICx_ISPENDRn? (if not, there's no interrupt to be sent)
    • Do you see the interrupt as NOT active in GICx_ISACTIVERn? (if the interrupt is Active, or Active&Pending, it won't be signalled)
    • Have you checked the individual enable, group, priority and target configuration?
    • What do ICC_HPPIR0_EL1 and ICC_HPPIR1_EL1 report? (these will tell you if the interrupt was forwarded to the CPU and aren't effected the PMR or RPR)
    • What does ICC_RPR_EL1 report?  (if not "idle", then a new interrupt will only be signalled if it meets the pre-emption rules)
    • If the interrupt is reported in one of the HPPIs, will its priority beat the PMR? (remember, must be numerically lower than PMR)

    Also... you probably don't want SCR_EL3.FIQ cleared while in Non-secure state.  In GICv3, FIQ is used for G0 interrupts and interrupts for the "other" Security state.  Meaning in NS state, FIQs will either be G0 interrupts or SG1 interrupts - neither of which you can really manage in Non-secure state.

Children