On Fri, May 30, 2025 at 09:36:39AM +0200, Herbert J. Skuhra wrote:
> Hi,
> 
> building lang/go (e.g. 1.24) and go ports (e.g. aerc, netbird) on main
> (amd64) fails with: fatal: bad g in signal handler. 
> Arm64 seems to be OK.

I might have a guess.  Try the following untested patch, you need to rebuild
at least kernel, but ideally both kernel and userspace.  Also it is amd64-only.

diff --git a/lib/libthr/thread/thr_create.c b/lib/libthr/thread/thr_create.c
index 2ae7cf0cd7b2..84bbd36ed28d 100644
--- a/lib/libthr/thread/thr_create.c
+++ b/lib/libthr/thread/thr_create.c
@@ -160,7 +160,7 @@ _pthread_create(pthread_t * __restrict thread,
 	param.tls_size = sizeof(struct tcb);
 	param.child_tid = &new_thread->tid;
 	param.parent_tid = &new_thread->tid;
-	param.flags = 0;
+	param.flags = THR_C_RUNTIME;
 	if (new_thread->attr.flags & PTHREAD_SCOPE_SYSTEM)
 		param.flags |= THR_SYSTEM_SCOPE;
 	if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED)
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index 4001f40554af..c763ff58680e 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -60,6 +60,7 @@
 #include <sys/smp.h>
 #include <sys/sysctl.h>
 #include <sys/sysent.h>
+#include <sys/thr.h>
 #include <sys/unistd.h>
 #include <sys/vnode.h>
 #include <sys/vmmeter.h>
@@ -164,6 +165,7 @@ copy_thread(struct thread *td1, struct thread *td2)
 		MPASS((pcb2->pcb_flags & (PCB_KERNFPU | PCB_KERNFPU_THR)) == 0);
 		bcopy(get_pcb_user_save_td(td1), get_pcb_user_save_pcb(pcb2),
 		    cpu_max_ext_state_size);
+		clear_pcb_flags(pcb2, PCB_TLSBASE);
 	}
 
 	td2->td_frame = (struct trapframe *)td2->td_md.md_stack_base - 1;
@@ -655,7 +657,7 @@ cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg,
 }
 
 int
-cpu_set_user_tls(struct thread *td, void *tls_base)
+cpu_set_user_tls(struct thread *td, void *tls_base, int thr_flags)
 {
 	struct pcb *pcb;
 
@@ -663,7 +665,8 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
 		return (EINVAL);
 
 	pcb = td->td_pcb;
-	set_pcb_flags(pcb, PCB_FULL_IRET | PCB_TLSBASE);
+	set_pcb_flags(pcb, PCB_FULL_IRET | ((thr_flags &
+	    THR_C_RUNTIME) != 0 ? PCB_TLSBASE : 0));
 #ifdef COMPAT_FREEBSD32
 	if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
 		pcb->pcb_gsbase = (register_t)tls_base;
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index 0ab4cb5f7970..afd016ec9e75 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -169,7 +169,7 @@ thr_new_initthr(struct thread *td, void *thunk)
 	if (error != 0)
 		return (error);
 	/* Setup user TLS address and TLS pointer register. */
-	return (cpu_set_user_tls(td, param->tls_base));
+	return (cpu_set_user_tls(td, param->tls_base, param->flags));
 }
 
 int
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index eb0b66618a9d..fcacfec4442b 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1236,7 +1236,7 @@ int	cpu_procctl(struct thread *td, int idtype, id_t id, int com,
 void	cpu_set_syscall_retval(struct thread *, int);
 int	cpu_set_upcall(struct thread *, void (*)(void *), void *,
 	    stack_t *);
-int	cpu_set_user_tls(struct thread *, void *tls_base);
+int	cpu_set_user_tls(struct thread *, void *tls_base, int flags);
 void	cpu_thread_alloc(struct thread *);
 void	cpu_thread_clean(struct thread *);
 void	cpu_thread_exit(struct thread *);
diff --git a/sys/sys/thr.h b/sys/sys/thr.h
index 5e83ec208f07..54766668c929 100644
--- a/sys/sys/thr.h
+++ b/sys/sys/thr.h
@@ -43,6 +43,7 @@ typedef __size_t	size_t;
 #define	THR_SUSPENDED		0x0001
 /* Create the system scope thread. */
 #define	THR_SYSTEM_SCOPE	0x0002
+#define	THR_C_RUNTIME		0x0004
 
 struct thr_param {
     void	(*start_func)(void *);	/* thread entry function. */

Reply via email to