Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F156456723
D50482.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D50482.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D50482: amd64: add pcb_tlsbase
Attached
Detach File
Event Timeline
Log In to Comment