Module Name:    src
Committed By:   bouyer
Date:           Fri Mar  2 16:43:31 UTC 2012

Modified Files:
        src/sys/arch/amd64/amd64: machdep.c
        src/sys/arch/i386/i386: locore.S machdep.c
        src/sys/arch/x86/include: cpu.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.178 -r1.179 src/sys/arch/amd64/amd64/machdep.c
cvs rdiff -u -r1.96 -r1.97 src/sys/arch/i386/i386/locore.S
cvs rdiff -u -r1.722 -r1.723 src/sys/arch/i386/i386/machdep.c
cvs rdiff -u -r1.48 -r1.49 src/sys/arch/x86/include/cpu.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/amd64/amd64/machdep.c
diff -u src/sys/arch/amd64/amd64/machdep.c:1.178 src/sys/arch/amd64/amd64/machdep.c:1.179
--- src/sys/arch/amd64/amd64/machdep.c:1.178	Thu Feb 23 14:45:54 2012
+++ src/sys/arch/amd64/amd64/machdep.c	Fri Mar  2 16:43:30 2012
@@ -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 @@ cpu_startup(void)
 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);
 	}
-}
 
-#endif
+	/* 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 /* XEN */
 
 /*
  * Set up proc0's TSS and LDT.
@@ -2257,28 +2287,6 @@ cpu_fsgs_reload(struct lwp *l, int fssel
 	}
 }
 
-#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

Index: src/sys/arch/i386/i386/locore.S
diff -u src/sys/arch/i386/i386/locore.S:1.96 src/sys/arch/i386/i386/locore.S:1.97
--- src/sys/arch/i386/i386/locore.S:1.96	Fri Feb 24 08:06:07 2012
+++ src/sys/arch/i386/i386/locore.S	Fri Mar  2 16:43:31 2012
@@ -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 @@ ENTRY(cpu_switchto)
 	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 @@ ENTRY(cpu_switchto)
 	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 @@ ENTRY(cpu_switchto)
 	 * 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 @@ ENTRY(cpu_switchto)
 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

Index: src/sys/arch/i386/i386/machdep.c
diff -u src/sys/arch/i386/i386/machdep.c:1.722 src/sys/arch/i386/i386/machdep.c:1.723
--- src/sys/arch/i386/i386/machdep.c:1.722	Mon Feb 27 19:52:59 2012
+++ src/sys/arch/i386/i386/machdep.c	Fri Mar  2 16:43:31 2012
@@ -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 @@ i386_proc0_tss_ldt_init(void)
 }
 
 #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 @@ i386_switch_context(lwp_t *l)
 
 	pcb = lwp_getpcb(l);
 	ci = curcpu();
-	if (pcb->pcb_fpcpu != ci) {
-		HYPERVISOR_fpu_taskswitch(1);
-	}
 
 	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);
+	}
+
 	/* 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 */
 

Index: src/sys/arch/x86/include/cpu.h
diff -u src/sys/arch/x86/include/cpu.h:1.48 src/sys/arch/x86/include/cpu.h:1.49
--- src/sys/arch/x86/include/cpu.h:1.48	Fri Feb 17 18:40:18 2012
+++ src/sys/arch/x86/include/cpu.h	Fri Mar  2 16:43:31 2012
@@ -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 @@ struct region_descriptor;
 void	lgdt(struct region_descriptor *);
 #ifdef XEN
 void	lgdt_finish(void);
-void	i386_switch_context(lwp_t *);
 #endif
 
 struct pcb;

Reply via email to