Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151293688
D50482.id155906.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D50482.id155906.diff
View Options
diff --git a/lib/libsys/amd64/Makefile.sys b/lib/libsys/amd64/Makefile.sys
--- a/lib/libsys/amd64/Makefile.sys
+++ b/lib/libsys/amd64/Makefile.sys
@@ -3,6 +3,7 @@
amd64_get_gsbase.c \
amd64_set_fsbase.c \
amd64_set_gsbase.c \
+ amd64_set_tlsbase.c \
rfork_thread.S
MDASM= vfork.S cerror.S getcontext.S
diff --git a/lib/libsys/amd64/Symbol.sys.map b/lib/libsys/amd64/Symbol.sys.map
--- a/lib/libsys/amd64/Symbol.sys.map
+++ b/lib/libsys/amd64/Symbol.sys.map
@@ -13,6 +13,10 @@
x86_pkru_unprotect_range;
};
+FBSD_1.8 {
+ amd64_set_tlsbase;
+};
+
FBSDprivate_1.0 {
_vfork;
};
diff --git a/lib/libsys/amd64/amd64_set_tlsbase.c b/lib/libsys/amd64/amd64_set_tlsbase.c
new file mode 100644
--- /dev/null
+++ b/lib/libsys/amd64/amd64_set_tlsbase.c
@@ -0,0 +1,51 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define _WANT_P_OSREL
+#include <sys/param.h>
+#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
+#include <machine/sysarch.h>
+#include <x86/ifunc.h>
+#include "libc_private.h"
+
+static int
+amd64_set_tlsbase_syscall(void *addr)
+{
+ return (sysarch(AMD64_SET_TLSBASE, &addr));
+}
+
+DEFINE_UIFUNC(, int, amd64_set_tlsbase, (void *))
+{
+ if (__getosreldate() >= P_OSREL_TLSBASE)
+ return (amd64_set_tlsbase_syscall);
+ return (amd64_set_fsbase);
+}
diff --git a/libexec/rtld-elf/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c
--- a/libexec/rtld-elf/amd64/reloc.c
+++ b/libexec/rtld-elf/amd64/reloc.c
@@ -543,10 +543,12 @@
addr = allocate_tls(objs, 0, TLS_TCB_SIZE, TLS_TCB_ALIGN);
/*
- * This does not use _tcb_set() as it calls amd64_set_fsbase()
+ * This does not use _tcb_set() as it calls amd64_set_tlsbase()
* which is an ifunc and rtld must not use ifuncs.
*/
- if (__getosreldate() >= P_OSREL_WRFSBASE &&
+ if (__getosreldate() >= P_OSREL_TLSBASE)
+ sysarch(AMD64_SET_TLSBASE, &addr);
+ else if (__getosreldate() >= P_OSREL_WRFSBASE &&
(cpu_stdext_feature & CPUID_STDEXT_FSGSBASE) != 0)
wrfsbase((uintptr_t)addr);
else
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/ptrace_machdep.c b/sys/amd64/amd64/ptrace_machdep.c
--- a/sys/amd64/amd64/ptrace_machdep.c
+++ b/sys/amd64/amd64/ptrace_machdep.c
@@ -368,6 +368,27 @@
cpu_ptrace_setbase(td, req, rv);
break;
+ case PT_GETTLSBASE:
+ pcb = td->td_pcb;
+ if ((pcb->pcb_flags & PCB_TLSBASE) != 0)
+ error = copyout(&pcb->pcb_tlsbase, addr, sizeof(*r));
+ else
+ error = ESRCH;
+ break;
+
+ case PT_SETTLSBASE:
+ pcb = td->td_pcb;
+ error = copyin(addr, &rv, sizeof(rv));
+ if (error != 0)
+ break;
+ if (rv >= td->td_proc->p_sysent->sv_maxuser) {
+ error = EINVAL;
+ break;
+ }
+ pcb->pcb_tlsbase = rv;
+ set_pcb_flags(pcb, PCB_TLSBASE);
+ break;
+
default:
error = EINVAL;
break;
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/sys/param.h b/sys/sys/param.h
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -73,7 +73,7 @@
* cannot include sys/param.h and should only be updated here.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1500043
+#define __FreeBSD_version 1500044
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
@@ -106,6 +106,7 @@
#define P_OSREL_POWERPC_NEW_AUX_ARGS 1300070
#define P_OSREL_TIDPID 1400079
#define P_OSREL_ARM64_SPSR 1400084
+#define P_OSREL_TLSBASE 1500044
#define P_OSREL_MAJOR(x) ((x) / 100000)
#endif
diff --git a/sys/x86/include/frame.h b/sys/x86/include/frame.h
--- a/sys/x86/include/frame.h
+++ b/sys/x86/include/frame.h
@@ -152,6 +152,7 @@
#define TF_HASSEGS 0x1
#define TF_HASBASES 0x2
#define TF_HASFPXSTATE 0x4
+#define TF_RESERV0 0x8 /* no tlsbase in the trapframe */
#endif /* __amd64__ */
#endif /* _MACHINE_FRAME_H_ */
diff --git a/sys/x86/include/ptrace.h b/sys/x86/include/ptrace.h
--- a/sys/x86/include/ptrace.h
+++ b/sys/x86/include/ptrace.h
@@ -54,6 +54,8 @@
#define PT_SETFSBASE (PT_FIRSTMACH + 8)
#define PT_GETGSBASE (PT_FIRSTMACH + 9)
#define PT_SETGSBASE (PT_FIRSTMACH + 10)
+#define PT_GETTLSBASE (PT_FIRSTMACH + 11)
+#define PT_SETTLSBASE (PT_FIRSTMACH + 12)
/* Argument structure for PT_GETXSTATE_INFO. */
struct ptrace_xstate_info {
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
diff --git a/sys/x86/include/tls.h b/sys/x86/include/tls.h
--- a/sys/x86/include/tls.h
+++ b/sys/x86/include/tls.h
@@ -69,7 +69,7 @@
_tcb_set(struct tcb *tcb)
{
#ifdef __amd64__
- amd64_set_fsbase(tcb);
+ amd64_set_tlsbase(tcb);
#else
i386_set_gsbase(tcb);
#endif
diff --git a/sys/x86/include/ucontext.h b/sys/x86/include/ucontext.h
--- a/sys/x86/include/ucontext.h
+++ b/sys/x86/include/ucontext.h
@@ -99,7 +99,9 @@
#define _MC_HASSEGS 0x1
#define _MC_HASBASES 0x2
#define _MC_HASFPXSTATE 0x4
-#define _MC_FLAG_MASK (_MC_HASSEGS | _MC_HASBASES | _MC_HASFPXSTATE)
+#define _MC_HASTLSBASE 0x8
+#define _MC_FLAG_MASK (_MC_HASSEGS | _MC_HASBASES | _MC_HASFPXSTATE | \
+ _MC_HASTLSBASE)
typedef struct __mcontext {
/*
@@ -158,7 +160,9 @@
__register_t mc_xfpustate;
__register_t mc_xfpustate_len;
- long mc_spare[4];
+ __register_t mc_tlsbase;
+
+ long mc_spare[3];
} mcontext_t;
#endif /* __amd64__ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 8, 9:30 AM (8 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31091660
Default Alt Text
D50482.id155906.diff (11 KB)
Attached To
Mode
D50482: amd64: add pcb_tlsbase
Attached
Detach File
Event Timeline
Log In to Comment