Module Name:    src
Committed By:   chs
Date:           Wed Jul  7 01:14:53 UTC 2010

Modified Files:
        src/sys/arch/amd64/amd64: cpufunc.S gdt.c genassym.cf locore.S
            machdep.c netbsd32_machdep.c vector.S
        src/sys/arch/amd64/include: frameasm.h gdt.h pcb.h segments.h
        src/sys/arch/x86/include: cpufunc.h sysarch.h
        src/sys/arch/x86/x86: pmap.c

Log Message:
add the guts of TLS support on amd64.  based on joerg's patch,
reworked by me to support 32-bit processes as well.
we now keep %fs and %gs loaded with the user values
while in the kernel, which means we don't need to
reload them when returning to user mode.


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/amd64/amd64/cpufunc.S
cvs rdiff -u -r1.23 -r1.24 src/sys/arch/amd64/amd64/gdt.c
cvs rdiff -u -r1.44 -r1.45 src/sys/arch/amd64/amd64/genassym.cf
cvs rdiff -u -r1.57 -r1.58 src/sys/arch/amd64/amd64/locore.S
cvs rdiff -u -r1.145 -r1.146 src/sys/arch/amd64/amd64/machdep.c
cvs rdiff -u -r1.63 -r1.64 src/sys/arch/amd64/amd64/netbsd32_machdep.c
cvs rdiff -u -r1.33 -r1.34 src/sys/arch/amd64/amd64/vector.S
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/amd64/include/frameasm.h
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/amd64/include/gdt.h
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/amd64/include/pcb.h
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/amd64/include/segments.h
cvs rdiff -u -r1.11 -r1.12 src/sys/arch/x86/include/cpufunc.h
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/x86/include/sysarch.h
cvs rdiff -u -r1.110 -r1.111 src/sys/arch/x86/x86/pmap.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/cpufunc.S
diff -u src/sys/arch/amd64/amd64/cpufunc.S:1.16 src/sys/arch/amd64/amd64/cpufunc.S:1.17
--- src/sys/arch/amd64/amd64/cpufunc.S:1.16	Thu Oct  1 09:13:54 2009
+++ src/sys/arch/amd64/amd64/cpufunc.S	Wed Jul  7 01:14:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpufunc.S,v 1.16 2009/10/01 09:13:54 skrll Exp $	*/
+/*	$NetBSD: cpufunc.S,v 1.17 2010/07/07 01:14:52 chs Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -34,6 +34,7 @@
  */
 
 #include <machine/asm.h>
+#include <machine/frameasm.h>
 #include <machine/specialreg.h>
 #include <machine/segments.h>
 
@@ -513,3 +514,15 @@
 	rep
 	outsl
 	ret
+
+ENTRY(setfs)
+	movw	%di, %fs
+	ret
+
+ENTRY(setusergs)
+	CLI(ax)
+	swapgs
+	movw	%di, %gs
+	swapgs
+	STI(ax)
+	ret

Index: src/sys/arch/amd64/amd64/gdt.c
diff -u src/sys/arch/amd64/amd64/gdt.c:1.23 src/sys/arch/amd64/amd64/gdt.c:1.24
--- src/sys/arch/amd64/amd64/gdt.c:1.23	Sat Nov 21 03:11:01 2009
+++ src/sys/arch/amd64/amd64/gdt.c	Wed Jul  7 01:14:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: gdt.c,v 1.23 2009/11/21 03:11:01 rmind Exp $	*/
+/*	$NetBSD: gdt.c,v 1.24 2010/07/07 01:14:52 chs Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 2009 The NetBSD Foundation, Inc.
@@ -37,10 +37,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gdt.c,v 1.23 2009/11/21 03:11:01 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gdt.c,v 1.24 2010/07/07 01:14:52 chs Exp $");
 
 #include "opt_multiprocessor.h"
 #include "opt_xen.h"
+#include "opt_user_ldt.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -56,7 +57,6 @@
 #include <xen/hypervisor.h>
 #endif 
 
-
 int gdt_size;		/* size of GDT in bytes */
 int gdt_dyncount;	/* number of dyn. allocated GDT entries in use */
 int gdt_dynavail;
@@ -69,48 +69,45 @@
 void gdt_put_slot(int);
 
 void
-set_mem_gdt(struct mem_segment_descriptor *sd, void *base, size_t limit,
-	    int type, int dpl, int gran, int def32, int is64)
+update_descriptor(void *tp, void *ep)
 {
-#if 0
-	CPU_INFO_ITERATOR cii;
-	struct cpu_info *ci;
-	int off;
-#endif
+	uint64_t *table, *entry;
 
-        set_mem_segment(sd, base, limit, type, dpl, gran, def32, is64);
-#if 0
-	off = (char *)sd - gdtstore;
-        for (CPU_INFO_FOREACH(cii, ci)) {
-                if (ci->ci_gdt != NULL)
-			*(struct mem_segment_descriptor *)(ci->ci_gdt + off) =
-			    *sd;
-        }
+	table = tp;
+	entry = ep;
+
+#ifndef XEN
+	*table = *entry;
+#else
+	paddr_t pa;
+
+	if (!pmap_extract_ma(pmap_kernel(), (vaddr_t)table, &pa) ||
+	    HYPERVISOR_update_descriptor(pa, *entry))
+		panic("HYPERVISOR_update_descriptor failed\n");
 #endif
 }
 
 void
