]> xenbits.xensource.com Git - people/sstabellini/xen-unstable.git/.git/commitdiff
cpu: sync any remaining RCU callbacks before CPU up/down
authorIgor Druzhinin <igor.druzhinin@citrix.com>
Thu, 26 Mar 2020 11:49:42 +0000 (12:49 +0100)
committerJan Beulich <jbeulich@suse.com>
Thu, 26 Mar 2020 11:49:42 +0000 (12:49 +0100)
During CPU down operation RCU callbacks are scheduled to finish
off some actions later as soon as CPU is fully dead (the same applies
to CPU up operation in case error path is taken). If in the same grace
period another CPU up operation is performed on the same CPU, RCU callback
will be called later on a CPU in a potentially wrong (already up again
instead of still being down) state leading to eventual state inconsistency
and/or crash.

In order to avoid it - flush RCU callbacks explicitly before starting the
next CPU up/down operation.

Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/acpi/power.c
xen/arch/x86/sysctl.c
xen/common/cpu.c

index e3d6eefe6590925e38d19769e984f100a00a43fc..3ad7dfc9a3cceac0c8f4265dcb4b00183e467301 100644 (file)
@@ -306,7 +306,6 @@ static int enter_state(u32 state)
     cpufreq_add_cpu(0);
 
  enable_cpu:
-    rcu_barrier();
     mtrr_aps_sync_begin();
     enable_nonboot_cpus();
     mtrr_aps_sync_end();
index a95923e591eab4e61d0490acbca714b44c655fac..b0cb1b57e79960f20b63185a06a48b4fc46e4d9b 100644 (file)
@@ -84,12 +84,9 @@ long cpu_up_helper(void *data)
     unsigned int cpu = (unsigned long)data;
     int ret = cpu_up(cpu);
 
+    /* Have one more go on EBUSY. */
     if ( ret == -EBUSY )
-    {
-        /* On EBUSY, flush RCU work and have one more go. */
-        rcu_barrier();
         ret = cpu_up(cpu);
-    }
 
     if ( !ret && !opt_smt &&
          cpu_data[cpu].compute_unit_id == INVALID_CUID &&
@@ -109,12 +106,9 @@ long cpu_down_helper(void *data)
 {
     int cpu = (unsigned long)data;
     int ret = cpu_down(cpu);
+    /* Have one more go on EBUSY. */
     if ( ret == -EBUSY )
-    {
-        /* On EBUSY, flush RCU work and have one more go. */
-        rcu_barrier();
         ret = cpu_down(cpu);
-    }
     return ret;
 }
 
index 31953f32e4fdf1879890d7cb6b0a167fdd7be205..1f976db0a51f0fb6d6650ba8ce708f8f525422d1 100644 (file)
@@ -4,6 +4,7 @@
 #include <xen/init.h>
 #include <xen/sched.h>
 #include <xen/stop_machine.h>
+#include <xen/rcupdate.h>
 
 unsigned int __read_mostly nr_cpu_ids = NR_CPUS;
 #ifndef nr_cpumask_bits
@@ -53,6 +54,7 @@ void put_cpu_maps(void)
 
 void cpu_hotplug_begin(void)
 {
+    rcu_barrier();
     write_lock(&cpu_add_remove_lock);
 }