Doorbell can be used to cause ipi on cpus which are sibling threads on
the same core. So icp_native_cause_ipi checks if the destination cpu
is a sibling thread of the current cpu and uses doorbell in such cases.

But while running with CONFIG_PREEMPT=y, since this section is
preemtible, we can run into issues if after we check if the destination
cpu is a sibling cpu, the task gets migrated from a sibling cpu to a
cpu on another core.

Fix this by using get_cpu()/ put_cpu()

Signed-off-by: Shreyas B. Prabhu <[email protected]>
---
 arch/powerpc/sysdev/xics/icp-native.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/sysdev/xics/icp-native.c 
b/arch/powerpc/sysdev/xics/icp-native.c
index 2fc4cf1..62fd478 100644
--- a/arch/powerpc/sysdev/xics/icp-native.c
+++ b/arch/powerpc/sysdev/xics/icp-native.c
@@ -147,12 +147,16 @@ static void icp_native_cause_ipi(int cpu, unsigned long 
data)
 {
        kvmppc_set_host_ipi(cpu, 1);
 #ifdef CONFIG_PPC_DOORBELL
-       if (cpu_has_feature(CPU_FTR_DBELL) &&
-           (cpumask_test_cpu(cpu, cpu_sibling_mask(smp_processor_id()))))
-               doorbell_cause_ipi(cpu, data);
-       else
+       if (cpu_has_feature(CPU_FTR_DBELL)) {
+               if (cpumask_test_cpu(cpu, cpu_sibling_mask(get_cpu()))) {
+                       doorbell_cause_ipi(cpu, data);
+                       put_cpu();
+                       return;
+               }
+               put_cpu();
+       }
 #endif
-               icp_native_set_qirr(cpu, IPI_PRIORITY);
+       icp_native_set_qirr(cpu, IPI_PRIORITY);
 }
 
 /*
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to