-set_sys_gdt(struct sys_segment_descriptor *sd, void *base, size_t limit,
+set_sys_gdt(int slot, void *base, size_t limit,
 	    int type, int dpl, int gran)
 {
-#if 0
+	union {
+		struct sys_segment_descriptor sd;
+		uint64_t bits[2];
+	} d;
 	CPU_INFO_ITERATOR cii;
 	struct cpu_info *ci;
-	int off;
-#endif
+	int idx;
 
-        set_sys_segment(sd, base, limit, type, dpl, gran);
-#if 0
-	off = (char *)sd - gdtstore;
+        set_sys_segment(&d.sd, base, limit, type, dpl, gran);
+	idx = IDXSEL(GDYNSEL(slot, SEL_KPL));
         for (CPU_INFO_FOREACH(cii, ci)) {
-                if (ci->ci_gdt != NULL)
-			*(struct sys_segment_descriptor *)(ci->ci_gdt + off) =
-			    *sd;
+                KASSERT(ci->ci_gdt != NULL);
+		update_descriptor(&ci->ci_gdt[idx + 0], &d.bits[0]);
+		update_descriptor(&ci->ci_gdt[idx + 1], &d.bits[1]);
         }
-#endif
 }
 
-
 /*
  * Initialize the GDT.
  */
@@ -157,16 +154,25 @@
 void
 gdt_alloc_cpu(struct cpu_info *ci)
 {
-#if 0
-        ci->ci_gdt = (void *)uvm_km_valloc(kernel_map, MAXGDTSIZ);
-        uvm_map_pageable(kernel_map, (vaddr_t)ci->ci_gdt,
-            (vaddr_t)ci->ci_gdt + MINGDTSIZ, false, false);
-        memset(ci->ci_gdt, 0, MINGDTSIZ);
-        memcpy(ci->ci_gdt, gdtstore,
-	   DYNSEL_START + gdt_dyncount * sizeof(struct sys_segment_descriptor));
-#else
-	ci->ci_gdt = (void *)gdtstore;
-#endif
+	int max_len = MAXGDTSIZ;
+	int min_len = MINGDTSIZ;
+	struct vm_page *pg;
+	vaddr_t va;
+
+	ci->ci_gdt = (union descriptor *)uvm_km_alloc(kernel_map, max_len,
+	    0, UVM_KMF_VAONLY);
+	for (va = (vaddr_t)ci->ci_gdt; va < (vaddr_t)ci->ci_gdt + min_len;
+	    va += PAGE_SIZE) {
+		while ((pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO))
+		    == NULL) {
+			uvm_wait("gdt_alloc_cpu");
+		}
+		pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
+		    VM_PROT_READ | VM_PROT_WRITE, 0);
+	}
+	pmap_update(pmap_kernel());
+	memset(ci->ci_gdt, 0, min_len);
+	memcpy(ci->ci_gdt, gdtstore, gdt_size);
 }
 
 
@@ -182,14 +188,12 @@
 #ifndef XEN
 	setregion(&region, ci->ci_gdt, (uint16_t)(MAXGDTSIZ - 1));
 #else
-	/* Enter only allocated frames */
 	setregion(&region, ci->ci_gdt, (uint16_t)(gdt_size - 1));
 #endif
 	lgdt(&region);
 }
 
 #ifdef MULTIPROCESSOR
-
 void
 gdt_reload_cpu(struct cpu_info *ci)
 {
@@ -198,7 +202,6 @@
 #ifndef XEN
 	setregion(&region, ci->ci_gdt, MAXGDTSIZ - 1);
 #else
-	/* Enter only allocated frames */
 	setregion(&region, ci->ci_gdt, gdt_size - 1);
 #endif
 	lgdt(&region);
@@ -303,28 +306,9 @@
 
 	mutex_enter(&cpu_lock);
 	slot = gdt_get_slot();
-#if 0
-	printf("tss_alloc: slot %d addr %p\n", slot, &gdt[slot]);
-#endif
-	set_sys_gdt(&gdt[slot], tss, sizeof (struct x86_64_tss)-1,
+	set_sys_gdt(slot, tss, sizeof (struct x86_64_tss) - 1,
 	    SDT_SYS386TSS, SEL_KPL, 0);
 	mutex_exit(&cpu_lock);
-#if 0
-	printf("lolimit %lx lobase %lx type %lx dpl %lx p %lx hilimit %lx\n"
-	       "xx1 %lx gran %lx hibase %lx xx2 %lx zero %lx xx3 %lx pad %lx\n",
-		(unsigned long)gdt[slot].sd_lolimit,
-		(unsigned long)gdt[slot].sd_lobase,
-		(unsigned long)gdt[slot].sd_type,
-		(unsigned long)gdt[slot].sd_dpl,
-		(unsigned long)gdt[slot].sd_p,
-		(unsigned long)gdt[slot].sd_hilimit,
-		(unsigned long)gdt[slot].sd_xx1,
-		(unsigned long)gdt[slot].sd_gran,
-		(unsigned long)gdt[slot].sd_hibase,
-		(unsigned long)gdt[slot].sd_xx2,
-		(unsigned long)gdt[slot].sd_zero,
-		(unsigned long)gdt[slot].sd_xx3);
-#endif
 	return GDYNSEL(slot, SEL_KPL);
 #else  /* XEN */
 	/* TSS, what for? */
@@ -344,6 +328,7 @@
 #endif
 }
 
+#ifdef USER_LDT
 void
 ldt_alloc(struct pmap *pmap, char *ldt, size_t len)
 {
@@ -355,7 +340,7 @@
 	gdt = (struct sys_segment_descriptor *)&gdtstore[DYNSEL_START];
 
 	slot = gdt_get_slot();
-	set_sys_gdt(&gdt[slot], ldt, len - 1, SDT_SYSLDT, SEL_KPL, 0);
+	set_sys_gdt(slot, ldt, len - 1, SDT_SYSLDT, SEL_KPL, 0);
 	pmap->pm_ldt_sel = GSEL(slot, SEL_KPL);
 }
 
@@ -370,6 +355,7 @@
 
 	gdt_put_slot(slot);
 }
