mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-18 02:24:18 +00:00
Set group status of PPIs and SGIs correctly on GICv3 systems
On a GICv2 system, the group status of PPIs and SGIs is set in the GICD_IGROUPR0 register. On a GICv3 system, if affinity routing is enabled for the non-secure state, then the group status of PPIs and SGIs should be set in the GICR_IGROUPR0 register. ARM Trusted firmware sets the group status using the GICv2 sequence. On a GICv3 system, if the group status of an interrupt is set to Group 1 through a write to the GICD_IGROUPR0, then the GICR_IGROUPR0 is updated as well. The current sequence is incorrect since it first marks all PPIs and SGIs as Group 1. It then clears the bits in GICD_IGROUPR0 corresponding to secure interrupts to set their group status to Group 0. This operation is a no-op. It leaves the secure generic timer interrupt (#29) used by the TSP marked as Group 1. This causes the interrupt to interfere with the execution of non-secure software. Once an interrupt has been marked as Group 1, the GICR_IGROUPR0 should be programmed to change its group status. This patch rectifies this issue by setting the group status of only the non-secure PPI and SGIs to Group 1 in the first place. GICD_IGROUPR0 resets to 0. So secure interrupts are marked as Group 0 by default. Change-Id: I958b4b15f3e2b2444ce4c17764def36216498d00
This commit is contained in:
parent
3b982be3b3
commit
8cfc3fd295
1 changed files with 12 additions and 6 deletions
|
@ -219,13 +219,10 @@ void arm_gic_cpuif_deactivate(void)
|
|||
******************************************************************************/
|
||||
void arm_gic_pcpu_distif_setup(void)
|
||||
{
|
||||
unsigned int index, irq_num;
|
||||
unsigned int index, irq_num, sec_ppi_sgi_mask;
|
||||
|
||||
assert(g_gicd_base);
|
||||
|
||||
/* Mark all 32 SGI+PPI interrupts as Group 1 (non-secure) */
|
||||
gicd_write_igroupr(g_gicd_base, 0, ~0);
|
||||
|
||||
/* Setup PPI priorities doing four at a time */
|
||||
for (index = 0; index < 32; index += 4) {
|
||||
gicd_write_ipriorityr(g_gicd_base, index,
|
||||
|
@ -233,16 +230,25 @@ void arm_gic_pcpu_distif_setup(void)
|
|||
}
|
||||
|
||||
assert(g_irq_sec_ptr);
|
||||
sec_ppi_sgi_mask = 0;
|
||||
for (index = 0; index < g_num_irqs; index++) {
|
||||
irq_num = g_irq_sec_ptr[index];
|
||||
if (irq_num < MIN_SPI_ID) {
|
||||
/* We have an SGI or a PPI */
|
||||
gicd_clr_igroupr(g_gicd_base, irq_num);
|
||||
/* We have an SGI or a PPI. They are Group0 at reset */
|
||||
sec_ppi_sgi_mask |= 1U << irq_num;
|
||||
gicd_set_ipriorityr(g_gicd_base, irq_num,
|
||||
GIC_HIGHEST_SEC_PRIORITY);
|
||||
gicd_set_isenabler(g_gicd_base, irq_num);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert the bitmask to create a mask for non-secure PPIs and
|
||||
* SGIs. Program the GICD_IGROUPR0 with this bit mask. This write will
|
||||
* update the GICR_IGROUPR0 as well in case we are running on a GICv3
|
||||
* system. This is critical if GICD_CTLR.ARE_NS=1.
|
||||
*/
|
||||
gicd_write_igroupr(g_gicd_base, 0, ~sec_ppi_sgi_mask);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
Loading…
Add table
Reference in a new issue