Handle %gs like %[def]s and reset set it in cpu_switchto() instead of on
authorguenther <guenther@openbsd.org>
Sat, 6 Jan 2018 22:03:12 +0000 (22:03 +0000)
committerguenther <guenther@openbsd.org>
Sat, 6 Jan 2018 22:03:12 +0000 (22:03 +0000)
every return to userspace.

ok kettenis@ mlarkin@

sys/arch/amd64/amd64/locore.S
sys/arch/amd64/amd64/machdep.c
sys/arch/amd64/include/frameasm.h

index 5a2450b..2b85fc6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: locore.S,v 1.91 2017/10/10 07:04:05 mlarkin Exp $     */
+/*     $OpenBSD: locore.S,v 1.92 2018/01/06 22:03:12 guenther Exp $    */
 /*     $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $     */
 
 /*
@@ -369,11 +369,15 @@ switch_exited:
        btrl    $CPUF_USERSEGS_BIT, CPUVAR(FLAGS)
        jnc     restore_saved
 
-       /* set %ds, %es, and %fs to expected value to prevent info leak */
+       /* set %ds, %es, %fs, and %gs to expected value to prevent info leak */
        movw    $(GSEL(GUDATA_SEL, SEL_UPL)),%ax
        movw    %ax,%ds
        movw    %ax,%es
        movw    %ax,%fs
+       cli                     /* block interrupts when on user GS.base */
+       swapgs                  /* switch from kernel to user GS.base */
+       movw    %ax,%gs         /* set %gs to UDATA and GS.base to 0 */
+       swapgs                  /* back to kernel GS.base */
 
 restore_saved:
        /*
index 33bef00..33d1d38 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: machdep.c,v 1.236 2017/12/11 05:27:40 deraadt Exp $   */
+/*     $OpenBSD: machdep.c,v 1.237 2018/01/06 22:03:12 guenther Exp $  */
 /*     $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
 
 /*-
@@ -999,25 +999,27 @@ dumpsys(void)
 
 /*
  * Force the userspace FS.base to be reloaded from the PCB on return from
- * the kernel, and reset most the segment registers (%ds, %es, and %fs)
+ * the kernel, and reset the segment registers (%ds, %es, %fs, and %gs)
  * to their expected userspace value.
  */
 void
 reset_segs(void)
 {
        /*
-        * Segment registers (%ds, %es, %fs, %gs) aren't in the trapframe.
-        * %gs is reset on return to userspace to avoid having to deal with
-        * swapgs; others are reset on context switch and here.  This
-        * operates like the cpu_switchto() sequence: if we haven't reset
-        * %[def]s already, do so now.
-        */
+        * This operates like the cpu_switchto() sequence: if we
+        * haven't reset %[defg]s already, do so now.
+       */
        if (curcpu()->ci_flags & CPUF_USERSEGS) {
                curcpu()->ci_flags &= ~CPUF_USERSEGS;
                __asm volatile(
                    "movw %%ax,%%ds\n\t"
                    "movw %%ax,%%es\n\t"
-                   "movw %%ax,%%fs" : : "a"(GSEL(GUDATA_SEL, SEL_UPL)));
+                   "movw %%ax,%%fs\n\t"
+                   "cli\n\t"           /* block intr when on user GS.base */
+                   "swapgs\n\t"        /* swap from kernel to user GS.base */
+                   "movw %%ax,%%gs\n\t"/* set %gs to UDATA and GS.base to 0 */
+                   "swapgs\n\t"        /* back to kernel GS.base */
+                   "sti" : : "a"(GSEL(GUDATA_SEL, SEL_UPL)));
        }
 }
 
index b48d11f..88309d1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: frameasm.h,v 1.10 2016/09/04 09:22:28 mpi Exp $       */
+/*     $OpenBSD: frameasm.h,v 1.11 2018/01/06 22:03:12 guenther Exp $  */
 /*     $NetBSD: frameasm.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $        */
 
 #ifndef _AMD64_MACHINE_FRAMEASM_H
        shrq    $32,%rdx                                                ; \
        movl    $MSR_FSBASE,%ecx                                        ; \
        wrmsr                                                           ; \
-99:    movw    $(GSEL(GUDATA_SEL, SEL_UPL)),%ax                        ; \
-       cli                                                             ; \
-       swapgs                                                          ; \
-       movw    %ax,%gs
+99:    cli                                                             ; \
+       swapgs
 
 #define        INTR_FAKE_TRAP  0xbadabada