aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-10-20 06:22:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-10-20 06:22:25 -0400
commit589f1222e043ab1f5cbce558cfaed0c0fa76e7bb (patch)
tree0e054ea811a6bd5ff40854a352abe1b6eba0c1ab /kernel
parent531e93d11470aa2e14e6a3febef50d9bc7bab7a1 (diff)
parentb1fc5833357524d5d342737913dbe32ff3557bc5 (diff)
Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull stop-machine fix from Thomas Gleixner: "A single fix, amending stop machine with WRITE/READ_ONCE() to address the fallout of KCSAN" * 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: stop_machine: Avoid potential race behaviour
Diffstat (limited to 'kernel')
-rw-r--r--kernel/stop_machine.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index c7031a22aa7b..998d50ee2d9b 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -7,6 +7,7 @@
7 * Copyright (C) 2010 SUSE Linux Products GmbH 7 * Copyright (C) 2010 SUSE Linux Products GmbH
8 * Copyright (C) 2010 Tejun Heo <tj@kernel.org> 8 * Copyright (C) 2010 Tejun Heo <tj@kernel.org>
9 */ 9 */
10#include <linux/compiler.h>
10#include <linux/completion.h> 11#include <linux/completion.h>
11#include <linux/cpu.h> 12#include <linux/cpu.h>
12#include <linux/init.h> 13#include <linux/init.h>
@@ -167,7 +168,7 @@ static void set_state(struct multi_stop_data *msdata,
167 /* Reset ack counter. */ 168 /* Reset ack counter. */
168 atomic_set(&msdata->thread_ack, msdata->num_threads); 169 atomic_set(&msdata->thread_ack, msdata->num_threads);
169 smp_wmb(); 170 smp_wmb();
170 msdata->state = newstate; 171 WRITE_ONCE(msdata->state, newstate);
171} 172}
172 173
173/* Last one to ack a state moves to the next state. */ 174/* Last one to ack a state moves to the next state. */
@@ -186,7 +187,7 @@ void __weak stop_machine_yield(const struct cpumask *cpumask)
186static int multi_cpu_stop(void *data) 187static int multi_cpu_stop(void *data)
187{ 188{
188 struct multi_stop_data *msdata = data; 189 struct multi_stop_data *msdata = data;
189 enum multi_stop_state curstate = MULTI_STOP_NONE; 190 enum multi_stop_state newstate, curstate = MULTI_STOP_NONE;
190 int cpu = smp_processor_id(), err = 0; 191 int cpu = smp_processor_id(), err = 0;
191 const struct cpumask *cpumask; 192 const struct cpumask *cpumask;
192 unsigned long flags; 193 unsigned long flags;
@@ -210,8 +211,9 @@ static int multi_cpu_stop(void *data)
210 do { 211 do {
211 /* Chill out and ensure we re-read multi_stop_state. */ 212 /* Chill out and ensure we re-read multi_stop_state. */
212 stop_machine_yield(cpumask); 213 stop_machine_yield(cpumask);
213 if (msdata->state != curstate) { 214 newstate = READ_ONCE(msdata->state);
214 curstate = msdata->state; 215 if (newstate != curstate) {
216 curstate = newstate;
215 switch (curstate) { 217 switch (curstate) {
216 case MULTI_STOP_DISABLE_IRQ: 218 case MULTI_STOP_DISABLE_IRQ:
217 local_irq_disable(); 219 local_irq_disable();