Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Follow locore.S and move FPU handling from x86_64_s...



details:   https://anonhg.NetBSD.org/src/rev/26494a766541
branches:  trunk
changeset: 777732:26494a766541
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Fri Mar 02 16:43:30 2012 +0000

description:
Follow locore.S and move FPU handling from x86_64_switch_context() to
x86_64_tls_switch(); raise IPL to IPL_HIGH in x86_64_switch_context()
and test ci_fpcurlwp to decide to disable FPU or not.
Change the Xen i386 context switch code to be like the amd64 one.

diffstat:

 sys/arch/amd64/amd64/machdep.c |  66 +++++++++++++++++++++++------------------
 sys/arch/i386/i386/locore.S    |  18 +++++++---
 sys/arch/i386/i386/machdep.c   |  41 ++++++++++++++++++++-----
 sys/arch/x86/include/cpu.h     |   3 +-
 4 files changed, 82 insertions(+), 46 deletions(-)

diffs (271 lines):

diff -r 22f2a2914aad -r 26494a766541 sys/arch/amd64/amd64/machdep.c
--- a/sys/arch/amd64/amd64/machdep.c    Fri Mar 02 16:41:00 2012 +0000
+++ b/sys/arch/amd64/amd64/machdep.c    Fri Mar 02 16:43:30 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.178 2012/02/23 14:45:54 chs Exp $        */
+/*     $NetBSD: machdep.c,v 1.179 2012/03/02 16:43:30 bouyer Exp $     */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -111,7 +111,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.178 2012/02/23 14:45:54 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.179 2012/03/02 16:43:30 bouyer Exp $");
 
 /* #define XENDEBUG_LOW  */
 
@@ -407,23 +407,53 @@
 void hypervisor_callback(void);
 void failsafe_callback(void);
 void x86_64_switch_context(struct pcb *);
+void x86_64_tls_switch(struct lwp *);
 
 void
 x86_64_switch_context(struct pcb *new)
 {
-       struct cpu_info *ci;
-       ci = curcpu();
        HYPERVISOR_stack_switch(GSEL(GDATA_SEL, SEL_KPL), new->pcb_rsp0);
        struct physdev_op physop;
        physop.cmd = PHYSDEVOP_SET_IOPL;
        physop.u.set_iopl.iopl = new->pcb_iopl;
        HYPERVISOR_physdev_op(&physop);
-       if (new->pcb_fpcpu != ci) {
+}
+
+void
+x86_64_tls_switch(struct lwp *l)
+{
+       struct cpu_info *ci = curcpu();
+       struct pcb *pcb = lwp_getpcb(l);
+       struct trapframe *tf = l->l_md.md_regs;
+
+       /*
+        * Raise the IPL to IPL_HIGH.
+        * FPU IPIs can alter the LWP's saved cr0.  Dropping the priority
+        * is deferred until mi_switch(), when cpu_switchto() returns.
+        */
+       (void)splhigh();
+       /*
+        * If our floating point registers are on a different CPU,
+        * set CR0_TS so we'll trap rather than reuse bogus state.
+        */
+       if (l != ci->ci_fpcurlwp) {
                HYPERVISOR_fpu_taskswitch(1);
        }
+
+       /* Update TLS segment pointers */
+       if (pcb->pcb_flags & PCB_COMPAT32) {
+               update_descriptor(&curcpu()->ci_gdt[GUFS_SEL], &pcb->pcb_fs);
+               update_descriptor(&curcpu()->ci_gdt[GUGS_SEL], &pcb->pcb_gs);
+               setfs(tf->tf_fs);
+               HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, tf->tf_gs);
+       } else {
+               setfs(0);
+               HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, 0);
+               HYPERVISOR_set_segment_base(SEGBASE_FS, pcb->pcb_fs);
+               HYPERVISOR_set_segment_base(SEGBASE_GS_USER, pcb->pcb_gs);
+       }
 }
-
-#endif
+#endif /* XEN */
 
 /*
  * Set up proc0's TSS and LDT.
@@ -2257,28 +2287,6 @@
        }
 }
 
-#ifdef XEN
-void x86_64_tls_switch(struct lwp *);
-
-void
-x86_64_tls_switch(struct lwp *l)
-{
-       struct pcb *pcb = lwp_getpcb(l);
-       struct trapframe *tf = l->l_md.md_regs;
-
-       if (pcb->pcb_flags & PCB_COMPAT32) {
-               update_descriptor(&curcpu()->ci_gdt[GUFS_SEL], &pcb->pcb_fs);
-               update_descriptor(&curcpu()->ci_gdt[GUGS_SEL], &pcb->pcb_gs);
-               setfs(tf->tf_fs);
-               HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, tf->tf_gs);
-       } else {
-               setfs(0);
-               HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, 0);
-               HYPERVISOR_set_segment_base(SEGBASE_FS, pcb->pcb_fs);
-               HYPERVISOR_set_segment_base(SEGBASE_GS_USER, pcb->pcb_gs);
-       }
-}
-#endif
 
 #ifdef __HAVE_DIRECT_MAP
 bool
diff -r 22f2a2914aad -r 26494a766541 sys/arch/i386/i386/locore.S
--- a/sys/arch/i386/i386/locore.S       Fri Mar 02 16:41:00 2012 +0000
+++ b/sys/arch/i386/i386/locore.S       Fri Mar 02 16:43:30 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.S,v 1.96 2012/02/24 08:06:07 cherry Exp $       */
+/*     $NetBSD: locore.S,v 1.97 2012/03/02 16:43:31 bouyer Exp $       */
 
 /*
  * Copyright-o-rama!
@@ -129,7 +129,7 @@
  */
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.96 2012/02/24 08:06:07 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.97 2012/03/02 16:43:31 bouyer Exp $");
 
 #include "opt_compat_oldboot.h"
 #include "opt_ddb.h"
