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 <shre...@linux.vnet.ibm.com>
---
 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

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to