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

GICv2 initialization for Non-Secure World

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

Parents
  • 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 register
    • Any Non-secure write to the GICC_PMR is ignored.

    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.

    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.

Reply
  • 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 register
    • Any Non-secure write to the GICC_PMR is ignored.

    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.

    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.

Children
No data