Skip to content

Commit 45b21cf

Browse files
committed
powerpc/powernv: Fix oops on P9 DD1 in cause_ipi()
Recently we merged the native xive support for Power9, and then separately some reworks for doorbell IPI support. In isolation both series were OK, but the merged result had a bug in one case. On P9 DD1 we use pnv_p9_dd1_cause_ipi() which tries to use doorbells, and then falls back to the interrupt controller. However the fallback is implemented by calling icp_ops->cause_ipi. But now that xive support is merged we might be using xive, in which case icp_ops is not initialised, it's a xics specific structure. This leads to an oops such as: Unable to handle kernel paging request for data at address 0x00000028 Oops: Kernel access of bad area, sig: 11 [#1] NIP pnv_p9_dd1_cause_ipi+0x74/0xe0 LR smp_muxed_ipi_message_pass+0x54/0x70 To fix it, rather than using icp_ops which might be NULL, have both xics and xive set smp_ops->cause_ipi, and then in the powernv code we save that as ic_cause_ipi before overriding smp_ops->cause_ipi. For paranoia add a WARN_ON() to check if somehow smp_ops->cause_ipi is NULL. Fixes: b866cc2 ("powerpc: Change the doorbell IPI calling convention") Tested-by: Gautham R. Shenoy <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 83c4919 commit 45b21cf

File tree

2 files changed

+11
-4
lines changed

2 files changed

+11
-4
lines changed

arch/powerpc/platforms/powernv/smp.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,12 +249,15 @@ static int pnv_smp_prepare_cpu(int cpu)
249249
return 0;
250250
}
251251

252+
/* Cause IPI as setup by the interrupt controller (xics or xive) */
253+
static void (*ic_cause_ipi)(int cpu);
254+
252255
static void pnv_cause_ipi(int cpu)
253256
{
254257
if (doorbell_try_core_ipi(cpu))
255258
return;
256259

257-
icp_ops->cause_ipi(cpu);
260+
ic_cause_ipi(cpu);
258261
}
259262

260263
static void pnv_p9_dd1_cause_ipi(int cpu)
@@ -269,7 +272,7 @@ static void pnv_p9_dd1_cause_ipi(int cpu)
269272
if (cpumask_test_cpu(cpu, cpu_sibling_mask(this_cpu)))
270273
doorbell_global_ipi(cpu);
271274
else
272-
icp_ops->cause_ipi(cpu);
275+
ic_cause_ipi(cpu);
273276

274277
put_cpu();
275278
}
@@ -282,6 +285,9 @@ static void __init pnv_smp_probe(void)
282285
xics_smp_probe();
283286

284287
if (cpu_has_feature(CPU_FTR_DBELL)) {
288+
ic_cause_ipi = smp_ops->cause_ipi;
289+
WARN_ON(!ic_cause_ipi);
290+
285291
if (cpu_has_feature(CPU_FTR_ARCH_300)) {
286292
if (cpu_has_feature(CPU_FTR_POWER9_DD1))
287293
smp_ops->cause_ipi = pnv_p9_dd1_cause_ipi;
@@ -290,8 +296,6 @@ static void __init pnv_smp_probe(void)
290296
} else {
291297
smp_ops->cause_ipi = pnv_cause_ipi;
292298
}
293-
} else {
294-
smp_ops->cause_ipi = icp_ops->cause_ipi;
295299
}
296300
}
297301

arch/powerpc/sysdev/xics/xics-common.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ void __init xics_smp_probe(void)
145145
{
146146
/* Register all the IPIs */
147147
xics_request_ipi();
148+
149+
/* Setup cause_ipi callback based on which ICP is used */
150+
smp_ops->cause_ipi = icp_ops->cause_ipi;
148151
}
149152

150153
#endif /* CONFIG_SMP */

0 commit comments

Comments
 (0)