Module Name: src Committed By: sborrill Date: Mon Mar 5 20:18:03 UTC 2012
Modified Files: src/sys/arch/amd64/amd64 [netbsd-6]: machdep.c src/sys/arch/i386/i386 [netbsd-6]: locore.S machdep.c src/sys/arch/x86/include [netbsd-6]: cpu.h specialreg.h src/sys/arch/xen/x86 [netbsd-6]: x86_xpmap.c Log Message: Pull up the following revisions(s) (requested by bouyer in ticket #80): sys/arch/xen/x86/x86_xpmap.c: revision 1.42 sys/arch/x86/include/specialreg.h: revision 1.56 sys/arch/amd64/amd64/machdep.c: revision 1.179 sys/arch/i386/i386/locore.S: revision 1.97 sys/arch/i386/i386/machdep.c: revision 1.723 via patch sys/arch/x86/include/cpu.h: revision 1.49 Fix possible FPU registers corruption on context switches. Fix type of pointers passed to some hypercalls. To generate a diff of this commit: cvs rdiff -u -r1.175.2.1 -r1.175.2.2 src/sys/arch/amd64/amd64/machdep.c cvs rdiff -u -r1.95 -r1.95.10.1 src/sys/arch/i386/i386/locore.S cvs rdiff -u -r1.717.2.3 -r1.717.2.4 src/sys/arch/i386/i386/machdep.c cvs rdiff -u -r1.47.2.1 -r1.47.2.2 src/sys/arch/x86/include/cpu.h cvs rdiff -u -r1.55 -r1.55.2.1 src/sys/arch/x86/include/specialreg.h cvs rdiff -u -r1.38.2.2 -r1.38.2.3 src/sys/arch/xen/x86/x86_xpmap.c 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.175.2.1 src/sys/arch/amd64/amd64/machdep.c:1.175.2.2 --- src/sys/arch/amd64/amd64/machdep.c:1.175.2.1 Thu Feb 23 18:37:12 2012 +++ src/sys/arch/amd64/amd64/machdep.c Mon Mar 5 20:18:01 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.175.2.1 2012/02/23 18:37:12 riz Exp $ */ +/* $NetBSD: machdep.c,v 1.175.2.2 2012/03/05 20:18:01 sborrill 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.175.2.1 2012/02/23 18:37:12 riz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.175.2.2 2012/03/05 20:18:01 sborrill Exp $"); /* #define XENDEBUG_LOW */ @@ -414,23 +414,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. @@ -2297,28 +2327,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.95 src/sys/arch/i386/i386/locore.S:1.95.10.1 --- src/sys/arch/i386/i386/locore.S:1.95 Fri Mar 18 15:18:16 2011 +++ src/sys/arch/i386/i386/locore.S Mon Mar 5 20:18:01 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: locore.S,v 1.95 2011/03/18 15:18:16 joerg Exp $ */ +/* $NetBSD: locore.S,v 1.95.10.1 2012/03/05 20:18:01 sborrill Exp $ */ /* * Copyright-o-rama! @@ -129,7 +129,7 @@ */ #include <machine/asm.h> -__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.95 2011/03/18 15:18:16 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.95.10.1 2012/03/05 20:18:01 sborrill Exp $"); #include "opt_compat_oldboot.h" #include "opt_ddb.h" @@ -999,15 +999,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 @@ -1018,7 +1020,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 @@ -1038,7 +1040,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 @@ -1055,7 +1061,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.717.2.3 src/sys/arch/i386/i386/machdep.c:1.717.2.4 --- src/sys/arch/i386/i386/machdep.c:1.717.2.3 Mon Feb 27 20:29:36 2012 +++ src/sys/arch/i386/i386/machdep.c Mon Mar 5 20:18:02 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.717.2.3 2012/02/27 20:29:36 riz Exp $ */ +/* $NetBSD: machdep.c,v 1.717.2.4 2012/03/05 20:18:02 sborrill 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.717.2.3 2012/02/27 20:29:36 riz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.717.2.4 2012/03/05 20:18:02 sborrill Exp $"); #include "opt_beep.h" #include "opt_compat_ibcs2.h" @@ -530,9 +530,12 @@ i386_proc0_tss_ldt_init(void) /* Shim for curcpu() until %fs is ready */ extern struct cpu_info * (*xpq_cpu)(void); +/* 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 @@ -544,12 +547,35 @@ 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); @@ -562,9 +588,6 @@ i386_switch_context(lwp_t *l) xpq_cpu = x86_curcpu; } - 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.47.2.1 src/sys/arch/x86/include/cpu.h:1.47.2.2 --- src/sys/arch/x86/include/cpu.h:1.47.2.1 Wed Feb 22 18:56:47 2012 +++ src/sys/arch/x86/include/cpu.h Mon Mar 5 20:18:02 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.47.2.1 2012/02/22 18:56:47 riz Exp $ */ +/* $NetBSD: cpu.h,v 1.47.2.2 2012/03/05 20:18:02 sborrill 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; Index: src/sys/arch/x86/include/specialreg.h diff -u src/sys/arch/x86/include/specialreg.h:1.55 src/sys/arch/x86/include/specialreg.h:1.55.2.1 --- src/sys/arch/x86/include/specialreg.h:1.55 Thu Dec 15 09:38:21 2011 +++ src/sys/arch/x86/include/specialreg.h Mon Mar 5 20:18:03 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: specialreg.h,v 1.55 2011/12/15 09:38:21 abs Exp $ */ +/* $NetBSD: specialreg.h,v 1.55.2.1 2012/03/05 20:18:03 sborrill Exp $ */ /*- * Copyright (c) 1991 The Regents of the University of California. @@ -307,7 +307,7 @@ /* Blacklists of CPUID flags - used to mask certain features */ #ifdef XEN /* Not on Xen */ -#define CPUID_FEAT_BLACKLIST (CPUID_PGE|CPUID_PSE|CPUID_MTRR|CPUID_FXSR) +#define CPUID_FEAT_BLACKLIST (CPUID_PGE|CPUID_PSE|CPUID_MTRR) #else #define CPUID_FEAT_BLACKLIST 0 #endif /* XEN */ Index: src/sys/arch/xen/x86/x86_xpmap.c diff -u src/sys/arch/xen/x86/x86_xpmap.c:1.38.2.2 src/sys/arch/xen/x86/x86_xpmap.c:1.38.2.3 --- src/sys/arch/xen/x86/x86_xpmap.c:1.38.2.2 Thu Feb 23 21:17:25 2012 +++ src/sys/arch/xen/x86/x86_xpmap.c Mon Mar 5 20:18:03 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: x86_xpmap.c,v 1.38.2.2 2012/02/23 21:17:25 riz Exp $ */ +/* $NetBSD: x86_xpmap.c,v 1.38.2.3 2012/03/05 20:18:03 sborrill Exp $ */ /* * Copyright (c) 2006 Mathieu Ropert <m...@adviseo.fr> @@ -69,7 +69,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: x86_xpmap.c,v 1.38.2.2 2012/02/23 21:17:25 riz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: x86_xpmap.c,v 1.38.2.3 2012/03/05 20:18:03 sborrill Exp $"); #include "opt_xen.h" #include "opt_ddb.h" @@ -78,10 +78,11 @@ __KERNEL_RCSID(0, "$NetBSD: x86_xpmap.c, #include <sys/param.h> #include <sys/systm.h> #include <sys/mutex.h> +#include <sys/cpu.h> #include <uvm/uvm.h> -#include <machine/pmap.h> +#include <x86/pmap.h> #include <machine/gdt.h> #include <xen/xenfunc.h> @@ -106,13 +107,6 @@ static char XBUF[256]; #define PRINTF(x) printf x #define PRINTK(x) printk x -/* on x86_64 kernel runs in ring 3 */ -#ifdef __x86_64__ -#define PG_k PG_u -#else -#define PG_k 0 -#endif - volatile shared_info_t *HYPERVISOR_shared_info; /* Xen requires the start_info struct to be page aligned */ union start_info_union start_info_union __aligned(PAGE_SIZE); @@ -370,13 +364,14 @@ void xen_mcast_invlpg(vaddr_t va, uint32_t cpumask) { mmuext_op_t op; + u_long xcpumask = cpumask; /* Flush pending page updates */ xpq_flush_queue(); op.cmd = MMUEXT_INVLPG_MULTI; op.arg1.linear_addr = va; - op.arg2.vcpumask = &cpumask; + op.arg2.vcpumask = &xcpumask; if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) { panic("xpq_queue_invlpg_all"); @@ -408,12 +403,13 @@ void xen_mcast_tlbflush(uint32_t cpumask) { mmuext_op_t op; + u_long xcpumask = cpumask; /* Flush pending page updates */ xpq_flush_queue(); op.cmd = MMUEXT_TLB_FLUSH_MULTI; - op.arg2.vcpumask = &cpumask; + op.arg2.vcpumask = &xcpumask; if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) { panic("xpq_queue_invlpg_all");