Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 May 2003 15:02:25 -0700 (PDT)
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 31199 for review
Message-ID:  <200305142202.h4EM2P9G061160@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=31199

Change 31199 by peter@peter_hammer on 2003/05/14 15:02:11

	Collect the nastiness about load_gs vs gsbase into a single
	file.  Do load_fs/fsbase while here, except it doesn't need
	to disable the interrupts.

Affected files ...

.. //depot/projects/hammer/sys/amd64/amd64/machdep.c#35 edit
.. //depot/projects/hammer/sys/amd64/ia32/ia32_sysvec.c#6 edit
.. //depot/projects/hammer/sys/amd64/include/cpufunc.h#8 edit

Differences ...

==== //depot/projects/hammer/sys/amd64/amd64/machdep.c#35 (text+ko) ====

@@ -476,7 +476,6 @@
 {
 	struct trapframe *regs = td->td_frame;
 	struct pcb *pcb = td->td_pcb;
-	u_int64_t pc;
 	
 	wrmsr(MSR_FSBASE, 0);
 	wrmsr(MSR_KGSBASE, 0);	/* User value while we're in the kernel */
@@ -486,11 +485,7 @@
 	load_ds(_udatasel);
 	load_es(_udatasel);
 	load_fs(_udatasel);
-	critical_enter();
-	pc = rdmsr(MSR_GSBASE);
-	load_gs(_udatasel);	/* Clobbers kernel %GS.base */
-	wrmsr(MSR_GSBASE, pc);
-	critical_exit();
+	load_gs(_udatasel);
 	pcb->pcb_ds = _udatasel;
 	pcb->pcb_es = _udatasel;
 	pcb->pcb_fs = _udatasel;

==== //depot/projects/hammer/sys/amd64/ia32/ia32_sysvec.c#6 (text+ko) ====

@@ -241,8 +241,6 @@
 {
 	struct trapframe *regs = td->td_frame;
 	struct pcb *pcb = td->td_pcb;
-	u_int64_t pc;
-	register_t s;
 	
 	wrmsr(MSR_FSBASE, 0);
 	wrmsr(MSR_KGSBASE, 0);	/* User value while we're in the kernel */
@@ -252,11 +250,7 @@
 	load_ds(_udatasel);
 	load_es(_udatasel);
 	load_fs(_udatasel);
-	s = intr_disable();
-	pc = rdmsr(MSR_GSBASE);
-	load_gs(_udatasel);	/* Clobbers kernel %GS.base */
-	wrmsr(MSR_GSBASE, pc);
-	intr_restore(s);
+	load_gs(_udatasel);
 	pcb->pcb_ds = _udatasel;
 	pcb->pcb_es = _udatasel;
 	pcb->pcb_fs = _udatasel;

==== //depot/projects/hammer/sys/amd64/include/cpufunc.h#8 (text+ko) ====

@@ -475,6 +475,41 @@
 	__asm __volatile("movl %0,%%es" : : "rm" (sel));
 }
 
+#ifdef _KERNEL
+/* This is defined in <machine/specialreg.h> but is too painful to get to */
+#ifndef	MSR_FSBASE
+#define	MSR_FSBASE	0xc0000100
+#endif
+static __inline void
+load_fs(u_int sel)
+{
+	register u_int32_t fsbase __asm("ecx");
+
+	/* Preserve the fsbase value across the selector load */
+	fsbase = MSR_FSBASE;
+        __asm __volatile("rdmsr; movl %0,%%fs; wrmsr"
+            : : "rm" (sel), "c" (fsbase) : "eax", "edx");
+}
+
+#ifndef	MSR_GSBASE
+#define	MSR_GSBASE	0xc0000101
+#endif
+static __inline void
+load_gs(u_int sel)
+{
+	register u_int32_t gsbase __asm("ecx");
+
+	/*
+	 * Preserve the gsbase value across the selector load.
+	 * Note that we have to disable interrupts because the gsbase
+	 * being trashed happens to be the kernel gsbase at the time.
+	 */
+	gsbase = MSR_GSBASE;
+        __asm __volatile("pushfq; cli; rdmsr; movl %0,%%gs; wrmsr; popfq"
+            : : "rm" (sel), "c" (gsbase) : "eax", "edx");
+}
+#else
+/* Usable by userland */
 static __inline void
 load_fs(u_int sel)
 {
@@ -486,6 +521,7 @@
 {
 	__asm __volatile("movl %0,%%gs" : : "rm" (sel));
 }
+#endif
 
 /* void lidt(struct region_descriptor *addr); */
 static __inline void



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200305142202.h4EM2P9G061160>