+#endif
 
 #ifdef XEN
 void
@@ -380,22 +366,22 @@
 	vaddr_t va;
 
 	/*
-	* XXX: Xen even checks descriptors AFTER limit.
-	* Zero out last frame after limit if needed.
-	*/
+	 * XXX: Xen even checks descriptors AFTER limit.
+	 * Zero out last frame after limit if needed.
+	 */
 	va = desc->rd_base + desc->rd_limit + 1;
 	__PRINTK(("memset 0x%lx -> 0x%lx\n", va, roundup(va, PAGE_SIZE)));
 	memset((void *) va, 0, roundup(va, PAGE_SIZE) - va);
-	for  (i = 0; i < roundup(desc->rd_limit,PAGE_SIZE) >> PAGE_SHIFT; i++) {
+	for (i = 0; i < roundup(desc->rd_limit, PAGE_SIZE) >> PAGE_SHIFT; i++) {
+
 		/*
-		* The lgdt instr uses virtual addresses, do some translation fo
-r Xen.
-		* Mark pages R/O too, else Xen will refuse to use them
-		*/
+		 * The lgdt instruction uses virtual addresses,
+		 * do some translation for Xen.
+		 * Mark pages R/O too, else Xen will refuse to use them.
+		 */
 
 		frames[i] = ((paddr_t) xpmap_ptetomach(
-				(pt_entry_t *) (desc->rd_base + (i << PAGE_SHIFT
-))))
+				(pt_entry_t *) (desc->rd_base + (i << PAGE_SHIFT))))
 			>> PAGE_SHIFT;
 		__PRINTK(("frames[%d] = 0x%lx (pa 0x%lx)\n", i, frames[i],
 		    xpmap_mtop(frames[i] << PAGE_SHIFT)));

Index: src/sys/arch/amd64/amd64/genassym.cf
diff -u src/sys/arch/amd64/amd64/genassym.cf:1.44 src/sys/arch/amd64/amd64/genassym.cf:1.45
--- src/sys/arch/amd64/amd64/genassym.cf:1.44	Wed Apr 28 19:17:03 2010
+++ src/sys/arch/amd64/amd64/genassym.cf	Wed Jul  7 01:14:52 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.44 2010/04/28 19:17:03 dyoung Exp $
+#	$NetBSD: genassym.cf,v 1.45 2010/07/07 01:14:52 chs Exp $
 
 #
 # Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -188,6 +188,10 @@
 define	PCB_CR0			offsetof(struct pcb, pcb_cr0)
 define	PCB_ONFAULT		offsetof(struct pcb, pcb_onfault)
 define	PCB_FPCPU		offsetof(struct pcb, pcb_fpcpu)
+define	PCB_FLAGS		offsetof(struct pcb, pcb_flags)
+define	PCB_COMPAT32		PCB_COMPAT32
+define	PCB_FS			offsetof(struct pcb, pcb_fs)
+define	PCB_GS			offsetof(struct pcb, pcb_gs)
 
 define	TF_RDI			offsetof(struct trapframe, tf_rdi)
 define	TF_RSI			offsetof(struct trapframe, tf_rsi)
@@ -298,7 +302,7 @@
 define  LINUX32_RT_SF_UC	offsetof(struct linux32_rt_sigframe, sf_uc)
 define  LINUX32_SYS_rt_sigreturn	LINUX32_SYS_rt_sigreturn
 define  LINUX32_SYS_sigreturn		LINUX32_SYS_sigreturn
-define  LINUX32_SYS_exit		LINUX32_SYS_netbsd32_exit
+define  LINUX32_SYS_exit		LINUX32_SYS_exit
 endif
 
 ifdef XEN

Index: src/sys/arch/amd64/amd64/locore.S
diff -u src/sys/arch/amd64/amd64/locore.S:1.57 src/sys/arch/amd64/amd64/locore.S:1.58
--- src/sys/arch/amd64/amd64/locore.S:1.57	Sun Apr 18 23:47:50 2010
+++ src/sys/arch/amd64/amd64/locore.S	Wed Jul  7 01:14:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.S,v 1.57 2010/04/18 23:47:50 jym Exp $	*/
+/*	$NetBSD: locore.S,v 1.58 2010/07/07 01:14:52 chs Exp $	*/
 
 /*
  * Copyright-o-rama!
@@ -887,7 +887,7 @@
 	ret
 
 /*
- * struct lwp *cpu_switchto(struct lwp *oldlwp, struct newlwp,
+ * struct lwp *cpu_switchto(struct lwp *oldlwp, struct lwp *newlwp,
  *			    bool returning)
  *
  *	1. if (oldlwp != NULL), save its context.
@@ -976,10 +976,58 @@
 
 	/* Reloading CR0 is very expensive - avoid if possible. */
 3:	cmpq	%rdx,%rcx
-	je	4f
+	je	6f
 	movq	%rcx,%cr0
-#endif
 
