We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi,
Recently I am working on porting our Cortex A7 code that used to run in secure world to non-secure world for some reason. I got a problem when it came to GIC initialization.
I noticed that in order to manipulate a certain interrupt settings in non-secure world, I need to set that interrupt to Group 1 before I jump to non-secure. Besides that, everything else should be just identical to what should be done in secure world. Even the GICC and GICD control registers banked for non-secure world changed the enable bit for Group 1 to bit 0 so it can be enabled with the same bit mask I used for secure world. I also noticed the difference in priority settings, however, since all my interrupts have the same priority, I didn't make any change to priority settings either.
However, the CPU is not seeing any interrupts that could be seen before, PPI or SPI. Did I miss something here?
BTW, one reason I need to make this work is because I need to jump to non-secure Linux at some point, so need to make sure the GIC is initialized properly for non-secure operations. It would be great if somebody could point me at something explains how to prepare the processor before jumping to a NS linux.
Thanks,
Zizhu
This could be a priority issue.
From the GICv2 Architecture Reference Manual (ARM IHI 0048B) §4.4.2 "Interrupt Priority Mask Register, GICC_PMR":
If a Secure write has programmed the GICC_PMR with a value that corresponds to a value in the upper half of the priority range then:Any Non-secure read of the GICC_PMR returns 0x00, regardless of the value held in the registerAny Non-secure write to the GICC_PMR is ignored.
If a Secure write has programmed the GICC_PMR with a value that corresponds to a value in the upper half of the priority range then:
Note: Higher priority corresponds to a lower Priority field value.
A similar effect occurs when programming the GICD_IPRIORITYR Priority field of an interrupt. From §3.5.1 "Software views of interrupt priority in a GIC that includes the Security Extensions":
The Non-secure view of a priority value does not show how the value is stored in the Distributor. Taking the value from a Non-secure write to a priority field, before storing the value:• The value is right-shifted by one bit• Bit [7] of the value is set to 1.
The Non-secure view of a priority value does not show how the value is stored in the Distributor. Taking the value from a Non-secure write to a priority field, before storing the value:
• The value is right-shifted by one bit
• Bit [7] of the value is set to 1.
In other words the Non-secure world can only program interrupts to have a priority in the bottom half of the priority range (0x80-0xFF), and similarly can only program GICC_PMR if the Secure world has already written a value to it in the range [0x80..0xFF] inclusive.
The end result of this is that if you haven't programmed GICC_PMR to a low enough priority value while still in the Secure world, the Non-secure world cannot program interrupts to have a higher priority than GICC_PMR, which means all of your interrupts will be masked out i.e. they will not be signalled to the processor.
As a simple test, before leaving the Secure world please can you try writing 0xFF to GICC_PMR on each CPU that will be attempting to handle interrupts in the Non-secure world and see if that works?
Hope that helps,
Ash.