Page MenuHomeFreeBSD

D50482.diff
No OneTemporary

D50482.diff

diff --git a/sys/amd64/amd64/exec_machdep.c b/sys/amd64/amd64/exec_machdep.c
--- a/sys/amd64/amd64/exec_machdep.c
+++ b/sys/amd64/amd64/exec_machdep.c
@@ -209,6 +209,8 @@
regs->tf_fs = _ufssel;
regs->tf_gs = _ugssel;
regs->tf_flags = TF_HASSEGS;
+ if ((pcb->pcb_flags & PCB_TLSBASE) != 0)
+ pcb->pcb_fsbase = pcb->pcb_tlsbase;
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
@@ -379,9 +381,9 @@
user_ldt_free(td);
update_pcb_bases(pcb);
- pcb->pcb_fsbase = 0;
+ pcb->pcb_fsbase = pcb->pcb_tlsbase = 0;
pcb->pcb_gsbase = 0;
- clear_pcb_flags(pcb, PCB_32BIT);
+ clear_pcb_flags(pcb, PCB_32BIT | PCB_TLSBASE);
pcb->pcb_initial_fpucw = __INITIAL_FPUCW__;
saved_rflags = regs->tf_rflags & PSL_T;
diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -206,6 +206,8 @@
case AMD64_GET_XFPUSTATE:
case AMD64_SET_PKRU:
case AMD64_CLEAR_PKRU:
+ case AMD64_GET_TLSBASE:
+ case AMD64_SET_TLSBASE:
break;
case I386_SET_IOPERM:
@@ -311,14 +313,27 @@
error = copyout(&pcb->pcb_fsbase, uap->parms,
sizeof(pcb->pcb_fsbase));
break;
+ case AMD64_GET_TLSBASE:
+ if ((pcb->pcb_flags & PCB_TLSBASE) == 0) {
+ error = ESRCH;
+ } else {
+ error = copyout(&pcb->pcb_tlsbase, uap->parms,
+ sizeof(pcb->pcb_tlsbase));
+ }
+ break;
case AMD64_SET_FSBASE:
+ case AMD64_SET_TLSBASE:
error = copyin(uap->parms, &a64base, sizeof(a64base));
if (error == 0) {
if (a64base < curproc->p_sysent->sv_maxuser) {
set_pcb_flags(pcb, PCB_FULL_IRET);
pcb->pcb_fsbase = a64base;
td->td_frame->tf_fs = _ufssel;
+ if (uap->op == AMD64_SET_TLSBASE) {
+ pcb->pcb_tlsbase = a64base;
+ set_pcb_flags(pcb, PCB_TLSBASE);
+ }
} else
error = EINVAL;
}
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -156,7 +156,7 @@
/* Kernel threads start with clean FPU and segment bases. */
if ((td2->td_pflags & TDP_KTHREAD) != 0) {
- pcb2->pcb_fsbase = 0;
+ pcb2->pcb_fsbase = pcb2->pcb_tlsbase = 0;
pcb2->pcb_gsbase = 0;
clear_pcb_flags(pcb2, PCB_FPUINITDONE | PCB_USERFPUINITDONE |
PCB_KERNFPU | PCB_KERNFPU_THR);
@@ -182,7 +182,7 @@
* pcb2->pcb_savefpu: cloned above.
* pcb2->pcb_flags: cloned above.
* pcb2->pcb_onfault: cloned above (always NULL here?).
- * pcb2->pcb_[fg]sbase: cloned above
+ * pcb2->pcb_[f,g,tls]sbase: cloned above
*/
pcb2->pcb_tssp = NULL;
@@ -663,14 +663,14 @@
return (EINVAL);
pcb = td->td_pcb;
- set_pcb_flags(pcb, PCB_FULL_IRET);
+ set_pcb_flags(pcb, PCB_FULL_IRET | PCB_TLSBASE);
#ifdef COMPAT_FREEBSD32
if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
pcb->pcb_gsbase = (register_t)tls_base;
return (0);
}
#endif
- pcb->pcb_fsbase = (register_t)tls_base;
+ pcb->pcb_fsbase = pcb->pcb_tlsbase = (register_t)tls_base;
return (0);
}
diff --git a/sys/amd64/ia32/ia32_signal.c b/sys/amd64/ia32/ia32_signal.c
--- a/sys/amd64/ia32/ia32_signal.c
+++ b/sys/amd64/ia32/ia32_signal.c
@@ -958,4 +958,5 @@
/* Return via doreti so that we can change to a different %cs */
set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET);
+ clear_pcb_flags(pcb, PCB_TLSBASE);
}
diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h
--- a/sys/amd64/include/pcb.h
+++ b/sys/amd64/include/pcb.h
@@ -84,6 +84,7 @@
#define PCB_KERNFPU_THR 0x0020 /* fpu_kern_thread() */
#define PCB_32BIT 0x0040 /* process has 32 bit context (segs etc) */
#define PCB_FPUNOSAVE 0x0080 /* no save area for current FPU ctx */
+#define PCB_TLSBASE 0x0100 /* tlsbase was set */
uint16_t pcb_initial_fpucw;
@@ -104,7 +105,8 @@
struct savefpu *pcb_save;
- uint64_t pcb_pad[5];
+ register_t pcb_tlsbase; /* not same as pcb_fsbase */
+ uint64_t pcb_pad[4];
};
/* Per-CPU state saved during suspend and resume. */
diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -247,7 +247,7 @@
pcb->pcb_fsbase = 0;
pcb->pcb_gsbase = 0;
- clear_pcb_flags(pcb, PCB_32BIT);
+ clear_pcb_flags(pcb, PCB_32BIT | PCB_TLSBASE);
pcb->pcb_initial_fpucw = __LINUX_NPXCW__;
set_pcb_flags(pcb, PCB_FULL_IRET);
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -580,6 +580,10 @@
if (td->td_proc->p_md.md_ldt != NULL)
user_ldt_free(td);
+ /* Do full restore on return so that we can change to a different %cs */
+ set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET);
+ clear_pcb_flags(pcb, PCB_TLSBASE);
+
critical_enter();
wrmsr(MSR_FSBASE, 0);
wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */
@@ -605,9 +609,6 @@
x86_clear_dbregs(pcb);
fpstate_drop(td);
-
- /* Do full restore on return so that we can change to a different %cs */
- set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET);
}
/*
diff --git a/sys/x86/include/sysarch.h b/sys/x86/include/sysarch.h
--- a/sys/x86/include/sysarch.h
+++ b/sys/x86/include/sysarch.h
@@ -61,6 +61,8 @@
#define AMD64_GET_XFPUSTATE 132
#define AMD64_SET_PKRU 133
#define AMD64_CLEAR_PKRU 134
+#define AMD64_GET_TLSBASE 135
+#define AMD64_SET_TLSBASE 136
/* Flags for AMD64_SET_PKRU */
#define AMD64_PKRU_EXCL 0x0001

File Metadata

Mime Type
text/plain
Expires
Thu, May 14, 7:41 PM (20 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33057090
Default Alt Text
D50482.diff (5 KB)

Event Timeline