+6:	testl   $PCB_COMPAT32, PCB_FLAGS(%r14)
+	jne	32f
+
+	/* Zero out %fs/%gs registers and GDT descriptors. */
+	xorq	%rax, %rax
+	movw	%ax, %fs
+	CLI(cx)
+	swapgs
+	movw	%ax, %gs
+	swapgs
+	STI(cx)
+
+	movq	CPUVAR(GDT),%rcx
+	movq	%rax, (GUFS_SEL*8)(%rcx)
+	movq	%rax, (GUGS_SEL*8)(%rcx)
+
+	/* Reload 64-bit %fs/%gs MSRs. */
+	movl	$MSR_FSBASE, %ecx
+	movl	PCB_FS(%r14), %eax
+	movl	4+PCB_FS(%r14), %edx
+	wrmsr
+	movl	$MSR_KERNELGSBASE, %ecx
+	movl	PCB_GS(%r14), %eax
+	movl	4+PCB_GS(%r14), %edx
+	wrmsr
+	jmp	4f
+
+32:
+	/* Reload %fs/%gs GDT descriptors. */
+	movq	CPUVAR(GDT),%rcx
+	movq	PCB_FS(%r14), %rax
+	movq	%rax, (GUFS_SEL*8)(%rcx)
+	movq	PCB_GS(%r14), %rax
+	movq	%rax, (GUGS_SEL*8)(%rcx)
+
+	/* Reload %fs and %gs */
+	movq	L_MD_REGS(%r12), %rbx
+	movw	TF_FS(%rbx), %fs
+	CLI(ax)
+	swapgs
+	movw	TF_GS(%rbx), %gs
+	swapgs
+	STI(ax)
+
+#else
+	movq	%r12,%rdi
+	callq	_C_LABEL(x86_64_tls_switch)
+#endif
+	
 	/* Return to the new LWP, returning 'oldlwp' in %rax. */
 4:	movq	%r13,%rax
 	popq	%r15
@@ -1078,9 +1126,6 @@
 	movl	L_MD_ASTPENDING(%r14), %eax
 	orl	CPUVAR(WANT_PMAPLOAD), %eax
 	jnz	9f
-#ifdef XEN
-	STI(si)					/* wtf is this? */
-#endif
 	testl	$MDP_IRET, L_MD_FLAGS(%r14)
 	jne	iret_return;
 syscall_return:
@@ -1088,13 +1133,9 @@
 	cmpl	$IPL_NONE,CPUVAR(ILEVEL)
 	jne	3f
 #endif
-#ifndef XEN
-	swapgs
-#endif
 	movw	TF_ES(%rsp),%es
-	movw	TF_FS(%rsp),%fs
 #ifndef XEN
-	movw	TF_GS(%rsp),%gs
+	swapgs
 #endif
 	INTR_RESTORE_GPRS
 	movw	$(LSEL(LUDATA_SEL, SEL_UPL)),%r11

Index: src/sys/arch/amd64/amd64/machdep.c
diff -u src/sys/arch/amd64/amd64/machdep.c:1.145 src/sys/arch/amd64/amd64/machdep.c:1.146
--- src/sys/arch/amd64/amd64/machdep.c:1.145	Tue May  4 23:27:13 2010
+++ src/sys/arch/amd64/amd64/machdep.c	Wed Jul  7 01:14:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.145 2010/05/04 23:27:13 jym Exp $	*/
+/*	$NetBSD: machdep.c,v 1.146 2010/07/07 01:14:52 chs Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008
@@ -107,7 +107,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.145 2010/05/04 23:27:13 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.146 2010/07/07 01:14:52 chs Exp $");
 
 /* #define XENDEBUG_LOW  */
 
@@ -999,8 +999,6 @@
 
 	l->l_md.md_flags &= ~MDP_USEDFPU;
 	pcb->pcb_flags = 0;
-	pcb->pcb_fs = 0;
-	pcb->pcb_gs = 0;
 	pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_NPXCW__;
 	pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__;
 	pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;
@@ -1010,8 +1008,7 @@
 	tf = l->l_md.md_regs;
 	tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
 	tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
-	tf->tf_fs = LSEL(LUDATA_SEL, SEL_UPL);
-	tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL);
+	cpu_fsgs_zero(l);
 	tf->tf_rdi = 0;
 	tf->tf_rsi = 0;
 	tf->tf_rbp = 0;
@@ -1061,7 +1058,7 @@
 }
 
 void
