summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2018-01-06 22:03:13 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2018-01-06 22:03:13 +0000
commit5213f26b97b8228cd98d4ed7ed090ac651204b1b (patch)
treec7841fb7178685edc414912004f013aa5ae121a1 /sys
parent7f80d5805c4f4bd667df787ff0b8913b5d8bf4a2 (diff)
Handle %gs like %[def]s and reset set it in cpu_switchto() instead of on
every return to userspace. ok kettenis@ mlarkin@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/amd64/amd64/locore.S8
-rw-r--r--sys/arch/amd64/amd64/machdep.c20
-rw-r--r--sys/arch/amd64/include/frameasm.h8
3 files changed, 20 insertions, 16 deletions
diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S
index 5a2450b1164..2b85fc65dab 100644
--- a/sys/arch/amd64/amd64/locore.S
+++ b/sys/arch/amd64/amd64/locore.S
@@ -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:
/*
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 33bef001d4f..33d1d38395b 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -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)));
}
}
diff --git a/sys/arch/amd64/include/frameasm.h b/sys/arch/amd64/include/frameasm.h
index b48d11f4e2d..88309d1dd4f 100644
--- a/sys/arch/amd64/include/frameasm.h
+++ b/sys/arch/amd64/include/frameasm.h
@@ -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
@@ -65,10 +65,8 @@
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