@@ -1013,15 +1013,17 @@
        pushl   %edi
        call    _C_LABEL(i386_switch_context)
        addl    $4,%esp
-#else /* XEN */
+#else /* !XEN */
        /* Switch ring0 esp */
        movl    PCB_ESP0(%ebx),%eax
        movl    %eax,CPUVAR(ESP0)
+#endif /* !XEN */
 
        /* Don't bother with the rest if switching to a system process. */
        testl   $LW_SYSTEM,L_FLAG(%edi)
        jnz     4f
 
+#ifndef XEN
        /* Restore thread-private %fs/%gs descriptors. */
        movl    CPUVAR(GDT),%ecx
        movl    PCB_FSD(%ebx), %eax
@@ -1032,7 +1034,7 @@
        movl    PCB_GSD+4(%ebx), %edx
        movl    %eax, (GUGS_SEL*8)(%ecx)
        movl    %edx, (GUGS_SEL*8+4)(%ecx)
-#endif /* XEN */
+#endif /* !XEN */
 
        /* Switch I/O bitmap */
        movl    PCB_IOMAP(%ebx),%eax
@@ -1052,7 +1054,11 @@
         * is deferred until mi_switch(), when cpu_switchto() returns.
         */
 2:
-#ifndef XEN
+#ifdef XEN
+       pushl   %edi
+       call    _C_LABEL(i386_tls_switch)
+       addl    $4,%esp
+#else /* !XEN */
        movl    $IPL_HIGH,CPUVAR(ILEVEL)
        movl    PCB_CR0(%ebx),%ecx              /* has CR0_TS clear */
        movl    %cr0,%edx
@@ -1069,7 +1075,7 @@
 3:     cmpl    %edx,%ecx
        je      4f
        movl    %ecx,%cr0
-#endif /* XEN */
+#endif /* !XEN */
 
        /* Return to the new LWP, returning 'oldlwp' in %eax. */
 4:     movl    %esi,%eax
diff -r 22f2a2914aad -r 26494a766541 sys/arch/i386/i386/machdep.c
--- a/sys/arch/i386/i386/machdep.c      Fri Mar 02 16:41:00 2012 +0000
+++ b/sys/arch/i386/i386/machdep.c      Fri Mar 02 16:43:30 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.722 2012/02/27 19:52:59 bouyer Exp $     */
+/*     $NetBSD: machdep.c,v 1.723 2012/03/02 16:43:31 bouyer Exp $     */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.722 2012/02/27 19:52:59 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.723 2012/03/02 16:43:31 bouyer Exp $");
 
 #include "opt_beep.h"
 #include "opt_compat_ibcs2.h"
@@ -525,9 +525,12 @@
 }
 
 #ifdef XEN
+/* used in assembly */
+void i386_switch_context(lwp_t *);
+void i386_tls_switch(lwp_t *);
+
 /*
  * Switch context:
- * - honor CR0_TS in saved CR0 and request DNA exception on FPU use
  * - switch stack pointer for user->kernel transition
  */
 void
@@ -539,21 +542,41 @@
 
        pcb = lwp_getpcb(l);
        ci = curcpu();
-       if (pcb->pcb_fpcpu != ci) {
+
+       HYPERVISOR_stack_switch(GSEL(GDATA_SEL, SEL_KPL), pcb->pcb_esp0);
+
+       physop.cmd = PHYSDEVOP_SET_IOPL;
+       physop.u.set_iopl.iopl = pcb->pcb_iopl;
+       HYPERVISOR_physdev_op(&physop);
+}
+
+void
+i386_tls_switch(lwp_t *l)
+{
+       struct cpu_info *ci = curcpu();
+       struct pcb *pcb = lwp_getpcb(l);
+       /*
+         * Raise the IPL to IPL_HIGH.
+        * FPU IPIs can alter the LWP's saved cr0.  Dropping the priority
+        * is deferred until mi_switch(), when cpu_switchto() returns.
+        */
+       (void)splhigh();
+
+        /*
+        * If our floating point registers are on a different CPU,
+        * set CR0_TS so we'll trap rather than reuse bogus state.
+        */
+
+       if (l != ci->ci_fpcurlwp) {
                HYPERVISOR_fpu_taskswitch(1);
        }
 
-       HYPERVISOR_stack_switch(GSEL(GDATA_SEL, SEL_KPL), pcb->pcb_esp0);
-
        /* Update TLS segment pointers */
        update_descriptor(&ci->ci_gdt[GUFS_SEL],
                          (union descriptor *) &pcb->pcb_fsd);
        update_descriptor(&ci->ci_gdt[GUGS_SEL], 
                          (union descriptor *) &pcb->pcb_gsd);
 
-       physop.cmd = PHYSDEVOP_SET_IOPL;
-       physop.u.set_iopl.iopl = pcb->pcb_iopl;
-       HYPERVISOR_physdev_op(&physop);
 }
 #endif /* XEN */
 
diff -r 22f2a2914aad -r 26494a766541 sys/arch/x86/include/cpu.h
--- a/sys/arch/x86/include/cpu.h        Fri Mar 02 16:41:00 2012 +0000
+++ b/sys/arch/x86/include/cpu.h        Fri Mar 02 16:43:30 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cpu.h,v 1.48 2012/02/17 18:40:18 bouyer Exp $  */
+/*     $NetBSD: cpu.h,v 1.49 2012/03/02 16:43:31 bouyer Exp $  */
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -404,7 +404,6 @@
 void   lgdt(struct region_descriptor *);
 #ifdef XEN
 void   lgdt_finish(void);
-void   i386_switch_context(lwp_t *);
 #endif
 
 struct pcb;



Home | Main Index | Thread Index | Old Index