-unsetgate( struct gate_descriptor *gd)
+unsetgate(struct gate_descriptor *gd)
 {
 
 	kpreempt_disable();
@@ -1414,6 +1411,12 @@
 	set_mem_segment(GDT_ADDR_MEM(gdtstore, GUDATA32_SEL), 0,
 	    x86_btop(VM_MAXUSER_ADDRESS32) - 1, SDT_MEMRWA, SEL_UPL, 1, 1, 0);
 
+	set_mem_segment(GDT_ADDR_MEM(gdtstore, GUFS_SEL), 0,
+	    x86_btop(VM_MAXUSER_ADDRESS32) - 1, SDT_MEMRWA, SEL_UPL, 1, 1, 0);
+
+	set_mem_segment(GDT_ADDR_MEM(gdtstore, GUGS_SEL), 0,
+	    x86_btop(VM_MAXUSER_ADDRESS32) - 1, SDT_MEMRWA, SEL_UPL, 1, 1, 0);
+
 	/*
 	 * 32 bit LDT entries.
 	 */
@@ -1800,3 +1803,105 @@
 {
 	return memseg_baseaddr(l, seg, ldtp, len, NULL);
 }
+
+/*
+ * Zero out an LWP's TLS context (%fs and %gs and associated stuff).
+ * Used when exec'ing a new program.
+ */
+
+void
+cpu_fsgs_zero(struct lwp *l)
+{
+	struct trapframe *tf;
+	struct pcb *pcb;
+	uint64_t zero = 0;
+
+	pcb = lwp_getpcb(l);
+	if (l == curlwp) {
+		tf = l->l_md.md_regs;
+		kpreempt_disable();
+		tf->tf_fs = 0;
+		tf->tf_gs = 0;
+		if (l->l_proc->p_flag & PK_32) {
+			setfs(0);
+#ifndef XEN
+			setusergs(0);
+#else
+			HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, 0);
+#endif
+		} else {
+#ifndef XEN
+			wrmsr(MSR_FSBASE, 0);
+			wrmsr(MSR_KERNELGSBASE, 0);
+#else
+			HYPERVISOR_set_segment_base(SEGBASE_FS, 0);
+			HYPERVISOR_set_segment_base(SEGBASE_GS_USER, 0);
+#endif
+		}
+		pcb->pcb_fs = 0;
+		pcb->pcb_gs = 0;
+		update_descriptor(&curcpu()->ci_gdt[GUFS_SEL], &zero);
+		update_descriptor(&curcpu()->ci_gdt[GUGS_SEL], &zero);
+		kpreempt_enable();
+	} else {
+		pcb->pcb_fs = 0;
+		pcb->pcb_gs = 0;
+	}
+
+}
+
+/*
+ * Load an LWP's TLS context, possibly changing the %fs and %gs selectors.
+ * Used only for 32-bit processes.
+ */
+
+void
+cpu_fsgs_reload(struct lwp *l, int fssel, int gssel)
+{
+	struct trapframe *tf;
+	struct pcb *pcb;
+
+	KASSERT(l->l_proc->p_flag & PK_32);
+	tf = l->l_md.md_regs;
+	if (l == curlwp) {
+		pcb = lwp_getpcb(l);
+		kpreempt_disable();
+		update_descriptor(&curcpu()->ci_gdt[GUFS_SEL], &pcb->pcb_fs);
+		update_descriptor(&curcpu()->ci_gdt[GUGS_SEL], &pcb->pcb_gs);
+		setfs(fssel);
+#ifndef XEN
+		setusergs(gssel);
+#else
+		HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, gssel);
+#endif
+		tf->tf_fs = fssel;
+		tf->tf_gs = gssel;
+		kpreempt_enable();
+	} else {
+		tf->tf_fs = fssel;
+		tf->tf_gs = gssel;
+	}
+}
+
+#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

Index: src/sys/arch/amd64/amd64/netbsd32_machdep.c
diff -u src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.63 src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.64
--- src/sys/arch/amd64/amd64/netbsd32_machdep.c:1.63	Tue May 11 02:34:39 2010
+++ src/sys/arch/amd64/amd64/netbsd32_machdep.c	Wed Jul  7 01:14:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: netbsd32_machdep.c,v 1.63 2010/05/11 02:34:39 joerg Exp $	*/
+/*	$NetBSD: netbsd32_machdep.c,v 1.64 2010/07/07 01:14:52 chs Exp $	*/
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.63 2010/05/11 02:34:39 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.64 2010/07/07 01:14:52 chs Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -95,9 +95,8 @@
 #define x86_64_set_mtrr32(x, y, z)	ENOSYS
 #endif
 
