x86 mtrr: Fix set_mtrr() race against cpu_online_map changes.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
This commit is contained in:
Keir Fraser committed 2010-06-01 10:40:06 +01:00
1 parent 1f60b34911
commit 01c02ad2a8
1 file changed
+14 -11
+14 -11
View File
@@ -229,29 +229,32 @@ static inline int types_compatible(mtrr_type type1, mtrr_type type2) {
static void set_mtrr(unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type)
{
cpumask_t allbutself;
unsigned int nr_cpus;
struct set_mtrr_data data;
unsigned long flags;
allbutself = cpu_online_map;
cpu_clear(smp_processor_id(), allbutself);
nr_cpus = cpus_weight(allbutself);
data.smp_reg = reg;
data.smp_base = base;
data.smp_size = size;
data.smp_type = type;
atomic_set(&data.count, num_online_cpus() - 1);
/* make sure data.count is visible before unleashing other CPUs */
smp_wmb();
atomic_set(&data.count, nr_cpus);
atomic_set(&data.gate,0);
/* Start the ball rolling on other CPUs */
if (smp_call_function(ipi_handler, &data, 0) != 0)
panic("mtrr: timed out waiting for other CPUs\n");
/* Start the ball rolling on other CPUs */
on_selected_cpus(&allbutself, ipi_handler, &data, 0);
local_irq_save(flags);
while(atomic_read(&data.count))
while (atomic_read(&data.count))
cpu_relax();
/* ok, reset count and toggle gate */
atomic_set(&data.count, num_online_cpus() - 1);
atomic_set(&data.count, nr_cpus);
smp_wmb();
atomic_set(&data.gate,1);
@@ -271,10 +274,10 @@ static void set_mtrr(unsigned int reg, unsigned long base,
mtrr_if->set(reg,base,size,type);
/* wait for the others */
while(atomic_read(&data.count))
while (atomic_read(&data.count))
cpu_relax();
atomic_set(&data.count, num_online_cpus() - 1);
atomic_set(&data.count, nr_cpus);
smp_wmb();
atomic_set(&data.gate,0);
@@ -282,7 +285,7 @@ static void set_mtrr(unsigned int reg, unsigned long base,
* Wait here for everyone to have seen the gate change
* So we're the last ones to touch 'data'
*/
while(atomic_read(&data.count))
while (atomic_read(&data.count))
cpu_relax();
local_irq_restore(flags);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.