diff options
author | peter <peter@FreeBSD.org> | 2003-05-15 00:23:40 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2003-05-15 00:23:40 +0000 |
commit | 12d7e4bee670b00c658676727ee630be6fbb7af1 (patch) | |
tree | 1cae0c59e2d1157890a9bc0eb09af3e021373ef6 /sys/amd64/include | |
parent | 7208ad8cbbe97024b739c1267077266cf9792ad3 (diff) | |
download | FreeBSD-src-12d7e4bee670b00c658676727ee630be6fbb7af1.zip FreeBSD-src-12d7e4bee670b00c658676727ee630be6fbb7af1.tar.gz |
Collect the nastiness for preserving the kernel MSR_GSBASE around the
load_gs() calls into a single place that is less likely to go wrong.
Eliminate the per-process context switching of MSR_GSBASE, because it
should be constant for a single cpu. Instead, save/restore it during
the loading of the new %gs selector for the new process.
Approved by: re (amd64/* blanket)
Diffstat (limited to 'sys/amd64/include')
-rw-r--r-- | sys/amd64/include/cpufunc.h | 36 | ||||
-rw-r--r-- | sys/amd64/include/pcb.h | 1 |
2 files changed, 36 insertions, 1 deletions
diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h index 21257dd..5d4c0dc 100644 --- a/sys/amd64/include/cpufunc.h +++ b/sys/amd64/include/cpufunc.h @@ -475,6 +475,41 @@ load_es(u_int sel) __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 @@ load_gs(u_int sel) { __asm __volatile("movl %0,%%gs" : : "rm" (sel)); } +#endif /* void lidt(struct region_descriptor *addr); */ static __inline void diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h index 5bfb41f..83d308f 100644 --- a/sys/amd64/include/pcb.h +++ b/sys/amd64/include/pcb.h @@ -59,7 +59,6 @@ struct pcb { register_t pcb_rflags; register_t pcb_fsbase; register_t pcb_gsbase; - register_t pcb_kgsbase; u_int32_t pcb_ds; u_int32_t pcb_es; u_int32_t pcb_fs; |