Skip to content

Commit d447bf0

Browse files
mrutland-armctmarinas
authored andcommitted
irqchip/gic-v3: Detect GICD_CTRL.DS and SCR_EL3.FIQ earlier
In subsequent patches the GICv3 driver will choose the regular interrupt priority at boot time, dependent on the configuration of GICD_CTRL.DS and SCR_EL3.FIQ. This will need to be chosen before we configure the distributor with default prioirities for all the interrupts, which happens before we currently detect these in gic_cpu_sys_reg_init(). Add a new gic_prio_init() function to detect these earlier and log them to the console so that any problems can be debugged more easily. This also allows the uniformity checks in gic_cpu_sys_reg_init() to be simplified, as we can compare directly with the boot CPU values which were recorded earlier. Signed-off-by: Mark Rutland <[email protected]> Cc: Alexandru Elisei <[email protected]> Cc: Marc Zyngier <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Will Deacon <[email protected]> Reviewed-by: Marc Zyngier <[email protected]> Tested-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]> Acked-by: Thomas Gleixner <[email protected]>
1 parent a6156e7 commit d447bf0

File tree

1 file changed

+63
-54
lines changed

1 file changed

+63
-54
lines changed

drivers/irqchip/irq-gic-v3.c

Lines changed: 63 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,62 @@ EXPORT_SYMBOL(gic_nonsecure_priorities);
134134
__priority; \
135135
})
136136

137+
static u32 gic_get_pribits(void)
138+
{
139+
u32 pribits;
140+
141+
pribits = gic_read_ctlr();
142+
pribits &= ICC_CTLR_EL1_PRI_BITS_MASK;
143+
pribits >>= ICC_CTLR_EL1_PRI_BITS_SHIFT;
144+
pribits++;
145+
146+
return pribits;
147+
}
148+
149+
static bool gic_has_group0(void)
150+
{
151+
u32 val;
152+
u32 old_pmr;
153+
154+
old_pmr = gic_read_pmr();
155+
156+
/*
157+
* Let's find out if Group0 is under control of EL3 or not by
158+
* setting the highest possible, non-zero priority in PMR.
159+
*
160+
* If SCR_EL3.FIQ is set, the priority gets shifted down in
161+
* order for the CPU interface to set bit 7, and keep the
162+
* actual priority in the non-secure range. In the process, it
163+
* looses the least significant bit and the actual priority
164+
* becomes 0x80. Reading it back returns 0, indicating that
165+
* we're don't have access to Group0.
166+
*/
167+
gic_write_pmr(BIT(8 - gic_get_pribits()));
168+
val = gic_read_pmr();
169+
170+
gic_write_pmr(old_pmr);
171+
172+
return val != 0;
173+
}
174+
175+
static inline bool gic_dist_security_disabled(void)
176+
{
177+
return readl_relaxed(gic_data.dist_base + GICD_CTLR) & GICD_CTLR_DS;
178+
}
179+
180+
static bool cpus_have_security_disabled __ro_after_init;
181+
static bool cpus_have_group0 __ro_after_init;
182+
183+
static void __init gic_prio_init(void)
184+
{
185+
cpus_have_security_disabled = gic_dist_security_disabled();
186+
cpus_have_group0 = gic_has_group0();
187+
188+
pr_info("GICD_CTRL.DS=%d, SCR_EL3.FIQ=%d\n",
189+
cpus_have_security_disabled,
190+
!cpus_have_group0);
191+
}
192+
137193
/* rdist_nmi_refs[n] == number of cpus having the rdist interrupt n set as NMI */
138194
static refcount_t *rdist_nmi_refs;
139195

@@ -868,44 +924,6 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
868924
__gic_handle_irq_from_irqson(regs);
869925
}
870926

871-
static u32 gic_get_pribits(void)
872-
{
873-
u32 pribits;
874-
875-
pribits = gic_read_ctlr();
876-
pribits &= ICC_CTLR_EL1_PRI_BITS_MASK;
877-
pribits >>= ICC_CTLR_EL1_PRI_BITS_SHIFT;
878-
pribits++;
879-
880-
return pribits;
881-
}
882-
883-
static bool gic_has_group0(void)
884-
{
885-
u32 val;
886-
u32 old_pmr;
887-
888-
old_pmr = gic_read_pmr();
889-
890-
/*
891-
* Let's find out if Group0 is under control of EL3 or not by
892-
* setting the highest possible, non-zero priority in PMR.
893-
*
894-
* If SCR_EL3.FIQ is set, the priority gets shifted down in
895-
* order for the CPU interface to set bit 7, and keep the
896-
* actual priority in the non-secure range. In the process, it
897-
* looses the least significant bit and the actual priority
898-
* becomes 0x80. Reading it back returns 0, indicating that
899-
* we're don't have access to Group0.
900-
*/
901-
gic_write_pmr(BIT(8 - gic_get_pribits()));
902-
val = gic_read_pmr();
903-
904-
gic_write_pmr(old_pmr);
905-
906-
return val != 0;
907-
}
908-
909927
static void __init gic_dist_init(void)
910928
{
911929
unsigned int i;
@@ -1122,12 +1140,6 @@ static void gic_update_rdist_properties(void)
11221140
gic_data.rdists.has_vpend_valid_dirty ? "Valid+Dirty " : "");
11231141
}
11241142

1125-
/* Check whether it's single security state view */
1126-
static inline bool gic_dist_security_disabled(void)
1127-
{
1128-
return readl_relaxed(gic_data.dist_base + GICD_CTLR) & GICD_CTLR_DS;
1129-
}
1130-
11311143
static void gic_cpu_sys_reg_init(void)
11321144
{
11331145
int i, cpu = smp_processor_id();
@@ -1155,18 +1167,14 @@ static void gic_cpu_sys_reg_init(void)
11551167
write_gicreg(DEFAULT_PMR_VALUE, ICC_PMR_EL1);
11561168
} else if (gic_supports_nmi()) {
11571169
/*
1158-
* Mismatch configuration with boot CPU, the system is likely
1159-
* to die as interrupt masking will not work properly on all
1160-
* CPUs
1170+
* Check that all CPUs use the same priority space.
11611171
*
1162-
* The boot CPU calls this function before enabling NMI support,
1163-
* and as a result we'll never see this warning in the boot path
1164-
* for that CPU.
1172+
* If there's a mismatch with the boot CPU, the system is
1173+
* likely to die as interrupt masking will not work properly on
1174+
* all CPUs.
11651175
*/
1166-
if (static_branch_unlikely(&gic_nonsecure_priorities))
1167-
WARN_ON(!group0 || gic_dist_security_disabled());
1168-
else
1169-
WARN_ON(group0 && !gic_dist_security_disabled());
1176+
WARN_ON(group0 != cpus_have_group0);
1177+
WARN_ON(gic_dist_security_disabled() != cpus_have_security_disabled);
11701178
}
11711179

11721180
/*
@@ -2062,6 +2070,7 @@ static int __init gic_init_bases(phys_addr_t dist_phys_base,
20622070

20632071
gic_update_rdist_properties();
20642072

2073+
gic_prio_init();
20652074
gic_dist_init();
20662075
gic_cpu_init();
20672076
gic_enable_nmi_support();

0 commit comments

Comments
 (0)