Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 Jul 2005 18:33:58 GMT
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 80922 for review
Message-ID:  <200507241833.j6OIXwNW035022@repoman.freebsd.org>

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

Change 80922 by peter@peter_overcee on 2005/07/24 18:33:46

	Finally do what I've been threatening to do for months and move
	load_gs() to a function and catch traps from it.

Affected files ...

.. //depot/projects/hammer/sys/amd64/amd64/exception.S#43 edit
.. //depot/projects/hammer/sys/amd64/amd64/support.S#32 edit
.. //depot/projects/hammer/sys/amd64/amd64/trap.c#71 edit
.. //depot/projects/hammer/sys/amd64/amd64/vm_machdep.c#78 edit
.. //depot/projects/hammer/sys/amd64/include/cpufunc.h#35 edit
.. //depot/projects/hammer/sys/amd64/include/md_var.h#34 edit

Differences ...

==== //depot/projects/hammer/sys/amd64/amd64/exception.S#43 (text+ko) ====

@@ -221,9 +221,12 @@
 	movq	$T_PROTFLT,TF_TRAPNO(%rsp)
 	movq	$0,TF_ADDR(%rsp)
 	movq	%rdi,TF_RDI(%rsp)	/* free up a GP register */
-	leaq	doreti_iret(%rip),%rdi
+	leaq	doreti_iret(%rip),%rdi	/* iretq trapped */
 	cmpq	%rdi,TF_RIP(%rsp)
 	je	2f			/* kernel but with user gsbase!! */
+	leaq	load_gs_load(%rip),%rdi	/* load_gs() trapped */
+	cmpq	%rdi,TF_RIP(%rsp)
+	je	2f
 	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
 	jz	1f			/* already running with kernel GS.base */
 2:

==== //depot/projects/hammer/sys/amd64/amd64/support.S#32 (text+ko) ====

@@ -612,6 +612,24 @@
 	MEXITCOUNT
 	lretq
 
+/*
+ * Special handling of %gs selector.
+ * This is done as an asm function so that traps can be recovered
+ * from while in the intermediate gsbase state.
+ * %edi
+ */
+/* void load_gs(u_int sel); */
+ENTRY(load_gs)
+	pushfq
+	cli
+	swapgs
+	.globl load_gs_load
+load_gs_load:
+	movl	%edi,%gs
+	swapgs
+	popfq
+	ret
+
 /*****************************************************************************/
 /* setjump, longjump                                                         */
 /*****************************************************************************/

==== //depot/projects/hammer/sys/amd64/amd64/trap.c#71 (text+ko) ====

@@ -393,6 +393,20 @@
 				frame.tf_rip = (long)doreti_iret_fault;
 				goto out;
 			}
+			/*
+			 * Handle invalid userland selectors causing a trap
+			 * by turning it onto a SIGBUS.
+			 */
+			if (frame.tf_rip == (long)load_gs_load) {
+				ucode = code + BUS_SEGM_FAULT;
+				i = SIGBUS;
+				goto out;
+			}
+			/*
+			 * Handle things like users passing non-canonical
+			 * pointers to syscalls which will cause a GPF during
+			 * copyin etc.
+			 */
 			if (PCPU_GET(curpcb)->pcb_onfault != NULL) {
 				frame.tf_rip =
 				    (long)PCPU_GET(curpcb)->pcb_onfault;

==== //depot/projects/hammer/sys/amd64/amd64/vm_machdep.c#78 (text+ko) ====

@@ -69,6 +69,7 @@
 #include <machine/cpu.h>
 #include <machine/md_var.h>
 #include <machine/pcb.h>
+#include <machine/specialreg.h>
 
 #include <vm/vm.h>
 #include <vm/vm_extern.h>

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

@@ -514,47 +514,17 @@
 	__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");
+        __asm __volatile("movl %0,%%fs" : : "rm" (sel));
 }
 
-#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");
-}
+#ifdef _KERNEL
+/* In assembler so we can recover from traps */
+void load_gs(u_int sel);
 #else
-/* Usable by userland */
-static __inline void
-load_fs(u_int sel)
-{
-	__asm __volatile("movl %0,%%fs" : : "rm" (sel));
-}
-
 static __inline void
 load_gs(u_int sel)
 {

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

@@ -64,6 +64,7 @@
 void	cpu_setregs(void);
 void	doreti_iret(void) __asm(__STRING(doreti_iret));
 void	doreti_iret_fault(void) __asm(__STRING(doreti_iret_fault));
+void	load_gs_load(void) __asm(__STRING(load_gs_load));
 void	initializecpu(void);
 void	fillw(int /*u_short*/ pat, void *base, size_t cnt);
 void	fpstate_drop(struct thread *td);



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