Skip to content

Commit

Permalink
MTRR: Fix race causing set_mtrr to go into infinite loop
Browse files Browse the repository at this point in the history
Processors synchronization in set_mtrr requires the .gate field to be set
after .count field is properly initialized.  Without an explicit barrier,
the compiler was reordering those memory stores.  That was sometimes
causing a processor (in ipi_handler) to see the .gate change and decrement
.count before the latter is set by set_mtrr() (which then hangs in a
infinite loop with irqs disabled).

Signed-off-by: Loic Prylli <loic@myri.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Loic Prylli authored and Linus Torvalds committed Jul 6, 2007
1 parent 1e2e99f commit d25c1ba
Showing 1 changed file with 4 additions and 0 deletions.
4 changes: 4 additions & 0 deletions arch/i386/kernel/cpu/mtrr/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ static void set_mtrr(unsigned int reg, unsigned long base,
data.smp_size = size;
data.smp_type = type;
atomic_set(&data.count, num_booting_cpus() - 1);
/* make sure data.count is visible before unleashing other CPUs */
smp_wmb();
atomic_set(&data.gate,0);

/* Start the ball rolling on other CPUs */
Expand All @@ -242,6 +244,7 @@ static void set_mtrr(unsigned int reg, unsigned long base,

/* ok, reset count and toggle gate */
atomic_set(&data.count, num_booting_cpus() - 1);
smp_wmb();
atomic_set(&data.gate,1);

/* do our MTRR business */
Expand All @@ -260,6 +263,7 @@ static void set_mtrr(unsigned int reg, unsigned long base,
cpu_relax();

atomic_set(&data.count, num_booting_cpus() - 1);
smp_wmb();
atomic_set(&data.gate,0);

/*
Expand Down

0 comments on commit d25c1ba

Please sign in to comment.