From: Jan Beulich <jbeulich@xxxxxxxxxx> Touching of the floating point state in a kernel debugger must be NMI-safe, specifically math_state_restore() must be able to deal with being called out of an NMI context. In order to do that reliably, the context switch code must take care to not leave a window open where the current task's TS_USEDFPU flag and CR0.TS could get out of sync. Signed-Off-By: Jan Beulich <jbeulich@xxxxxxxxxx> Signed-off-by: Andi Kleen <ak@xxxxxxx> arch/x86_64/kernel/pmtimer.c | 3 ++- arch/x86_64/kernel/process.c | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) Index: linux/arch/x86_64/kernel/process.c =================================================================== --- linux.orig/arch/x86_64/kernel/process.c +++ linux/arch/x86_64/kernel/process.c @@ -527,8 +527,6 @@ __switch_to(struct task_struct *prev_p, int cpu = smp_processor_id(); struct tss_struct *tss = &per_cpu(init_tss, cpu); - unlazy_fpu(prev_p); - /* * Reload esp0, LDT and the page table pointer: */ @@ -586,11 +584,14 @@ __switch_to(struct task_struct *prev_p, } /* - * Switch the PDA context. + * Switch the PDA and FPU contexts. */ prev->userrsp = read_pda(oldrsp); write_pda(oldrsp, next->userrsp); write_pda(pcurrent, next_p); + /* This must be here to ensure both math_state_restore() and + kernel_fpu_begin() work consistently. */ + unlazy_fpu(prev_p); write_pda(kernelstack, task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); @@ -841,3 +842,13 @@ unsigned long arch_align_stack(unsigned sp -= get_random_int() % 8192; return sp & ~0xf; } + +unsigned long last_clier; + +void local_irq_disable(void) +{ + if (!irqs_disabled()) { + last_clier = __builtin_return_address(0); + asm volatile("cli":::"memory"); + } +} Index: linux/arch/x86_64/kernel/pmtimer.c =================================================================== --- linux.orig/arch/x86_64/kernel/pmtimer.c +++ linux/arch/x86_64/kernel/pmtimer.c @@ -86,7 +86,7 @@ static unsigned pmtimer_wait_tick(void) for (a = b = inl(pmtmr_ioport) & ACPI_PM_MASK; a == b; b = inl(pmtmr_ioport) & ACPI_PM_MASK) - ; + cpu_relax(); return b; } @@ -97,6 +97,7 @@ void pmtimer_wait(unsigned us) a = pmtimer_wait_tick(); do { b = inl(pmtmr_ioport); + cpu_relax(); } while (cyc2us(b - a) < us); } - : send the line "unsubscribe linux-x86_64" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html