From 5febe8f5748ea5923d6465791c344a3a6138dee4 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Fri, 2 Oct 2009 15:53:17 -0700 Subject: [PATCH] vkernel - Fix FP corruption from preemptive thread switch * Recent work on the vkernel enabled preemptive interrupt thread switching. This introduced a race where the floating point state could change out from under the vkernel's go_user() function, causing the FP state in the virtual user process to become corrupt. * Fixed by introducing a critical section which essentially defers any preemptive thread switches inside go_user(). Reported-by: YONETANI Tomokazu Test-cases-by: YONETANI Tomokazu --- sys/platform/vkernel/i386/trap.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sys/platform/vkernel/i386/trap.c b/sys/platform/vkernel/i386/trap.c index e90fedc608..edbb75a332 100644 --- a/sys/platform/vkernel/i386/trap.c +++ b/sys/platform/vkernel/i386/trap.c @@ -1425,7 +1425,12 @@ go_user(struct intrframe *frame) /* * Tell the real kernel whether it is ok to use the FP * unit or not. + * + * The critical section is required to prevent an interrupt + * from causing a preemptive task switch and changing + * the FP state. */ + crit_enter(); if (mdcpu->gd_npxthread == curthread) { tf->tf_xflags &= ~PGEX_FPFAULT; } else { @@ -1441,6 +1446,7 @@ go_user(struct intrframe *frame) */ r = vmspace_ctl(&curproc->p_vmspace->vm_pmap, VMSPACE_CTL_RUN, tf, &curthread->td_savevext); + crit_exit(); frame->if_xflags |= PGEX_U; #if 0 kprintf("GO USER %d trap %d EVA %08x EIP %08x ESP %08x XFLAGS %02x/%02x\n", -- 2.11.4.GIT