Commit b1979a5f authored by Ingo Molnar's avatar Ingo Molnar Committed by Thomas Gleixner

x86: prevent PGE flush from interruption/preemption

CR4 manipulation is not protected against interrupts and preemption,
but KVM uses smp_function_call to manipulate the X86_CR4_VMXE bit
either from the CPU hotplug code or from the kvm_init call.

We need to protect the CR4 manipulation from both interrupts and
preemption.

Original bug report: http://lkml.org/lkml/2008/5/7/48
Bugzilla entry: http://bugzilla.kernel.org/show_bug.cgi?id=10642

This is not a regression from 2.6.25, it's a long standing and hard to
trigger bug.
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent a1289643
...@@ -22,12 +22,23 @@ static inline void __native_flush_tlb(void) ...@@ -22,12 +22,23 @@ static inline void __native_flush_tlb(void)
static inline void __native_flush_tlb_global(void) static inline void __native_flush_tlb_global(void)
{ {
unsigned long cr4 = read_cr4(); unsigned long flags;
unsigned long cr4;
/*
* Read-modify-write to CR4 - protect it from preemption and
* from interrupts. (Use the raw variant because this code can
* be called from deep inside debugging code.)
*/
raw_local_irq_save(flags);
cr4 = read_cr4();
/* clear PGE */ /* clear PGE */
write_cr4(cr4 & ~X86_CR4_PGE); write_cr4(cr4 & ~X86_CR4_PGE);
/* write old PGE again and flush TLBs */ /* write old PGE again and flush TLBs */
write_cr4(cr4); write_cr4(cr4);
raw_local_irq_restore(flags);
} }
static inline void __native_flush_tlb_single(unsigned long addr) static inline void __native_flush_tlb_single(unsigned long addr)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment