git: cb089f00996c - stable/14 - amd64: add pcb_tlsbase
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 12 Jun 2025 18:02:58 UTC
The branch stable/14 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=cb089f00996cdbf2e7930b4e5598fcbbd43aae53
commit cb089f00996cdbf2e7930b4e5598fcbbd43aae53
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-05-19 23:56:37 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-06-12 18:02:49 +0000
amd64: add pcb_tlsbase
(cherry picked from commit 68ba38dad388b566877ba79ff02ed12a53b0ff3f)
---
sys/amd64/amd64/exec_machdep.c | 6 ++++--
sys/amd64/amd64/sys_machdep.c | 17 ++++++++++++++++-
sys/amd64/amd64/vm_machdep.c | 8 ++++----
sys/amd64/ia32/ia32_signal.c | 1 +
sys/amd64/include/pcb.h | 4 +++-
sys/amd64/linux/linux_sysvec.c | 2 +-
sys/amd64/linux32/linux32_sysvec.c | 7 ++++---
sys/x86/include/sysarch.h | 2 ++
8 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/sys/amd64/amd64/exec_machdep.c b/sys/amd64/amd64/exec_machdep.c
index cf635d822300..71e33e5b14c1 100644
--- a/sys/amd64/amd64/exec_machdep.c
+++ b/sys/amd64/amd64/exec_machdep.c
@@ -211,6 +211,8 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
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);
}
@@ -381,9 +383,9 @@ exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
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
index 39c89e2aad87..2acf410b9b1b 100644
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -208,6 +208,8 @@ sysarch(struct thread *td, struct sysarch_args *uap)
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:
@@ -313,14 +315,27 @@ sysarch(struct thread *td, struct sysarch_args *uap)
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
index 36001bc5b5b6..8a2705a38c46 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -158,7 +158,7 @@ copy_thread(struct thread *td1, struct thread *td2)
/* 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);
@@ -184,7 +184,7 @@ copy_thread(struct thread *td1, struct thread *td2)
* 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;
@@ -675,13 +675,13 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
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
index b793c66a95ad..08f8d73c2334 100644
--- a/sys/amd64/ia32/ia32_signal.c
+++ b/sys/amd64/ia32/ia32_signal.c
@@ -959,4 +959,5 @@ ia32_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
/* 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
index 2205607fa6fe..632181c1f75a 100644
--- a/sys/amd64/include/pcb.h
+++ b/sys/amd64/include/pcb.h
@@ -86,6 +86,7 @@ struct pcb {
#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;
@@ -106,7 +107,8 @@ struct pcb {
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
index 9c3d7e6405c1..3760a5455a73 100644
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -247,7 +247,7 @@ linux_exec_setregs(struct thread *td, struct image_params *imgp,
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
index 19b4af7661f0..a8cc03ea8c71 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -580,6 +580,10 @@ linux_exec_setregs(struct thread *td, struct image_params *imgp,
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 @@ linux_exec_setregs(struct thread *td, struct image_params *imgp,
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
index 3226f3b9d93a..61f559f4bd23 100644
--- 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