-static int check_sigcontext32(const struct netbsd32_sigcontext *,
-    struct trapframe *);
-static int check_mcontext32(const mcontext32_t *, struct trapframe *);
+static int check_sigcontext32(struct lwp *, const struct netbsd32_sigcontext *);
+static int check_mcontext32(struct lwp *, const mcontext32_t *);
 
 #ifdef EXEC_AOUT
 /*
@@ -128,11 +127,13 @@
 void
 netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
 {
-	struct pcb *pcb = lwp_getpcb(l);
+	struct pcb *pcb;
 	struct trapframe *tf;
 	struct proc *p = l->l_proc;
 	void **retaddr;
 
+	pcb = lwp_getpcb(l);
+
 	/* If we were using the FPU, forget about it. */
 	if (pcb->pcb_fpcpu != NULL) {
 		fpusave_lwp(l, false);
@@ -145,19 +146,18 @@
 	netbsd32_adjust_limits(p);
 
 	l->l_md.md_flags &= ~MDP_USEDFPU;
-	pcb->pcb_flags = 0;
+	pcb->pcb_flags = PCB_COMPAT32;
         pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_NPXCW__;
         pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__;  
 	pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;
 
-
 	p->p_flag |= PK_32;
 
 	tf = l->l_md.md_regs;
 	tf->tf_ds = LSEL(LUDATA32_SEL, SEL_UPL);
 	tf->tf_es = LSEL(LUDATA32_SEL, SEL_UPL);
-	tf->tf_fs = LSEL(LUDATA32_SEL, SEL_UPL);
-	tf->tf_gs = LSEL(LUDATA32_SEL, SEL_UPL);
+	cpu_fsgs_zero(l);
+	cpu_fsgs_reload(l, tf->tf_ds, tf->tf_ds);
 	tf->tf_rdi = 0;
 	tf->tf_rsi = 0;
 	tf->tf_rbp = 0;
@@ -402,20 +402,18 @@
 	if (copyin(scp, &context, sizeof(*scp)) != 0)
 		return (EFAULT);
 
-	/* Restore register context. */
-	tf = l->l_md.md_regs;
 	/*
 	 * Check for security violations.
 	 */
-	error = check_sigcontext32(&context, tf);
+	error = check_sigcontext32(l, &context);
 	if (error != 0)
 		return error;
 
+	/* Restore register context. */
+	tf = l->l_md.md_regs;
 	tf->tf_ds = context.sc_ds;
 	tf->tf_es = context.sc_es;
-	tf->tf_fs = context.sc_fs;
-	tf->tf_gs = context.sc_gs;
-
+	cpu_fsgs_reload(l, context.sc_fs, context.sc_gs);
 	tf->tf_rflags = context.sc_eflags;
 	tf->tf_rdi = context.sc_edi;
 	tf->tf_rsi = context.sc_esi;
@@ -838,11 +836,11 @@
 		/*
 		 * Check for security violations.
 		 */
-		error = check_mcontext32(mcp, tf);
+		error = check_mcontext32(l, mcp);
 		if (error != 0)
 			return error;
-		tf->tf_gs = gr[_REG32_GS];
-		tf->tf_fs = gr[_REG32_FS];
+
+		cpu_fsgs_reload(l, gr[_REG32_FS], gr[_REG32_GS]);
 		tf->tf_es = gr[_REG32_ES];
 		tf->tf_ds = gr[_REG32_DS];
 		/* Only change the user-alterable part of eflags */
@@ -955,13 +953,21 @@
  * These functions perform the needed checks.
  */
 static int
-check_sigcontext32(const struct netbsd32_sigcontext *scp, struct trapframe *tf)
+check_sigcontext32(struct lwp *l, const struct netbsd32_sigcontext *scp)
 {
+	struct trapframe *tf;
+	struct pcb *pcb;
+
+	tf = l->l_md.md_regs;
+	pcb = lwp_getpcb(curlwp);
+
 	if (((scp->sc_eflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0)
 		return EINVAL;
-	if (scp->sc_fs != 0 && !VALID_USER_DSEL32(scp->sc_fs))
+	if (scp->sc_fs != 0 && !VALID_USER_DSEL32(scp->sc_fs) &&
+	    !(scp->sc_fs == GSEL(GUFS_SEL, SEL_UPL) && pcb->pcb_fs != 0))
 		return EINVAL;
-	if (scp->sc_gs != 0 && !VALID_USER_DSEL32(scp->sc_gs))
+	if (scp->sc_gs != 0 && !VALID_USER_DSEL32(scp->sc_gs) &&
+	    !(scp->sc_gs == GSEL(GUGS_SEL, SEL_UPL) && pcb->pcb_gs != 0))
 		return EINVAL;
 	if (scp->sc_es != 0 && !VALID_USER_DSEL32(scp->sc_es))
 		return EINVAL;
@@ -973,17 +979,23 @@
 }
 
 static int
-check_mcontext32(const mcontext32_t *mcp, struct trapframe *tf)
+check_mcontext32(struct lwp *l, const mcontext32_t *mcp)
 {
 	const __greg32_t *gr;
+	struct trapframe *tf;
+	struct pcb *pcb;
 
 	gr = mcp->__gregs;
+	tf = l->l_md.md_regs;
+	pcb = lwp_getpcb(l);
 
 	if (((gr[_REG32_EFL] ^ tf->tf_rflags) & PSL_USERSTATIC) != 0)
 		return EINVAL;
-	if (gr[_REG32_FS] != 0 && !VALID_USER_DSEL32(gr[_REG32_FS]))
+	if (gr[_REG32_FS] != 0 && !VALID_USER_DSEL32(gr[_REG32_FS]) &&
+	    !(gr[_REG32_FS] == GSEL(GUFS_SEL, SEL_UPL) && pcb->pcb_fs != 0))
 		return EINVAL;
-	if (gr[_REG32_GS] != 0 && !VALID_USER_DSEL32(gr[_REG32_GS]))
+	if (gr[_REG32_GS] != 0 && !VALID_USER_DSEL32(gr[_REG32_GS]) &&
+	    !(gr[_REG32_GS] == GSEL(GUGS_SEL, SEL_UPL) && pcb->pcb_gs != 0))
 		return EINVAL;
 	if (gr[_REG32_ES] != 0 && !VALID_USER_DSEL32(gr[_REG32_ES]))
 		return EINVAL;

Index: src/sys/arch/amd64/amd64/vector.S
diff -u src/sys/arch/amd64/amd64/vector.S:1.33 src/sys/arch/amd64/amd64/vector.S:1.34
--- src/sys/arch/amd64/amd64/vector.S:1.33	Tue Feb 23 06:27:40 2010
+++ src/sys/arch/amd64/amd64/vector.S	Wed Jul  7 01:14:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: vector.S,v 1.33 2010/02/23 06:27:40 cegger Exp $	*/
+/*	$NetBSD: vector.S,v 1.34 2010/07/07 01:14:52 chs Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -154,11 +154,9 @@
 	movq	%rsp,%rdi
 	incl	CPUVAR(NTRAP)
 	call	_C_LABEL(trap)
-	swapgs
-	movw	TF_GS(%rsp),%gs
-	movw	TF_FS(%rsp),%fs
 	movw	TF_ES(%rsp),%es
 	movw	TF_DS(%rsp),%ds
+	swapgs
 	jmp	2f
 1:
 	movq	%rsp,%rdi

Index: src/sys/arch/amd64/include/frameasm.h
diff -u src/sys/arch/amd64/include/frameasm.h:1.13 src/sys/arch/amd64/include/frameasm.h:1.14
--- src/sys/arch/amd64/include/frameasm.h:1.13	Fri Nov 21 10:05:41 2008
+++ src/sys/arch/amd64/include/frameasm.h	Wed Jul  7 01:14:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: frameasm.h,v 1.13 2008/11/21 10:05:41 ad Exp $	*/
+/*	$NetBSD: frameasm.h,v 1.14 2010/07/07 01:14:52 chs Exp $	*/
 
 #ifndef _AMD64_MACHINE_FRAMEASM_H
 #define _AMD64_MACHINE_FRAMEASM_H
@@ -66,7 +66,7 @@
 	movw	%fs,TF_FS(%rsp)		; \
 	movw	%es,TF_ES(%rsp)		; \
 	movw	%ds,TF_DS(%rsp)		; \
-98: 	INTR_SAVE_GPRS
+98:	INTR_SAVE_GPRS
 
 #ifndef XEN
 #define INTRFASTEXIT \
@@ -74,11 +74,9 @@
 	testq	$SEL_UPL,TF_CS(%rsp)	/* Interrupted %cs */ ; \
 	je	99f			; \
 	cli				; \
-	swapgs				; \
-	movw	TF_GS(%rsp),%gs		; \
-	movw	TF_FS(%rsp),%fs		; \
 	movw	TF_ES(%rsp),%es		; \
 	movw	TF_DS(%rsp),%ds		; \
+	swapgs				; \
 99:	addq	$TF_REGSIZE+16,%rsp	/* + T_xxx and error code */ ; \
 	iretq
 
@@ -101,7 +99,6 @@
  	INTR_RESTORE_GPRS 		; \
  	testq	$SEL_UPL,TF_CS(%rsp)	; \
  	je	99f			; \
- 	movw	TF_FS(%rsp),%fs		; \
  	movw	TF_ES(%rsp),%es		; \
  	movw	TF_DS(%rsp),%ds		; \
 99:	addq	$TF_REGSIZE+16,%rsp	/* + T_xxx and error code */ ; \
@@ -122,13 +119,13 @@
 #endif	/* !XEN */
  
 #define	DO_DEFERRED_SWITCH \
-	cmpq	$0, CPUVAR(WANT_PMAPLOAD)		; \
+	cmpl	$0, CPUVAR(WANT_PMAPLOAD)		; \
 	jz	1f					; \
 	call	_C_LABEL(do_pmap_load)			; \
 	1:
 
 #define	CHECK_DEFERRED_SWITCH \
-	cmpq	$0, CPUVAR(WANT_PMAPLOAD)
+	cmpl	$0, CPUVAR(WANT_PMAPLOAD)
 
 #define CHECK_ASTPENDING(reg)	cmpl	$0, L_MD_ASTPENDING(reg)
 #define CLEAR_ASTPENDING(reg)	movl	$0, L_MD_ASTPENDING(reg)

Index: src/sys/arch/amd64/include/gdt.h
diff -u src/sys/arch/amd64/include/gdt.h:1.6 src/sys/arch/amd64/include/gdt.h:1.7
--- src/sys/arch/amd64/include/gdt.h:1.6	Sat Mar 14 14:45:54 2009
+++ src/sys/arch/amd64/include/gdt.h	Wed Jul  7 01:14:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: gdt.h,v 1.6 2009/03/14 14:45:54 dsl Exp $	*/
+/*	$NetBSD: gdt.h,v 1.7 2010/07/07 01:14:52 chs Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
@@ -45,10 +45,7 @@
 void ldt_alloc(struct pmap *, char *, size_t);
 void ldt_free(struct pmap *);
 
-void set_mem_gdt(struct mem_segment_descriptor *, void *, size_t,
-		 int, int, int, int, int);
-void set_sys_gdt(struct sys_segment_descriptor *, void *, size_t, int, int,
-		 int);
+void set_sys_gdt(int, void *, size_t, int, int, int);
 #endif
 
 #define MINGDTSIZ       PAGE_SIZE

Index: src/sys/arch/amd64/include/pcb.h
diff -u src/sys/arch/amd64/include/pcb.h:1.16 src/sys/arch/amd64/include/pcb.h:1.17
--- src/sys/arch/amd64/include/pcb.h:1.16	Tue Oct 27 03:05:28 2009
+++ src/sys/arch/amd64/include/pcb.h	Wed Jul  7 01:14:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: pcb.h,v 1.16 2009/10/27 03:05:28 rmind Exp $	*/
+/*	$NetBSD: pcb.h,v 1.17 2010/07/07 01:14:52 chs Exp $	*/
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -88,8 +88,7 @@
 struct pcb {
 	int	  pcb_flags;
 #define	PCB_USER_LDT	0x01		/* has user-set LDT */
-#define PCB_GS64	0x02
-#define PCB_FS64	0x04
+#define	PCB_COMPAT32	0x02
 	u_int	  pcb_cr0;		/* saved image of CR0 */
 	uint64_t pcb_rsp0;
 	uint64_t pcb_cr2;		/* page fault address (CR2) */
@@ -101,8 +100,8 @@
 	struct	savefpu pcb_savefpu __aligned(16); /* floating point state */
 	void     *pcb_onfault;		/* copyin/out fault recovery */
 	struct cpu_info *pcb_fpcpu;	/* cpu holding our fp state. */
-	uint64_t  pcb_gs;
 	uint64_t  pcb_fs;
+	uint64_t  pcb_gs;
 	int pcb_iopl;
 };
 

Index: src/sys/arch/amd64/include/segments.h
diff -u src/sys/arch/amd64/include/segments.h:1.19 src/sys/arch/amd64/include/segments.h:1.20
--- src/sys/arch/amd64/include/segments.h:1.19	Sun Oct 26 00:08:15 2008
+++ src/sys/arch/amd64/include/segments.h	Wed Jul  7 01:14:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: segments.h,v 1.19 2008/10/26 00:08:15 mrg Exp $	*/
+/*	$NetBSD: segments.h,v 1.20 2010/07/07 01:14:52 chs Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -209,6 +209,15 @@
 } __packed;
 
 /*
+ * Generic descriptor
+ */
+union descriptor {
+	struct mem_segment_descriptor sd;
+	uint32_t raw[2];
+	uint64_t raw64;
+} __packed;
+
+/*
  * region descriptors, used to load gdt/idt tables before segments yet exist.
  */
 struct region_descriptor {
@@ -236,6 +245,7 @@
 void set_mem_segment(struct mem_segment_descriptor *, void *, size_t,
 			  int, int, int, int, int);
 void cpu_init_idt(void);
+void update_descriptor(void *, void *);
 
 #if !defined(XEN)
 void idt_init(void);
@@ -248,7 +258,8 @@
 struct lwp;
 int memseg_baseaddr(struct lwp *, uint64_t, char *, int, uint64_t *);
 int valid_user_selector(struct lwp *, uint64_t, char *, int);
-
+void cpu_fsgs_zero(struct lwp *);
+void cpu_fsgs_reload(struct lwp *, int, int);
 
 #endif /* _KERNEL */
 
@@ -348,7 +359,9 @@
 #define GPNPBIOSTRAMP_SEL 13
 #define GUCODE32_SEL	14
 #define GUDATA32_SEL	15
-#define NGDT_MEM 16
+#define GUFS_SEL	16	/* 32-bit Per-thread %fs */
+#define GUGS_SEL	17	/* 32-bit Per-thread %gs */
+#define NGDT_MEM 18
 
 #define	GLDT_SEL	0	/* Default LDT descriptor */
 #define NGDT_SYS	1

Index: src/sys/arch/x86/include/cpufunc.h
diff -u src/sys/arch/x86/include/cpufunc.h:1.11 src/sys/arch/x86/include/cpufunc.h:1.12
--- src/sys/arch/x86/include/cpufunc.h:1.11	Tue Jan 27 21:59:24 2009
+++ src/sys/arch/x86/include/cpufunc.h	Wed Jul  7 01:14:53 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpufunc.h,v 1.11 2009/01/27 21:59:24 christos Exp $	*/
+/*	$NetBSD: cpufunc.h,v 1.12 2010/07/07 01:14:53 chs Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007 The NetBSD Foundation, Inc.
@@ -122,6 +122,8 @@
 uint64_t	rdpmc(u_int);
 void		wrmsr(u_int, uint64_t);
 void		wrmsr_locked(u_int, u_int, uint64_t);
+void		setfs(int);
+void		setusergs(int);
 
 #endif /* _KERNEL */
 

Index: src/sys/arch/x86/include/sysarch.h
diff -u src/sys/arch/x86/include/sysarch.h:1.8 src/sys/arch/x86/include/sysarch.h:1.9
--- src/sys/arch/x86/include/sysarch.h:1.8	Sat Mar 21 14:41:30 2009
+++ src/sys/arch/x86/include/sysarch.h	Wed Jul  7 01:14:53 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysarch.h,v 1.8 2009/03/21 14:41:30 ad Exp $	*/
+/*	$NetBSD: sysarch.h,v 1.9 2010/07/07 01:14:53 chs Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -174,10 +174,12 @@
 int x86_iopl(struct lwp *, void *, register_t *);
 int x86_get_mtrr(struct lwp *, void *, register_t *);
 int x86_set_mtrr(struct lwp *, void *, register_t *);
-int x86_get_ldt(struct lwp *l, void *, register_t *);
-int x86_get_ldt1(struct lwp *l, struct x86_get_ldt_args *, union descriptor *);
-int x86_set_ldt(struct lwp *l, void *, register_t *);
-int x86_set_ldt1(struct lwp *l, struct x86_set_ldt_args *, union descriptor *);
+int x86_get_ldt(struct lwp *, void *, register_t *);
+int x86_get_ldt1(struct lwp *, struct x86_get_ldt_args *, union descriptor *);
+int x86_set_ldt(struct lwp *, void *, register_t *);
+int x86_set_ldt1(struct lwp *, struct x86_set_ldt_args *, union descriptor *);
+int x86_set_sdbase(void *, char, lwp_t *, bool);
+int x86_get_sdbase(void *, char);
 #else
 #include <sys/cdefs.h>
 __BEGIN_DECLS

Index: src/sys/arch/x86/x86/pmap.c
diff -u src/sys/arch/x86/x86/pmap.c:1.110 src/sys/arch/x86/x86/pmap.c:1.111
--- src/sys/arch/x86/x86/pmap.c:1.110	Tue Jul  6 20:50:35 2010
+++ src/sys/arch/x86/x86/pmap.c	Wed Jul  7 01:14:53 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.110 2010/07/06 20:50:35 cegger Exp $	*/
+/*	$NetBSD: pmap.c,v 1.111 2010/07/07 01:14:53 chs Exp $	*/
 
 /*
  * Copyright (c) 2007 Manuel Bouyer.
@@ -149,7 +149,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.110 2010/07/06 20:50:35 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.111 2010/07/07 01:14:53 chs Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -2557,8 +2557,6 @@
 	ci = curcpu();
 
 	if (l == ci->ci_curlwp) {
-		struct pcb *pcb;
-
 		KASSERT(ci->ci_want_pmapload == 0);
 		KASSERT(ci->ci_tlbstate != TLBSTATE_VALID);
 #ifdef KSTACK_CHECK_DR0
@@ -2581,15 +2579,7 @@
 			return;
 		}
 
-		pcb = lwp_getpcb(l);
 		ci->ci_want_pmapload = 1;
-
-#if defined(__x86_64__)
-		if (pcb->pcb_flags & PCB_GS64)
-			wrmsr(MSR_KERNELGSBASE, pcb->pcb_gs);
-		if (pcb->pcb_flags & PCB_FS64)
-			wrmsr(MSR_FSBASE, pcb->pcb_fs);
-#endif /* defined(__x86_64__) */
 	}
 }
 

Reply via email to