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