I am trying to work out a loop SGI0 ~ SGI15 triggering and handling test.
I made it work for only one round. A72 can trigger SGI0~SGI15 and handle it.
But when I try to trigger any SGI again, it will not enter pending state, and be distributed to A72 again.
my first round code is like
init a53/a72/GIC
use a53 to kick off a72
use a72 to read out MPIDR_EL1
use a72 to configure affinity and set ICC_SGI0R_EL1 (SGI0 from A53 to A72)
use a72 to check redistributor GIR_ISPENDER (make sure SGI enter is generated and enter pending state)
use a72 to install interrupt handler (read out IAR0 and set EOIR0)
use a72 to enable interrupt (GICR_WAKER / GIC_PRIORITY / GICR_CFG / GICR_GROUP/ GICR_ISENABLER )
SGI0 ~ SGI15 can be triggered and handled without error. but when I set ICC_SGI0R_EL1 again to trigger anyone of SGI. GIR_ISPENDER is always 0x40000000, seems SGI can't enter pending state again?
why's that? thanks in advance.
Ok, a potential explanation if I understood the order of the steps correctly.
There are three registers for generating SGIs:
Which register you write sets the Group the sender wants to send. The GIC compares what the sender sent against how the receiver configured the interrupt. For example, if the sender sends G1 (ICC_SGI1R_EL1) but the receiver has configured the interrupt as G0 (in GICR_IGROUPR0/GICR_IGRPMODR0), then the request is dropped. The GIC guide has a handy table on the result of differences in the sending and receiving Group:
Learn the architecture - Generic Interrupt Controller v3 and v4, Overview (arm.com)
In you original post I think you generate the SGIs first (write ICC_SGI0R_EL1), then later configure the SGIs (GICR_IGROUPR0) later. Is that correct?
If so, that could be the problem.
You're writing ICC_SGI0R_EL1, which is setting the sending Group as 0. At reset, all SGIs are assigned to G0, so the sending/receiving Group are the same.
Later you're write 1s to GICR_IGROUPR0, which is allocating the SGIs to NS.G1. So when you write ICC_SGI0R_EL1 for a second time the sending and receiving Group no longer match.
To fix you either to leave the SGIs as G0 (remove the writes to GICR_IGROUPR0), or change which register you write to when you generate the second set of SGIs.
Hi Martin,
Much appreciated for your help!!!!! I made it after delete the GICR_IGROUPR0 register access!!!
I wondered why I need to access IGROUP0 after access IENABLER, but I didn't pay more attention on it. (Legacy code issue from colleague I suppose)
And I found that my access to EOIR is also wrong. After I correct them all. Looping SGI triggering and handling test can be run and pass.
Thanks very much again. And have a wonderful day!