aboutsummaryrefslogtreecommitdiff
path: root/kernel/arch
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/arch')
-rw-r--r--kernel/arch/aarch64/contextspfunc.S46
-rw-r--r--kernel/arch/aarch64/execregs.c226
-rw-r--r--kernel/arch/aarch64/execregs.h86
-rw-r--r--kernel/arch/aarch64/execsp.S99
-rw-r--r--kernel/arch/aarch64/h_execregs.S84
-rw-r--r--kernel/arch/aarch64/signalsphandler.S46
-rw-r--r--kernel/arch/aarch64/stack_pointer.h42
-rw-r--r--kernel/arch/aarch64/threadspfunc.S43
-rw-r--r--kernel/arch/alpha/contextspfunc.S50
-rw-r--r--kernel/arch/alpha/execsp.S106
-rw-r--r--kernel/arch/alpha/signalsphandler.S49
-rw-r--r--kernel/arch/alpha/stack_pointer.h35
-rw-r--r--kernel/arch/alpha/threadspfunc.S46
-rw-r--r--kernel/arch/arm/contextspfunc.S51
-rw-r--r--kernel/arch/arm/execsp.S119
-rw-r--r--kernel/arch/arm/signalsphandler.S51
-rw-r--r--kernel/arch/arm/stack_pointer.h35
-rw-r--r--kernel/arch/arm/threadspfunc.S43
-rw-r--r--kernel/arch/hppa/contextspfunc.S48
-rw-r--r--kernel/arch/hppa/execregs.c387
-rw-r--r--kernel/arch/hppa/execregs.h157
-rw-r--r--kernel/arch/hppa/execsp.S130
-rw-r--r--kernel/arch/hppa/h_execregs.S168
-rw-r--r--kernel/arch/hppa/signalsphandler.S46
-rw-r--r--kernel/arch/hppa/stack_pointer.h35
-rw-r--r--kernel/arch/hppa/threadspfunc.S43
-rw-r--r--kernel/arch/i386/contextspfunc.S56
-rw-r--r--kernel/arch/i386/execregs.c132
-rw-r--r--kernel/arch/i386/execregs.h69
-rw-r--r--kernel/arch/i386/execsp.S112
-rw-r--r--kernel/arch/i386/h_execregs.S85
-rw-r--r--kernel/arch/i386/signalsphandler.S56
-rw-r--r--kernel/arch/i386/stack_pointer.h35
-rw-r--r--kernel/arch/i386/threadspfunc.S43
-rw-r--r--kernel/arch/mips/contextspfunc.S53
-rw-r--r--kernel/arch/mips/execsp.S118
-rw-r--r--kernel/arch/mips/signalsphandler.S53
-rw-r--r--kernel/arch/mips/stack_pointer.h40
-rw-r--r--kernel/arch/mips/threadspfunc.S46
-rw-r--r--kernel/arch/riscv/contextspfunc.S45
-rw-r--r--kernel/arch/riscv/execsp.S100
-rw-r--r--kernel/arch/riscv/signalsphandler.S45
-rw-r--r--kernel/arch/riscv/stack_pointer.h35
-rw-r--r--kernel/arch/riscv/threadspfunc.S43
-rw-r--r--kernel/arch/sh3/asm.h58
-rw-r--r--kernel/arch/sh3/contextspfunc.S55
-rw-r--r--kernel/arch/sh3/execsp.S146
-rw-r--r--kernel/arch/sh3/h_execregs.S86
-rw-r--r--kernel/arch/sh3/signalsphandler.S61
-rw-r--r--kernel/arch/sh3/stack_pointer.h35
-rw-r--r--kernel/arch/sh3/threadspfunc.S41
-rw-r--r--kernel/arch/sparc/contextspfunc.S64
-rw-r--r--kernel/arch/sparc/execsp.S123
-rw-r--r--kernel/arch/sparc/signalsphandler.S62
-rw-r--r--kernel/arch/sparc/stack_pointer.h35
-rw-r--r--kernel/arch/sparc/threadspfunc.S45
-rw-r--r--kernel/arch/vax/execregs.c166
-rw-r--r--kernel/arch/vax/execregs.h77
-rw-r--r--kernel/arch/vax/h_execregs.S87
-rw-r--r--kernel/arch/x86_64/contextspfunc.S55
-rw-r--r--kernel/arch/x86_64/execregs.c156
-rw-r--r--kernel/arch/x86_64/execregs.h81
-rw-r--r--kernel/arch/x86_64/execsp.S111
-rw-r--r--kernel/arch/x86_64/h_execregs.S82
-rw-r--r--kernel/arch/x86_64/signalsphandler.S55
-rw-r--r--kernel/arch/x86_64/stack_pointer.h35
-rw-r--r--kernel/arch/x86_64/threadspfunc.S54
67 files changed, 5207 insertions, 0 deletions
diff --git a/kernel/arch/aarch64/contextspfunc.S b/kernel/arch/aarch64/contextspfunc.S
new file mode 100644
index 000000000000..9a4e3059a8e0
--- /dev/null
+++ b/kernel/arch/aarch64/contextspfunc.S
@@ -0,0 +1,46 @@
+/* $NetBSD: contextspfunc.S,v 1.2 2025/06/08 18:55:35 christos Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: contextspfunc.S,v 1.2 2025/06/08 18:55:35 christos Exp $")
+
+/*
+ * contextspfunc()
+ *
+ * makecontext(3) function. Store the stack pointer on entry at
+ * the global variable contextsp and call contextdone.
+ */
+ENTRY(contextspfunc)
+ mov x0, sp
+ adrp x1, _C_LABEL(contextsp)
+ str x0, [x1, :lo12:_C_LABEL(contextsp)]
+ b _C_LABEL(contextdone)
+END(contextspfunc)
diff --git a/kernel/arch/aarch64/execregs.c b/kernel/arch/aarch64/execregs.c
new file mode 100644
index 000000000000..4c7697fe98c7
--- /dev/null
+++ b/kernel/arch/aarch64/execregs.c
@@ -0,0 +1,226 @@
+/* $NetBSD: execregs.c,v 1.1 2025/02/27 00:55:31 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: execregs.c,v 1.1 2025/02/27 00:55:31 riastradh Exp $");
+
+#include "execregs.h"
+
+#include <errno.h>
+#include <spawn.h>
+#include <stddef.h>
+#include <unistd.h>
+
+extern char **environ;
+
+static unsigned long
+nonnull(unsigned long x)
+{
+
+ x |= x << 8;
+ x |= x << 16;
+ x |= x << 32;
+ return x;
+}
+
+int
+execregschild(char *path)
+{
+ /* x0: used to pass exec arg0, nonnull anyway (path) */
+ /* x1: used to pass exec arg1, nonnull anyway (argv) */
+ /* x2: used to pass exec arg2, nonnull anyway (environ) */
+ register long x3 __asm("x3") = nonnull(3);
+ register long x4 __asm("x4") = nonnull(4);
+ register long x5 __asm("x5") = nonnull(5);
+ register long x6 __asm("x6") = nonnull(6);
+ register long x7 __asm("x7") = nonnull(7);
+ register long x8 __asm("x8") = nonnull(8);
+ register long x9 __asm("x9") = nonnull(9);
+ register long x10 __asm("x10") = nonnull(10);
+ register long x11 __asm("x11") = nonnull(11);
+ register long x12 __asm("x12") = nonnull(12);
+ register long x13 __asm("x13") = nonnull(13);
+ register long x14 __asm("x14") = nonnull(14);
+ register long x15 __asm("x15") = nonnull(15);
+ register long x16 __asm("x16") = nonnull(16);
+ register long x17 __asm("x17") = nonnull(17);
+ register long x18 __asm("x18") = nonnull(18);
+ register long x19 __asm("x19") = nonnull(19);
+ register long x20 __asm("x20") = nonnull(20);
+ register long x21 __asm("x21") = nonnull(21);
+ register long x22 __asm("x22") = nonnull(22);
+ register long x23 __asm("x23") = nonnull(23);
+ register long x24 __asm("x24") = nonnull(24);
+ register long x25 __asm("x25") = nonnull(25);
+ register long x26 __asm("x26") = nonnull(26);
+ register long x27 __asm("x27") = nonnull(27);
+ register long x28 __asm("x28") = nonnull(28);
+ /* x29: frame pointer, nonnull anyway */
+ /* x30: link register, nonnull anyway */
+
+ char *argv[] = {path, NULL};
+ char **envp = environ;
+
+ /*
+ * Not perfect -- compiler might use some registers for
+ * stack/argument transfers, but all the arguments are nonnull
+ * so this is probably a good test anyway.
+ */
+ __asm volatile("" :
+ "+r"(x3),
+ "+r"(x4),
+ "+r"(x5),
+ "+r"(x6),
+ "+r"(x7),
+ "+r"(x8),
+ "+r"(x9),
+ "+r"(x10),
+ "+r"(x11),
+ "+r"(x12),
+ "+r"(x13),
+ "+r"(x14),
+ "+r"(x15),
+ "+r"(x16),
+ "+r"(x17)
+ :: "memory");
+ /* pacify gcc error: more than 30 operands in 'asm' */
+ __asm volatile("" :
+ "+r"(x18),
+ "+r"(x19),
+ "+r"(x20),
+ "+r"(x21),
+ "+r"(x22),
+ "+r"(x23),
+ "+r"(x24),
+ "+r"(x25),
+ "+r"(x26),
+ "+r"(x27),
+ "+r"(x28)
+ :: "memory");
+
+ return execve(path, argv, envp);
+}
+
+pid_t
+spawnregschild(char *path, int fd)
+{
+ /* x0: used to pass posix_spawn arg0, nonnull anyway (&pid) */
+ /* x1: used to pass posix_spawn arg1, nonnull anyway (path) */
+ /* x2: used to pass posix_spawn arg2, nonnull anyway (&fileacts) */
+ /* x3: used to pass posix_spawn arg3, nonnull anyway (&attr) */
+ /* x4: used to pass posix_spawn arg3, nonnull anyway (argv) */
+ /* x5: used to pass posix_spawn arg3, nonnull anyway (environ) */
+ register long x6 __asm("x6") = nonnull(6);
+ register long x7 __asm("x7") = nonnull(7);
+ register long x8 __asm("x8") = nonnull(8);
+ register long x9 __asm("x9") = nonnull(9);
+ register long x10 __asm("x10") = nonnull(10);
+ register long x11 __asm("x11") = nonnull(11);
+ register long x12 __asm("x12") = nonnull(12);
+ register long x13 __asm("x13") = nonnull(13);
+ register long x14 __asm("x14") = nonnull(14);
+ register long x15 __asm("x15") = nonnull(15);
+ register long x16 __asm("x16") = nonnull(16);
+ register long x17 __asm("x17") = nonnull(17);
+ register long x18 __asm("x18") = nonnull(18);
+ register long x19 __asm("x19") = nonnull(19);
+ register long x20 __asm("x20") = nonnull(20);
+ register long x21 __asm("x21") = nonnull(21);
+ register long x22 __asm("x22") = nonnull(22);
+ register long x23 __asm("x23") = nonnull(23);
+ register long x24 __asm("x24") = nonnull(24);
+ register long x25 __asm("x25") = nonnull(25);
+ register long x26 __asm("x26") = nonnull(26);
+ register long x27 __asm("x27") = nonnull(27);
+ register long x28 __asm("x28") = nonnull(28);
+ /* x29: frame pointer, nonnull anyway */
+ /* x30: link register, nonnull anyway */
+
+ char *argv[] = {path, NULL};
+ char **envp = environ;
+ posix_spawn_file_actions_t fileacts;
+ posix_spawnattr_t attr;
+ pid_t pid;
+ int error;
+
+ error = posix_spawn_file_actions_init(&fileacts);
+ if (error)
+ goto out;
+ error = posix_spawn_file_actions_adddup2(&fileacts, fd, STDOUT_FILENO);
+ if (error)
+ goto out;
+ error = posix_spawnattr_init(&attr);
+ if (error)
+ goto out;
+
+ /*
+ * Not perfect -- compiler might use some registers for
+ * stack/argument transfers, but all the arguments are nonnull
+ * so this is probably a good test anyway.
+ */
+ __asm volatile("" :
+ "+r"(x6),
+ "+r"(x7),
+ "+r"(x8),
+ "+r"(x9),
+ "+r"(x10),
+ "+r"(x11),
+ "+r"(x12),
+ "+r"(x13),
+ "+r"(x14),
+ "+r"(x15),
+ "+r"(x16),
+ "+r"(x17),
+ "+r"(x18),
+ "+r"(x19),
+ "+r"(x20)
+ :: "memory");
+ /* pacify gcc error: more than 30 operands in 'asm' */
+ __asm volatile("" :
+ "+r"(x21),
+ "+r"(x22),
+ "+r"(x23),
+ "+r"(x24),
+ "+r"(x25),
+ "+r"(x26),
+ "+r"(x27),
+ "+r"(x28)
+ :: "memory");
+
+ error = posix_spawn(&pid, path, &fileacts, &attr, argv, envp);
+ if (error)
+ goto out;
+
+out: posix_spawnattr_destroy(&attr);
+ posix_spawn_file_actions_destroy(&fileacts);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
diff --git a/kernel/arch/aarch64/execregs.h b/kernel/arch/aarch64/execregs.h
new file mode 100644
index 000000000000..471a3859c4d1
--- /dev/null
+++ b/kernel/arch/aarch64/execregs.h
@@ -0,0 +1,86 @@
+/* $NetBSD: execregs.h,v 1.1 2025/02/27 00:55:31 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_AARCH64_EXECREGS_H
+#define TESTS_KERNEL_ARCH_AARCH64_EXECREGS_H
+
+#include <sys/cdefs.h>
+
+#define NEXECREGS 31
+
+#ifndef _LOCORE
+
+#include <unistd.h>
+
+/*
+ * Ordered by struct reg in sys/arch/aarch64/include/reg.h for
+ * convenience of auditing. Must match h_execregs.S.
+ */
+static const char *const regname[] = {
+ "x0",
+ "x1",
+ /* x2: ps_strings */
+ "x3",
+ "x4",
+ "x5",
+ "x6",
+ "x7",
+ "x8",
+ "x9",
+ "x10",
+ "x11",
+ "x12",
+ "x13",
+ "x14",
+ "x15",
+ "x16",
+ "x17",
+ "x18",
+ "x19",
+ "x20",
+ "x21",
+ "x22",
+ "x23",
+ "x24",
+ "x25",
+ "x26",
+ "x27",
+ "x28",
+ "x29",
+ "x30",
+ "tpidr",
+};
+
+__CTASSERT(NEXECREGS == __arraycount(regname));
+
+int execregschild(char *);
+pid_t spawnregschild(char *, int);
+
+#endif /* _LOCORE */
+
+#endif /* TESTS_KERNEL_ARCH_AARCH64_EXECREGS_H */
diff --git a/kernel/arch/aarch64/execsp.S b/kernel/arch/aarch64/execsp.S
new file mode 100644
index 000000000000..52c1472afef6
--- /dev/null
+++ b/kernel/arch/aarch64/execsp.S
@@ -0,0 +1,99 @@
+/* $NetBSD: execsp.S,v 1.3 2025/06/04 19:25:45 christos Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: execsp.S,v 1.3 2025/06/04 19:25:45 christos Exp $")
+
+/*
+ * void execsp_start(void (*cleanup@x0)(void), void *obj_main@x1,
+ * struct ps_strings *ps_strings@x2)
+ *
+ * ELF entry point. Saves the stack pointer in startsp and defers
+ * to the usual csu __start routine.
+ */
+ENTRY(execsp_start)
+ mov x16, sp
+ adrp x17, _C_LABEL(startsp)
+ str x16, [x17, :lo12:_C_LABEL(startsp)]
+ b _C_LABEL(__start)
+END(execsp_start)
+
+/*
+ * void execsp_ctor(void)
+ *
+ * ELF constructor. Saves the stack pointer in ctorsp and
+ * returns.
+ */
+ENTRY(execsp_ctor)
+ mov x16, sp
+ adrp x17, _C_LABEL(ctorsp)
+ str x16, [x17, :lo12:_C_LABEL(ctorsp)]
+ ret
+END(execsp_ctor)
+
+ /* Make execsp_ctor a constructor. */
+ .section .init_array,"aw",%init_array
+ .p2align 3
+ .xword _C_LABEL(execsp_ctor)
+
+/*
+ * int main(int argc@x0, char **argv@x1, ...)
+ *
+ * Main function. Saves the stack pointer in mainsp and returns
+ * zero. We will call execsp_main in execsp_dtor once dtorsp has
+ * been initialized.
+ */
+ENTRY(main)
+ mov x16, sp
+ adrp x17, _C_LABEL(mainsp)
+ str x16, [x17, :lo12:_C_LABEL(mainsp)]
+ mov x0, #0
+ ret
+END(main)
+
+/*
+ * void execsp_dtor(void)
+ *
+ * ELF destructor. Saves the stack pointer in dtorsp and defers
+ * to the C execsp_main in h_execsp.c to report the stack pointers
+ * back to the t_signal_and_sp parent.
+ */
+ENTRY(execsp_dtor)
+ mov x16, sp
+ adrp x17, _C_LABEL(dtorsp)
+ str x16, [x17, :lo12:_C_LABEL(dtorsp)]
+ b _C_LABEL(execsp_main)
+END(execsp_dtor)
+
+ /* Make execsp_ctor a destructor. */
+ .section .fini_array,"aw",%fini_array
+ .p2align 3
+ .xword _C_LABEL(execsp_dtor)
diff --git a/kernel/arch/aarch64/h_execregs.S b/kernel/arch/aarch64/h_execregs.S
new file mode 100644
index 000000000000..f060911067f4
--- /dev/null
+++ b/kernel/arch/aarch64/h_execregs.S
@@ -0,0 +1,84 @@
+/* $NetBSD: h_execregs.S,v 1.2 2025/04/25 12:58:40 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <sys/syscall.h>
+
+#include <machine/asm.h>
+
+#include "execregs.h"
+
+ENTRY(execregs_start)
+ /* create a stack frame with NEXECREGS*8 bytes, aligned to 16-byte */
+ stp fp, lr, [sp, #-(16 + ((NEXECREGS*8 + 15)/16)*16)]!
+
+ /* store registers to buffer on stack */
+ stp x0, x1, [sp, #16] /* order matches execregs.h */
+ /* x2: ps_strings */
+ stp x3, x4, [sp, #(16 + 1*2*8)]
+ stp x5, x6, [sp, #(16 + 2*2*8)]
+ stp x7, x8, [sp, #(16 + 3*2*8)]
+ stp x9, x10, [sp, #(16 + 4*2*8)]
+ stp x11, x12, [sp, #(16 + 5*2*8)]
+ stp x13, x14, [sp, #(16 + 6*2*8)]
+ stp x15, x16, [sp, #(16 + 7*2*8)]
+ stp x17, x18, [sp, #(16 + 8*2*8)]
+ stp x19, x20, [sp, #(16 + 9*2*8)]
+ stp x21, x22, [sp, #(16 + 10*2*8)]
+ stp x23, x24, [sp, #(16 + 11*2*8)]
+ stp x25, x26, [sp, #(16 + 12*2*8)]
+ stp x27, x28, [sp, #(16 + 13*2*8)]
+ stp x29, x30, [sp, #(16 + 14*2*8)]
+ mrs x0, tpidr_el0
+ str x0, [sp, #(16 + 15*2*8)]
+
+ /* call write(STDOUT_FILENO, regs, sizeof(regs)) */
+ mov x0, #1 /* arg0 := STDOUT_FILENO */
+ add x1, sp, #16 /* arg1 := regs */
+ mov x2, #(NEXECREGS*8) /* arg2 := sizeof(regs) */
+ svc #SYS_write
+
+ b.cs 2f /* bail if write failed */
+ cmp x0, #(NEXECREGS*8) /* bail if wrote wrong # of bytes */
+ b.ne 2f
+
+ /* call exit(0) */
+ mov x0, #0 /* arg0 := 0 */
+1: svc #SYS_exit
+ brk #0xffff /* paranoia */
+
+2: /* call exit(127) */
+ mov x0, #127 /* arg0 := 127 */
+ b 1b
+END(execregs_start)
+
+/* main stub to simplify linking */
+ENTRY(main)
+ brk #0xffff
+END(main)
diff --git a/kernel/arch/aarch64/signalsphandler.S b/kernel/arch/aarch64/signalsphandler.S
new file mode 100644
index 000000000000..246ed383273d
--- /dev/null
+++ b/kernel/arch/aarch64/signalsphandler.S
@@ -0,0 +1,46 @@
+/* $NetBSD: signalsphandler.S,v 1.2 2025/06/08 18:55:35 christos Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: signalsphandler.S,v 1.2 2025/06/08 18:55:35 christos Exp $")
+
+/*
+ * signalsphandler(signo@x0)
+ *
+ * Signal handler. Store the stack pointer on entry at the global
+ * variable signalsp and return.
+ */
+ENTRY(signalsphandler)
+ mov x0, sp
+ adrp x1, _C_LABEL(signalsp)
+ str x0, [x1, :lo12:_C_LABEL(signalsp)]
+ ret
+END(signalsphandler)
diff --git a/kernel/arch/aarch64/stack_pointer.h b/kernel/arch/aarch64/stack_pointer.h
new file mode 100644
index 000000000000..3bd7e6f65335
--- /dev/null
+++ b/kernel/arch/aarch64/stack_pointer.h
@@ -0,0 +1,42 @@
+/* $NetBSD: stack_pointer.h,v 1.2 2025/04/20 22:31:00 riastradh Exp $ */
+
+/*
+ * Copyright (c) 2024 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_AARCH64_STACK_POINTER_H
+#define TESTS_KERNEL_ARCH_AARCH64_STACK_POINTER_H
+
+#define MISALIGN_SP \
+ __asm__ volatile ( \
+ "sub sp, sp, #8" \
+ )
+
+#define FIX_SP \
+ __asm__ volatile ( \
+ "add sp, sp, #8" \
+ )
+
+#endif /* TESTS_KERNEL_ARCH_AARCH64_STACK_POINTER_H */
diff --git a/kernel/arch/aarch64/threadspfunc.S b/kernel/arch/aarch64/threadspfunc.S
new file mode 100644
index 000000000000..90f779d5e961
--- /dev/null
+++ b/kernel/arch/aarch64/threadspfunc.S
@@ -0,0 +1,43 @@
+/* $NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $")
+
+/*
+ * void *threadspfunc(void *cookie@x0)
+ *
+ * pthread_create(3) function. Return the stack pointer on entry.
+ */
+ENTRY(threadspfunc)
+ mov x0, sp
+ ret
+END(threadspfunc)
diff --git a/kernel/arch/alpha/contextspfunc.S b/kernel/arch/alpha/contextspfunc.S
new file mode 100644
index 000000000000..da198f089124
--- /dev/null
+++ b/kernel/arch/alpha/contextspfunc.S
@@ -0,0 +1,50 @@
+/* $NetBSD: contextspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: contextspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $")
+
+ .set noat
+ .text
+
+/*
+ * contextspfunc()
+ *
+ * makecontext(3) function. Store the stack pointer on entry at
+ * the global variable contextsp and call contextdone.
+ */
+LEAF(contextspfunc, 1)
+ LDGP(pv)
+ ldq at_reg, contextsp(gp) !literal
+ stq sp, 0(at_reg)
+ ldq pv, contextdone(gp) !literal
+ jmp (pv), contextdone
+END(contextspfunc)
diff --git a/kernel/arch/alpha/execsp.S b/kernel/arch/alpha/execsp.S
new file mode 100644
index 000000000000..08eaa521fa03
--- /dev/null
+++ b/kernel/arch/alpha/execsp.S
@@ -0,0 +1,106 @@
+/* $NetBSD: execsp.S,v 1.2 2025/04/21 02:31:22 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: execsp.S,v 1.2 2025/04/21 02:31:22 riastradh Exp $")
+
+ .set noat
+ .text
+
+/*
+ * void execsp_start(void *stackpointer@a0, void (*cleanup@a1)(void),
+ * void *obj_main@a2, struct ps_strings *ps_strings@a3)
+ *
+ * ELF entry point. Saves the stack pointer in startsp and defers
+ * to the usual csu __start routine.
+ */
+LEAF(execsp_start, 4)
+ LDGP(pv)
+ ldq at_reg, startsp(gp) !literal
+ stq sp, 0(at_reg)
+ ldq pv, __start(gp) !literal
+ jmp (pv), __start
+END(execsp_start)
+
+/*
+ * void execsp_ctor(void)
+ *
+ * ELF constructor. Saves the stack pointer in ctorsp and
+ * returns.
+ */
+LEAF(execsp_ctor, 0)
+ LDGP(pv)
+ ldq at_reg, ctorsp(gp) !literal
+ stq sp, 0(at_reg)
+ RET
+END(execsp_ctor)
+
+ /* Make execsp_ctor a constructor. */
+ .pushsection .ctors,"aw",@progbits
+ .p2align 3
+ .quad execsp_ctor
+ .popsection
+
+/*
+ * int main(int argc@a0, char **argv@a1, ...)
+ *
+ * Main function. Saves the stack pointer in mainsp and returns
+ * zero. We will call execsp_main in execsp_dtor once dtorsp has
+ * been initialized.
+ */
+LEAF(main, 2)
+ LDGP(pv)
+ ldq at_reg, mainsp(gp) !literal
+ stq sp, 0(at_reg)
+ mov zero, v0
+ RET
+END(main)
+
+/*
+ * void execsp_dtor(void)
+ *
+ * ELF destructor. Saves the stack pointer in dtorsp and defers
+ * to the C execsp_main in h_execsp.c to report the stack pointers
+ * back to the t_signal_and_sp parent.
+ */
+LEAF(execsp_dtor, 0)
+ LDGP(pv)
+ ldq at_reg, dtorsp(gp) !literal
+ stq sp, 0(at_reg)
+ ldq pv, execsp_main(gp) !literal
+ jmp (pv), execsp_main
+END(execsp_dtor)
+
+ /* Make execsp_ctor a destructor. */
+ .pushsection .dtors,"aw",@progbits
+ .p2align 3
+ .quad execsp_dtor
+ .popsection
diff --git a/kernel/arch/alpha/signalsphandler.S b/kernel/arch/alpha/signalsphandler.S
new file mode 100644
index 000000000000..eaa3f2cdb654
--- /dev/null
+++ b/kernel/arch/alpha/signalsphandler.S
@@ -0,0 +1,49 @@
+/* $NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:31:57 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:31:57 riastradh Exp $")
+
+ .set noat
+ .text
+
+/*
+ * signalsphandler(signo@a0)
+ *
+ * Signal handler. Store the stack pointer on entry at the global
+ * variable signalsp and return.
+ */
+LEAF(signalsphandler, 1)
+ LDGP(pv)
+ ldq at_reg, signalsp(gp) !literal
+ stq sp, 0(at_reg)
+ RET
+END(signalsphandler)
diff --git a/kernel/arch/alpha/stack_pointer.h b/kernel/arch/alpha/stack_pointer.h
new file mode 100644
index 000000000000..58c581ffde0a
--- /dev/null
+++ b/kernel/arch/alpha/stack_pointer.h
@@ -0,0 +1,35 @@
+/* $NetBSD: stack_pointer.h,v 1.1 2025/04/20 22:31:57 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_ALPHA_STACK_POINTER_H
+#define TESTS_KERNEL_ARCH_ALPHA_STACK_POINTER_H
+
+#define MISALIGN_SP __asm __volatile("lda $sp,-1($sp)" ::: "memory")
+#define FIX_SP __asm __volatile("lda $sp,1($sp)" ::: "memory")
+
+#endif /* TESTS_KERNEL_ARCH_ALPHA_STACK_POINTER_H */
diff --git a/kernel/arch/alpha/threadspfunc.S b/kernel/arch/alpha/threadspfunc.S
new file mode 100644
index 000000000000..413387bb0867
--- /dev/null
+++ b/kernel/arch/alpha/threadspfunc.S
@@ -0,0 +1,46 @@
+/* $NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $")
+
+ .set noat
+ .text
+
+/*
+ * void *threadspfunc(void *cookie@a0)
+ *
+ * pthread_create(3) function. Return the stack pointer on entry.
+ */
+LEAF(threadspfunc, 1)
+ mov sp, v0
+ RET
+END(threadspfunc)
diff --git a/kernel/arch/arm/contextspfunc.S b/kernel/arch/arm/contextspfunc.S
new file mode 100644
index 000000000000..cf7fec19fb2a
--- /dev/null
+++ b/kernel/arch/arm/contextspfunc.S
@@ -0,0 +1,51 @@
+/* $NetBSD: contextspfunc.S,v 1.2 2025/05/07 16:26:47 uwe Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: contextspfunc.S,v 1.2 2025/05/07 16:26:47 uwe Exp $")
+
+/*
+ * contextspfunc()
+ *
+ * makecontext(3) function. Store the stack pointer on entry at
+ * the global variable contextsp and call contextdone.
+ */
+ENTRY(contextspfunc)
+0: GOT_INIT(r0, .Lgot)
+ mov r1, sp
+ GOT_GET(r2, r0, .Lcontextsp)
+ str r1, [r2]
+ b PLT_SYM(_C_LABEL(contextdone))
+
+ GOT_INITSYM(.Lgot, 0b)
+.Lcontextsp:
+ .word GOT_SYM(contextsp)
+END(contextspfunc)
diff --git a/kernel/arch/arm/execsp.S b/kernel/arch/arm/execsp.S
new file mode 100644
index 000000000000..b02587ef2b33
--- /dev/null
+++ b/kernel/arch/arm/execsp.S
@@ -0,0 +1,119 @@
+/* $NetBSD: execsp.S,v 1.4 2025/05/07 16:26:47 uwe Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: execsp.S,v 1.4 2025/05/07 16:26:47 uwe Exp $")
+
+/*
+ * void execsp_start(struct ps_strings *ps_strings@r0, void *obj_main@r1,
+ * void (*cleanup@r2)(void))
+ *
+ * ELF entry point. Saves the stack pointer in startsp and defers
+ * to the usual csu __start routine.
+ */
+ENTRY(execsp_start)
+0: GOT_INIT(r3, .Lgot.execsp_start)
+ mov r4, sp
+ GOT_GET(r5, r3, .Lstartsp)
+ str r4, [r5]
+ b PLT_SYM(_C_LABEL(__start))
+
+ GOT_INITSYM(.Lgot.execsp_start, 0b)
+.Lstartsp:
+ .word GOT_SYM(startsp)
+END(execsp_start)
+
+/*
+ * void execsp_ctor(void)
+ *
+ * ELF constructor. Saves the stack pointer in ctorsp and
+ * returns.
+ */
+ENTRY(execsp_ctor)
+0: GOT_INIT(r0, .Lgot.execsp_ctor)
+ mov r1, sp
+ GOT_GET(r2, r0, .Lctorsp)
+ str r1, [r2]
+ RET
+
+ GOT_INITSYM(.Lgot.execsp_ctor, 0b)
+.Lctorsp:
+ .word GOT_SYM(ctorsp)
+END(execsp_ctor)
+
+ /* Make execsp_ctor a constructor. */
+ .section .init_array,"aw",%init_array
+ .p2align 2
+ .word _C_LABEL(execsp_ctor)
+
+/*
+ * int main(int argc@r0, char **argv@r1, ...)
+ *
+ * Main function. Saves the stack pointer in mainsp and returns
+ * zero. We will call execsp_main in execsp_dtor once dtorsp has
+ * been initialized.
+ */
+ENTRY(main)
+0: GOT_INIT(r0, .Lgot.main)
+ mov r1, sp
+ GOT_GET(r2, r0, .Lmainsp)
+ str r1, [r2]
+ mov r0, #0
+ RET
+
+ GOT_INITSYM(.Lgot.main, 0b)
+.Lmainsp:
+ .word GOT_SYM(mainsp)
+END(main)
+
+/*
+ * void execsp_dtor(void)
+ *
+ * ELF destructor. Saves the stack pointer in dtorsp and defers
+ * to the C execsp_main in h_execsp.c to report the stack pointers
+ * back to the t_signal_and_sp parent.
+ */
+ENTRY(execsp_dtor)
+0: GOT_INIT(r0, .Lgot.execsp_dtor)
+ mov r1, sp
+ GOT_GET(r2, r0, .Ldtorsp)
+ str r1, [r2]
+ b PLT_SYM(_C_LABEL(execsp_main))
+
+ GOT_INITSYM(.Lgot.execsp_dtor, 0b)
+.Ldtorsp:
+ .word GOT_SYM(dtorsp)
+END(execsp_dtor)
+
+ /* Make execsp_ctor a destructor. */
+ .section .fini_array,"aw",%fini_array
+ .p2align 2
+ .word _C_LABEL(execsp_dtor)
diff --git a/kernel/arch/arm/signalsphandler.S b/kernel/arch/arm/signalsphandler.S
new file mode 100644
index 000000000000..21b7d26a53b9
--- /dev/null
+++ b/kernel/arch/arm/signalsphandler.S
@@ -0,0 +1,51 @@
+/* $NetBSD: signalsphandler.S,v 1.3 2025/05/07 16:26:47 uwe Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: signalsphandler.S,v 1.3 2025/05/07 16:26:47 uwe Exp $")
+
+/*
+ * signalsphandler(signo@r0)
+ *
+ * Signal handler. Store the stack pointer on entry at the global
+ * variable signalsp and return.
+ */
+ENTRY(signalsphandler)
+0: GOT_INIT(r0, .Lgot)
+ mov r1, sp
+ GOT_GET(r2, r0, .Lsignalsp)
+ str r1, [r2]
+ RET
+
+ GOT_INITSYM(.Lgot, 0b)
+.Lsignalsp:
+ .word GOT_SYM(signalsp)
+END(signalsphandler)
diff --git a/kernel/arch/arm/stack_pointer.h b/kernel/arch/arm/stack_pointer.h
new file mode 100644
index 000000000000..73d10c341138
--- /dev/null
+++ b/kernel/arch/arm/stack_pointer.h
@@ -0,0 +1,35 @@
+/* $NetBSD: stack_pointer.h,v 1.1 2025/04/25 02:24:01 riastradh Exp $ */
+
+/*
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_ARM_STACK_POINTER_H
+#define TESTS_KERNEL_ARCH_ARM_STACK_POINTER_H
+
+#define MISALIGN_SP __asm __volatile("sub sp, sp, #1")
+#define FIX_SP __asm __volatile("add sp, sp, #1")
+
+#endif /* TESTS_KERNEL_ARCH_ARM_STACK_POINTER_H */
diff --git a/kernel/arch/arm/threadspfunc.S b/kernel/arch/arm/threadspfunc.S
new file mode 100644
index 000000000000..5f34c547cadf
--- /dev/null
+++ b/kernel/arch/arm/threadspfunc.S
@@ -0,0 +1,43 @@
+/* $NetBSD: threadspfunc.S,v 1.1 2025/04/25 02:24:01 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: threadspfunc.S,v 1.1 2025/04/25 02:24:01 riastradh Exp $")
+
+/*
+ * void *threadspfunc(void *cookie@r0)
+ *
+ * pthread_create(3) function. Return the stack pointer on entry.
+ */
+ENTRY(threadspfunc)
+ mov r0, sp
+ RET
+END(threadspfunc)
diff --git a/kernel/arch/hppa/contextspfunc.S b/kernel/arch/hppa/contextspfunc.S
new file mode 100644
index 000000000000..683f59808c95
--- /dev/null
+++ b/kernel/arch/hppa/contextspfunc.S
@@ -0,0 +1,48 @@
+/* $NetBSD: contextspfunc.S,v 1.2 2025/04/21 12:06:08 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: contextspfunc.S,v 1.2 2025/04/21 12:06:08 riastradh Exp $")
+
+/*
+ * contextspfunc()
+ *
+ * makecontext(3) function. Store the stack pointer on entry at
+ * the global variable contextsp and call contextdone.
+ */
+LEAF_ENTRY(contextspfunc)
+ addil LT%_C_LABEL(contextdone), %r19 /* r20 := contextdone */
+ ldw RT%_C_LABEL(contextdone)(%r1), %r20
+ addil LT%_C_LABEL(contextsp), %r19 /* r21 := &contextsp */
+ ldw RT%_C_LABEL(contextsp)(%r1), %r21
+ bv %r0(%r20) /* jump to contextdone */
+ stw %sp, 0(%r21) /* contextsp := sp */
+EXIT(contextspfunc)
diff --git a/kernel/arch/hppa/execregs.c b/kernel/arch/hppa/execregs.c
new file mode 100644
index 000000000000..c064d3a36e37
--- /dev/null
+++ b/kernel/arch/hppa/execregs.c
@@ -0,0 +1,387 @@
+/* $NetBSD: execregs.c,v 1.2 2025/02/28 16:08:19 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: execregs.c,v 1.2 2025/02/28 16:08:19 riastradh Exp $");
+
+#include "execregs.h"
+
+#include <errno.h>
+#include <spawn.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <unistd.h>
+
+extern char **environ;
+
+static unsigned long
+nonnull(unsigned long x)
+{
+
+ x |= x << 8;
+ x |= x << 16;
+ return x;
+}
+
+/*
+ * setfpregs()
+ *
+ * Set up all the floating-point registers with something nonzero
+ * in each one. We initialize the floating-point status register
+ * to set various bits so it's not all zero, but nothing that
+ * would trigger traps.
+ */
+static void
+setfpregs(void)
+{
+ static const uint64_t fpe[] = {
+ (__BITS(63,59) /* all exception flags (VZOUI) set */
+ | __BIT(58) /* C bit (comparison) set */
+ | __BITS(54,43) /* CQ (comparison queue) all set */
+ | __SHIFTIN(1, __BITS(42,41)) /* round toward zero */
+ | __SHIFTIN(0, __BIT(38)) /* no delayed trap */
+ | __SHIFTIN(1, __BIT(37)) /* Denormalized As Zero */
+ | __SHIFTIN(0, __BITS(36,32)) /* exceptions masked */
+ | 0x10101010),
+ 0x9191919111111111,
+ 0x9292929212121212,
+ 0x9393939313131313,
+ };
+ const uint64_t *fpep = fpe;
+
+ static const double fr[28] = {
+ 0x1.04p0, 0x1.05p0, 0x1.06p0, 0x1.07p0,
+ 0x1.08p0, 0x1.09p0, 0x1.0ap0, 0x1.0bp0,
+ 0x1.0cp0, 0x1.0dp0, 0x1.0ep0, 0x1.0fp0,
+ 0x1.10p0, 0x1.11p0, 0x1.12p0, 0x1.13p0,
+ 0x1.14p0, 0x1.15p0, 0x1.16p0, 0x1.17p0,
+ 0x1.18p0, 0x1.19p0, 0x1.1ap0, 0x1.1bp0,
+ 0x1.1cp0, 0x1.1dp0, 0x1.1ep0, 0x1.1fp0,
+ };
+ const double *frp = fr;
+
+ __asm volatile(
+ "fldds,ma 8(%0), %%fr0\n\t"
+ "fldds,ma 8(%0), %%fr1\n\t"
+ "fldds,ma 8(%0), %%fr2\n\t"
+ "fldds 0(%0), %%fr3"
+ : "+r"(fpep)
+ : "m"(fpe));
+
+ __asm volatile(
+ "fldds,ma 8(%0), %%fr4\n\t"
+ "fldds,ma 8(%0), %%fr5\n\t"
+ "fldds,ma 8(%0), %%fr6\n\t"
+ "fldds,ma 8(%0), %%fr7\n\t"
+ "fldds,ma 8(%0), %%fr8\n\t"
+ "fldds,ma 8(%0), %%fr9\n\t"
+ "fldds,ma 8(%0), %%fr10\n\t"
+ "fldds,ma 8(%0), %%fr11\n\t"
+ "fldds,ma 8(%0), %%fr12\n\t"
+ "fldds,ma 8(%0), %%fr13\n\t"
+ "fldds,ma 8(%0), %%fr14\n\t"
+ "fldds,ma 8(%0), %%fr15\n\t"
+ "fldds,ma 8(%0), %%fr16\n\t"
+ "fldds,ma 8(%0), %%fr17\n\t"
+ "fldds,ma 8(%0), %%fr18\n\t"
+ "fldds,ma 8(%0), %%fr19\n\t"
+ "fldds,ma 8(%0), %%fr20\n\t"
+ "fldds,ma 8(%0), %%fr21\n\t"
+ "fldds,ma 8(%0), %%fr22\n\t"
+ "fldds,ma 8(%0), %%fr23\n\t"
+ "fldds,ma 8(%0), %%fr24\n\t"
+ "fldds,ma 8(%0), %%fr25\n\t"
+ "fldds,ma 8(%0), %%fr26\n\t"
+ "fldds,ma 8(%0), %%fr27\n\t"
+ "fldds,ma 8(%0), %%fr28\n\t"
+ "fldds,ma 8(%0), %%fr29\n\t"
+ "fldds,ma 8(%0), %%fr30\n\t"
+ "fldds 0(%0), %%fr31"
+ : "+r"(frp)
+ : "m"(fr));
+}
+
+/*
+ * setpsw()
+ *
+ * Set some bits in PSW, the processor status word.
+ */
+static void
+setpsw(void)
+{
+ uint32_t x = 0xe0000000, y = 0xffffffff, sum;
+
+ /*
+ * Trigger some arithmetic that causes the carry/borrow
+ * (PSW[C/B]) bits to be set.
+ *
+ * XXX Also set PSW[V].
+ */
+ __asm volatile("sh3add %[sum], %[x], %[y]"
+ : /* outputs */ [sum] "=r"(sum)
+ : /* inputs */ [x] "r"(x), [y] "r"(y));
+}
+
+int
+execregschild(char *path)
+{
+ register long t1 __asm("r22") = nonnull(22);
+ register long t2 __asm("r21") = nonnull(21);
+ /* r30/sp: stack pointer */
+ register long t3 __asm("r20") = nonnull(20);
+ /* cr17/iisq_head: privileged */
+ /* cr17/iisq_tail: privileged */
+ /* cr18/iioq_head: privileged */
+ /* cr18/iioq_tail: privileged */
+ /* cr15/eiem: privileged */
+ /* cr22/ipsw: privileged */
+ /* sr3: privileged(?) */
+ /* cr8/pidr1: privileged */
+ /* cr20/isr: privileged */
+ /* cr21/ior: privileged */
+ /* cr19/iir: privileged */
+ /* flags: N/A(?) */
+ long sar = nonnull(0x8a); /* cr11 */
+ /* r1: ADDIL (add immediate left) result, nonnull anyway */
+ /* r2/rp: return pointer, nonnull anyway */
+ /* r3: frame pointer, nonnull anyway */
+ register long r4 __asm("r4") = nonnull(4);
+ register long r5 __asm("r5") = nonnull(5);
+ register long r6 __asm("r6") = nonnull(6);
+ register long r7 __asm("r7") = nonnull(7);
+ register long r8 __asm("r8") = nonnull(8);
+ register long r9 __asm("r9") = nonnull(9);
+ register long r10 __asm("r10") = nonnull(10);
+ register long r11 __asm("r11") = nonnull(11);
+ register long r12 __asm("r12") = nonnull(12);
+ register long r13 __asm("r13") = nonnull(13);
+ register long r14 __asm("r14") = nonnull(14);
+ register long r15 __asm("r15") = nonnull(15);
+ register long r16 __asm("r16") = nonnull(16);
+ register long r17 __asm("r17") = nonnull(17);
+ register long r18 __asm("r18") = nonnull(18);
+ register long t4 __asm("r19") = nonnull(19);
+ register long arg3 __asm("r23") = nonnull(23);
+ /* r24/arg2: envp, nonnull anyway */
+ /* r25/arg1: argv, nonnull anyway */
+ /* r26/arg0: path, nonnull anyway */
+ /* r27/dp: data pointer, nonnull anyway */
+ register long ret0 __asm("r28") = nonnull(28);
+ register long ret1 __asm("r29") = nonnull(29);
+ register long r31 __asm("r31") = nonnull(31);
+ /* sr0-sr7: space registers initialized by kernel */
+ /* cr9/pidr2: privileged */
+ /* cr12/pidr3: privileged */
+ /* cr13/pidr4: privileged */
+ /* cr0/rctr: privileged */
+ /* cr10/ccr: privileged */
+ /* cr23/eirr: privileged */
+ /* cr24: privileged */
+ /* cr25/vtop: privileged */
+ /* cr27/tr3: _lwp_private, thread-local storage -- nonnull anyway */
+ /* cr28: privileged */
+ /* cr30/fpregs: privileged */
+ /* cr31: privileged */
+
+ char *argv[] = {path, NULL};
+ char **envp = environ;
+
+ setfpregs();
+ setpsw();
+
+ /*
+ * Not perfect -- compiler might use some registers for
+ * stack/argument transfers, but all the arguments are nonnull
+ * so this is probably a good test anyway.
+ */
+ __asm volatile("mtctl %[sar], %%sar" /* cr11 */
+ : /* outputs */
+ : [sar] "r"(sar)
+ : "memory");
+ __asm volatile("" :
+ "+r"(t1),
+ "+r"(t2),
+ "+r"(t3),
+ "+r"(r4),
+ "+r"(r5),
+ "+r"(r6),
+ "+r"(r7),
+ "+r"(r8),
+ "+r"(r9),
+ "+r"(r10),
+ "+r"(r11),
+ "+r"(r12)
+ :: "memory");
+ /* pacify gcc error: more than 30 operands in 'asm' */
+ __asm volatile("" :
+ "+r"(r13),
+ "+r"(r14),
+ "+r"(r15),
+ "+r"(r16),
+ "+r"(r17),
+ "+r"(r18),
+ "+r"(t4),
+ "+r"(arg3),
+ "+r"(ret0),
+ "+r"(ret1),
+ "+r"(r31)
+ :: "memory");
+
+ return execve(path, argv, envp);
+}
+
+pid_t
+spawnregschild(char *path, int fd)
+{
+ register long t1 __asm("r22") = nonnull(22);
+ register long t2 __asm("r21") = nonnull(21);
+ /* r30/sp: stack pointer */
+ register long t3 __asm("r20") = nonnull(20);
+ /* cr17/iisq_head: privileged */
+ /* cr17/iisq_tail: privileged */
+ /* cr18/iioq_head: privileged */
+ /* cr18/iioq_tail: privileged */
+ /* cr15/eiem: privileged */
+ /* cr22/ipsw: privileged */
+ /* sr3: privileged(?) */
+ /* cr8/pidr1: privileged */
+ /* cr20/isr: privileged */
+ /* cr21/ior: privileged */
+ /* cr19/iir: privileged */
+ /* flags: N/A(?) */
+ long sar = nonnull(0x8a); /* cr11 */
+ /* r1: ADDIL (add immediate left) result, nonnull anyway */
+ /* r2/rp: return pointer, nonnull anyway */
+ /* r3: frame pointer, nonnull anyway */
+ register long r4 __asm("r4") = nonnull(4);
+ register long r5 __asm("r5") = nonnull(5);
+ register long r6 __asm("r6") = nonnull(6);
+ register long r7 __asm("r7") = nonnull(7);
+ register long r8 __asm("r8") = nonnull(8);
+ register long r9 __asm("r9") = nonnull(9);
+ register long r10 __asm("r10") = nonnull(10);
+ register long r11 __asm("r11") = nonnull(11);
+ register long r12 __asm("r12") = nonnull(12);
+ register long r13 __asm("r13") = nonnull(13);
+ register long r14 __asm("r14") = nonnull(14);
+ register long r15 __asm("r15") = nonnull(15);
+ register long r16 __asm("r16") = nonnull(16);
+ register long r17 __asm("r17") = nonnull(17);
+ register long r18 __asm("r18") = nonnull(18);
+ register long t4 __asm("r19") = nonnull(19);
+ /* r23/arg3: attrp, nonnull anyway */
+ /* r24/arg2: fileactsp, nonnull anyway */
+ /* r25/arg1: path, nonnull anyway */
+ /* r26/arg0: pidp, nonnull anyway */
+ /* r27/dp: data pointer, nonnull anyway */
+ register long ret0 __asm("r28") = nonnull(28);
+ register long ret1 __asm("r29") = nonnull(29);
+ register long r31 __asm("r31") = nonnull(31);
+ /* sr0-sr7: space registers initialized by kernel */
+ /* cr9/pidr2: privileged */
+ /* cr12/pidr3: privileged */
+ /* cr13/pidr4: privileged */
+ /* cr0/rctr: privileged */
+ /* cr10/ccr: privileged */
+ /* cr23/eirr: privileged */
+ /* cr24: privileged */
+ /* cr25/vtop: privileged */
+ /* cr27/tr3: _lwp_private, thread-local storage -- nonnull anyway */
+ /* cr28: privileged */
+ /* cr30/fpregs: privileged */
+ /* cr31: privileged */
+
+ char *argv[] = {path, NULL};
+ char **envp = environ;
+ posix_spawn_file_actions_t fileacts;
+ posix_spawnattr_t attr;
+ pid_t pid;
+ int error;
+
+ error = posix_spawn_file_actions_init(&fileacts);
+ if (error)
+ goto out;
+ error = posix_spawn_file_actions_adddup2(&fileacts, fd, STDOUT_FILENO);
+ if (error)
+ goto out;
+ error = posix_spawnattr_init(&attr);
+ if (error)
+ goto out;
+
+ setfpregs();
+ setpsw();
+
+ /*
+ * Not perfect -- compiler might use some registers for
+ * stack/argument transfers, but all the arguments are nonnull
+ * so this is probably a good test anyway.
+ */
+ __asm volatile("mtctl %[sar], %%sar" /* cr11 */
+ : /* outputs */
+ : [sar] "r"(sar)
+ : "memory");
+ __asm volatile("" :
+ "+r"(t1),
+ "+r"(t2),
+ "+r"(t3),
+ "+r"(r4),
+ "+r"(r5),
+ "+r"(r6),
+ "+r"(r7),
+ "+r"(r8),
+ "+r"(r9),
+ "+r"(r10),
+ "+r"(r11),
+ "+r"(r12)
+ :: "memory");
+ /* pacify gcc error: more than 30 operands in 'asm' */
+ __asm volatile("" :
+ "+r"(r13),
+ "+r"(r14),
+ "+r"(r15),
+ "+r"(r16),
+ "+r"(r17),
+ "+r"(r18),
+ "+r"(t4),
+ "+r"(ret0),
+ "+r"(ret1),
+ "+r"(r31)
+ :: "memory");
+
+ error = posix_spawn(&pid, path, &fileacts, &attr, argv, envp);
+ if (error)
+ goto out;
+
+out: posix_spawnattr_destroy(&attr);
+ posix_spawn_file_actions_destroy(&fileacts);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
diff --git a/kernel/arch/hppa/execregs.h b/kernel/arch/hppa/execregs.h
new file mode 100644
index 000000000000..ae4dbb2e39c0
--- /dev/null
+++ b/kernel/arch/hppa/execregs.h
@@ -0,0 +1,157 @@
+/* $NetBSD: execregs.h,v 1.2 2025/02/28 16:08:19 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_HPPA_EXECREGS_H
+#define TESTS_KERNEL_ARCH_HPPA_EXECREGS_H
+
+#include <sys/cdefs.h>
+
+#define NEXECREGS 96
+
+#ifndef _LOCORE
+
+#include <unistd.h>
+
+/*
+ * Ordered by struct struct trapframe in sys/arch/hppa/include/frame.h
+ * for convenience of auditing. Must match h_execregs.S.
+ */
+static const char *const regname[] = {
+ "t1",
+ "t2",
+ /* sp: stack pointer */
+ "t3",
+ /* various privileged stuff */
+ "sar",
+ "r1",
+ "rp",
+ /* r3: frame pointer (set to initial stack pointer) */
+ "r4",
+ "r5",
+ "r6",
+ "r70",
+ "r8",
+ "r9",
+ "r10",
+ "r11",
+ "r12",
+ "r13",
+ "r14",
+ "r15",
+ "r16",
+ "r17",
+ "r18",
+ "t4",
+ "arg3",
+ "arg2",
+ "arg1",
+ /* arg0: ps_strings */
+ "dp",
+ "ret0",
+ "ret1",
+ "r31",
+ "cr27",
+ "cr28",
+
+ "psw", /* user-visible PSW bits: C/B and V */
+
+ /* Floating-point registers */
+ "fr0l",
+ "fr0r",
+ "fr1l",
+ "fr1r",
+ "fr2l",
+ "fr2r",
+ "fr3l",
+ "fr3r",
+ "fr4l",
+ "fr4r",
+ "fr5l",
+ "fr5r",
+ "fr6l",
+ "fr6r",
+ "fr7l",
+ "fr7r",
+ "fr8l",
+ "fr8r",
+ "fr9l",
+ "fr9r",
+ "fr10l",
+ "fr10r",
+ "fr11l",
+ "fr11r",
+ "fr12l",
+ "fr12r",
+ "fr13l",
+ "fr13r",
+ "fr14l",
+ "fr14r",
+ "fr15l",
+ "fr15r",
+ "fr16l",
+ "fr16r",
+ "fr17l",
+ "fr17r",
+ "fr18l",
+ "fr18r",
+ "fr19l",
+ "fr19r",
+ "fr20l",
+ "fr20r",
+ "fr21l",
+ "fr21r",
+ "fr22l",
+ "fr22r",
+ "fr23l",
+ "fr23r",
+ "fr24l",
+ "fr24r",
+ "fr25l",
+ "fr25r",
+ "fr26l",
+ "fr26r",
+ "fr27l",
+ "fr27r",
+ "fr28l",
+ "fr28r",
+ "fr29l",
+ "fr29r",
+ "fr30l",
+ "fr30r",
+ "fr31l",
+ "fr31r",
+};
+
+__CTASSERT(NEXECREGS == __arraycount(regname));
+
+int execregschild(char *);
+pid_t spawnregschild(char *, int);
+
+#endif /* _LOCORE */
+
+#endif /* TESTS_KERNEL_ARCH_HPPA_EXECREGS_H */
diff --git a/kernel/arch/hppa/execsp.S b/kernel/arch/hppa/execsp.S
new file mode 100644
index 000000000000..520421a1f1fc
--- /dev/null
+++ b/kernel/arch/hppa/execsp.S
@@ -0,0 +1,130 @@
+/* $NetBSD: execsp.S,v 1.1 2025/04/20 22:32:49 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: execsp.S,v 1.1 2025/04/20 22:32:49 riastradh Exp $")
+
+ .import _GLOBAL_OFFSET_TABLE_
+
+/*
+ * void execsp_start(struct ps_strings *ps_strings@arg0,
+ * void (*cleanup@arg1)(void), void *obj_main@arg2)
+ *
+ * ELF entry point. Saves the stack pointer in startsp and defers
+ * to the usual csu __start routine.
+ */
+LEAF_ENTRY(execsp_start)
+ /*
+ * Set up the data pointer (r19) and linkage table register
+ * (r27) like the real startup routine so we can get at the
+ * global symbols startsp and __start.
+ *
+ * XXX Not really sure why we need to set up r27, since we only
+ * use r19 here and the real startup routine, __start, will set
+ * up both r19 and r27 anyway. But this crashes with SIGSEGV
+ * shortly after startup if we don't set up r27, and gdb
+ * crashes on my attempts to single-step, so I'll just leave
+ * the initialization of r27 here for now until someone is
+ * motivated by the potential for a single-instruction
+ * micro-optimization in this test program to find out why r27
+ * is needed too.
+ */
+ bl L$lpc, %r27
+ depi 0, 31, 2, %r27
+L$lpc: addil L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 8), %r27
+ ldo R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 12)(%r1), %r27
+ copy %r27, %r19
+
+ addil LT%_C_LABEL(startsp), %r19 /* r20 := &startsp */
+ ldw RT%_C_LABEL(startsp)(%r1), %r20
+
+ /* PIC_TAILCALL(__start), if we had it */
+ addil LT%_C_LABEL(__start), %r19 /* r1 := __start */
+ ldw RT%_C_LABEL(__start)(%r1), %r1
+ bv %r0(%r1) /* jump to __start */
+ stw %sp, 0(%r20) /* startsp := sp */
+EXIT(execsp_start)
+
+/*
+ * void execsp_ctor(void)
+ *
+ * ELF constructor. Saves the stack pointer in ctorsp and
+ * returns.
+ */
+LEAF_ENTRY(execsp_ctor)
+ addil LT%_C_LABEL(ctorsp), %r19 /* r1 := &ctorsp */
+ ldw RT%_C_LABEL(ctorsp)(%r1), %r1
+ bv %r0(%rp) /* return */
+ stw %sp, 0(%r1) /* ctorsp := sp */
+EXIT(execsp_ctor)
+
+ /* Make execsp_ctor a constructor. */
+ .section .ctors,"aw",@progbits
+ .p2align 2
+ .word _C_LABEL(execsp_ctor)
+
+/*
+ * int main(int argc@arg0, char **argv@arg1, ...)
+ *
+ * Main function. Saves the stack pointer in mainsp and returns
+ * zero. We will call execsp_main in execsp_dtor once dtorsp has
+ * been initialized.
+ */
+LEAF_ENTRY(main)
+ addil LT%_C_LABEL(mainsp), %r19 /* r1 := &mainsp */
+ ldw RT%_C_LABEL(mainsp)(%r1), %r1
+ stw %sp, 0(%r1) /* ctorsp := sp */
+ bv %r0(%rp) /* return... */
+ copy %r0, %ret0 /* ...zero */
+EXIT(main)
+
+/*
+ * void execsp_dtor(void)
+ *
+ * ELF destructor. Saves the stack pointer in dtorsp and defers
+ * to the C execsp_main in h_execsp.c to report the stack pointers
+ * back to the t_signal_and_sp parent.
+ */
+LEAF_ENTRY(execsp_dtor)
+ addil LT%_C_LABEL(dtorsp), %r19 /* r20 := &dtorsp */
+ ldw RT%_C_LABEL(dtorsp)(%r1), %r20
+
+ /* PIC_TAILCALL(__start), if we had it */
+ addil LT%_C_LABEL(execsp_main), %r19 /* r1 := execsp_main */
+ ldw RT%_C_LABEL(execsp_main)(%r1), %r1
+ bv %r0(%r1) /* jump to execsp_main */
+ stw %sp, 0(%r20) /* startsp := sp */
+EXIT(execsp_dtor)
+
+ /* Make execsp_ctor a destructor. */
+ .section .dtors,"aw",@progbits
+ .p2align 2
+ .word _C_LABEL(execsp_dtor)
diff --git a/kernel/arch/hppa/h_execregs.S b/kernel/arch/hppa/h_execregs.S
new file mode 100644
index 000000000000..ad7a50a5b932
--- /dev/null
+++ b/kernel/arch/hppa/h_execregs.S
@@ -0,0 +1,168 @@
+/* $NetBSD: h_execregs.S,v 1.2 2025/02/28 16:08:19 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <sys/syscall.h>
+
+#include <machine/asm.h>
+#include <machine/vmparam.h>
+
+#include "execregs.h"
+
+_ENTRY(execregs_start)
+ .callinfo frame=(NEXECREGS*4), calls
+ .entry
+
+ ldo (NEXECREGS*4)(%sp), %sp /* space for NEXECREGS */
+ stw %t1, (4*(0 - NEXECREGS))(%sp) /* order matches execregs.h */
+ stw %t2, (4*(1 - NEXECREGS))(%sp)
+ /* sp: stack pointer */
+ stw %t3, (4*(2 - NEXECREGS))(%sp)
+ /* cr17/iisq_head: privileged */
+ /* cr17/iisq_tail: privileged */
+ /* cr18/iioq_head: privileged */
+ /* cr18/iioq_tail: privileged */
+ /* cr15/eiem: privileged */
+ /* cr22/ipsw: privileged */
+ /* sr3: privileged(?) */
+ /* cr8/pidr1: privileged */
+ /* cr20/isr: privileged */
+ /* cr21/ior: privileged */
+ /* cr19/iir: privileged */
+ /* flags: N/A(?) */
+ stw %sar, (4*(3 - NEXECREGS))(%sp)
+ stw %r1, (4*(4 - NEXECREGS))(%sp)
+ stw %rp, (4*(5 - NEXECREGS))(%sp)
+ /* r3: frame pointer (set to initial stack pointer) */
+ stw %r4, (4*(6 - NEXECREGS))(%sp)
+ stw %r5, (4*(7 - NEXECREGS))(%sp)
+ stw %r6, (4*(8 - NEXECREGS))(%sp)
+ stw %r7, (4*(9 - NEXECREGS))(%sp)
+ stw %r8, (4*(10 - NEXECREGS))(%sp)
+ stw %r9, (4*(11 - NEXECREGS))(%sp)
+ stw %r10, (4*(12 - NEXECREGS))(%sp)
+ stw %r11, (4*(13 - NEXECREGS))(%sp)
+ stw %r12, (4*(14 - NEXECREGS))(%sp)
+ stw %r13, (4*(15 - NEXECREGS))(%sp)
+ stw %r14, (4*(16 - NEXECREGS))(%sp)
+ stw %r15, (4*(17 - NEXECREGS))(%sp)
+ stw %r16, (4*(18 - NEXECREGS))(%sp)
+ stw %r17, (4*(19 - NEXECREGS))(%sp)
+ stw %r18, (4*(20 - NEXECREGS))(%sp)
+ stw %t4, (4*(21 - NEXECREGS))(%sp)
+ stw %arg3, (4*(22 - NEXECREGS))(%sp)
+ stw %arg2, (4*(23 - NEXECREGS))(%sp)
+ stw %arg1, (4*(24 - NEXECREGS))(%sp)
+ /* arg0: ps_strings */
+ stw %dp, (4*(25 - NEXECREGS))(%sp)
+ stw %ret0, (4*(26 - NEXECREGS))(%sp)
+ stw %ret1, (4*(27 - NEXECREGS))(%sp)
+ stw %r31, (4*(28 - NEXECREGS))(%sp)
+ /* sr0-sr7: space registers initialized by kernel */
+ /* cr9/pidr2: privileged */
+ /* cr12/pidr3: privileged */
+ /* cr13/pidr4: privileged */
+ /* cr0/rctr: privileged */
+ /* cr10/ccr: privileged */
+ /* cr23/eirr: privileged */
+ /* cr24: privileged */
+ /* cr25/vtop: privileged */
+ /* cr26: ??? */
+ stw %cr27, (4*(29 - NEXECREGS))(%sp)
+ stw %cr28, (4*(30 - NEXECREGS))(%sp)
+ /* cr30/fpregs: privileged */
+ /* cr31: privileged */
+
+ addc %t1, %r0, %r0 /* t1 := PSW[C/B]{0} */
+ zdep %t1, 23, 8, %t1 /* t1 := PSW */
+ stw %t1, (4*(31 - NEXECREGS))(%sp)
+
+ /* store the fp registers */
+ ldo (4*(32 - NEXECREGS))(%sp), %t1
+ fstd,ma %fr0, 8(%t1)
+ fstd,ma %fr1, 8(%t1)
+ fstd,ma %fr2, 8(%t1)
+ fstd,ma %fr3, 8(%t1)
+ fstd,ma %fr4, 8(%t1)
+ fstd,ma %fr5, 8(%t1)
+ fstd,ma %fr6, 8(%t1)
+ fstd,ma %fr7, 8(%t1)
+ fstd,ma %fr8, 8(%t1)
+ fstd,ma %fr9, 8(%t1)
+ fstd,ma %fr10, 8(%t1)
+ fstd,ma %fr11, 8(%t1)
+ fstd,ma %fr12, 8(%t1)
+ fstd,ma %fr13, 8(%t1)
+ fstd,ma %fr14, 8(%t1)
+ fstd,ma %fr15, 8(%t1)
+ fstd,ma %fr16, 8(%t1)
+ fstd,ma %fr17, 8(%t1)
+ fstd,ma %fr18, 8(%t1)
+ fstd,ma %fr19, 8(%t1)
+ fstd,ma %fr20, 8(%t1)
+ fstd,ma %fr21, 8(%t1)
+ fstd,ma %fr22, 8(%t1)
+ fstd,ma %fr23, 8(%t1)
+ fstd,ma %fr24, 8(%t1)
+ fstd,ma %fr25, 8(%t1)
+ fstd,ma %fr26, 8(%t1)
+ fstd,ma %fr27, 8(%t1)
+ fstd,ma %fr28, 8(%t1)
+ fstd,ma %fr29, 8(%t1)
+ fstd,ma %fr30, 8(%t1)
+ fstd %fr31, 0(%t1)
+
+ /* call write(STDOUT_FILENO, regs, sizeof(regs)) */
+ ldi 1, %arg0 /* arg0 := STDOUT_FILENO */
+ ldo -(4*NEXECREGS)(%sp), %arg1 /* arg1 := regs */
+ ldi (4*NEXECREGS), %arg2 /* arg2 := sizeof(regs) */
+ ldil L%SYSCALLGATE, %r1
+ ble 4(%sr2, %r1)
+ ldi SYS_write, %t1
+
+ comb,<>,n %r0, %t1, 2f /* bail if write failed */
+ ldi (4*NEXECREGS), %t1 /* bail if wrong # bytes */
+ comb,<>,n %ret0, %t1, 2f
+
+ /* call exit(0) */
+ ldi 0, %arg0
+1: ldil L%SYSCALLGATE, %r1
+ ble 4(%sr2, %r1)
+ ldi SYS_exit, %t1
+ break 0, 0 /* paranoia */
+
+2: /* call exit(127) */
+ b 1b
+ ldi 127, %arg0
+EXIT(execregs_start)
+
+/* main stub to simplify linking */
+LEAF_ENTRY(main)
+ break 0, 0 /* paranoia */
+EXIT(main)
diff --git a/kernel/arch/hppa/signalsphandler.S b/kernel/arch/hppa/signalsphandler.S
new file mode 100644
index 000000000000..01633d99ff8b
--- /dev/null
+++ b/kernel/arch/hppa/signalsphandler.S
@@ -0,0 +1,46 @@
+/* $NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:32:49 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:32:49 riastradh Exp $")
+
+/*
+ * signalsphandler(signo@arg0)
+ *
+ * Signal handler. Store the stack pointer on entry at the global
+ * variable signalsp and return.
+ */
+LEAF_ENTRY(signalsphandler)
+ addil LT%_C_LABEL(signalsp), %r19 /* r1 := &signalsp */
+ ldw RT%_C_LABEL(signalsp)(%r1), %r1
+ bv %r0(%rp) /* return */
+ stw %sp, 0(%r1) /* signalsp := sp */
+EXIT(signalsphandler)
diff --git a/kernel/arch/hppa/stack_pointer.h b/kernel/arch/hppa/stack_pointer.h
new file mode 100644
index 000000000000..acb73443621c
--- /dev/null
+++ b/kernel/arch/hppa/stack_pointer.h
@@ -0,0 +1,35 @@
+/* $NetBSD: stack_pointer.h,v 1.1 2025/04/20 22:32:49 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_HPPA_STACK_POINTER_H
+#define TESTS_KERNEL_ARCH_HPPA_STACK_POINTER_H
+
+#define MISALIGN_SP __asm __volatile("ldo 1(%%sp),%%sp" ::: "memory")
+#define FIX_SP __asm __volatile("ldo -1(%%sp),%%sp" ::: "memory")
+
+#endif /* TESTS_KERNEL_ARCH_HPPA_STACK_POINTER_H */
diff --git a/kernel/arch/hppa/threadspfunc.S b/kernel/arch/hppa/threadspfunc.S
new file mode 100644
index 000000000000..f1b1d21fadfe
--- /dev/null
+++ b/kernel/arch/hppa/threadspfunc.S
@@ -0,0 +1,43 @@
+/* $NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $")
+
+/*
+ * void *threadspfunc(void *cookie@arg0)
+ *
+ * pthread_create(3) function. Return the stack pointer on entry.
+ */
+LEAF_ENTRY(threadspfunc)
+ bv %r0(%rp) /* return to caller */
+ copy %sp, %ret0 /* return sp */
+EXIT(threadspfunc)
diff --git a/kernel/arch/i386/contextspfunc.S b/kernel/arch/i386/contextspfunc.S
new file mode 100644
index 000000000000..cc097cc61325
--- /dev/null
+++ b/kernel/arch/i386/contextspfunc.S
@@ -0,0 +1,56 @@
+/* $NetBSD: contextspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: contextspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $")
+
+/*
+ * contextspfunc()
+ *
+ * makecontext(3) function. Store the stack pointer on entry at
+ * the global variable contextsp and call contextdone.
+ */
+ENTRY(contextspfunc)
+ call getpc_eax
+ addl $_GLOBAL_OFFSET_TABLE_,%eax
+ movl _C_LABEL(contextsp)@GOT(%eax),%eax
+ movl %esp,(%eax)
+ jmp _C_LABEL(contextdone)@PLT
+END(contextspfunc)
+
+ .text
+ _ALIGN_TEXT
+ .local getpc_eax
+ .type getpc_eax,@function
+getpc_eax:
+ movl (%esp),%eax
+ ret
+END(getpc_eax)
diff --git a/kernel/arch/i386/execregs.c b/kernel/arch/i386/execregs.c
new file mode 100644
index 000000000000..477cd82989e9
--- /dev/null
+++ b/kernel/arch/i386/execregs.c
@@ -0,0 +1,132 @@
+/* $NetBSD: execregs.c,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: execregs.c,v 1.1 2025/02/27 00:55:32 riastradh Exp $");
+
+#include "execregs.h"
+
+#include <errno.h>
+#include <spawn.h>
+#include <stddef.h>
+#include <unistd.h>
+
+extern char **environ;
+
+static unsigned long
+nonnull(unsigned long x)
+{
+
+ x |= x << 8;
+ x |= x << 16;
+ return x;
+}
+
+int
+execregschild(char *path)
+{
+ register long edi __asm("edi") = nonnull('d');
+ register long esi __asm("esi") = nonnull('s');
+ /* ebp: frame pointer, can't touch that here, but it'll be nonnull */
+ /* ebx: ps_strings, passed to child */
+ register long edx __asm("edx") = nonnull('x');
+ register long ecx __asm("ecx") = nonnull('c');
+ register long eax __asm("eax") = nonnull('a');
+
+ char *argv[] = {path, NULL};
+ char **envp = environ;
+
+ /*
+ * Not perfect -- compiler might use some registers for
+ * stack/argument transfers, but all the arguments are nonnull
+ * so this is probably a good test anyway.
+ */
+ __asm volatile("" :
+ "+r"(edi),
+ "+r"(esi),
+ "+r"(edx),
+ "+r"(ecx),
+ "+r"(eax)
+ :: "memory");
+
+ return execve(path, argv, envp);
+}
+
+pid_t
+spawnregschild(char *path, int fd)
+{
+ register long edi __asm("edi") = nonnull('d');
+ register long esi __asm("esi") = nonnull('s');
+ /* ebp: frame pointer, can't touch that here, but it'll be nonnull */
+ /* ebx: ps_strings, passed to child */
+ register long edx __asm("edx") = nonnull('x');
+ register long ecx __asm("ecx") = nonnull('c');
+ register long eax __asm("eax") = nonnull('a');
+
+ char *argv[] = {path, NULL};
+ char **envp = environ;
+ posix_spawn_file_actions_t fileacts;
+ posix_spawnattr_t attr;
+ pid_t pid;
+ int error;
+
+ error = posix_spawn_file_actions_init(&fileacts);
+ if (error)
+ goto out;
+ error = posix_spawn_file_actions_adddup2(&fileacts, fd, STDOUT_FILENO);
+ if (error)
+ goto out;
+ error = posix_spawnattr_init(&attr);
+ if (error)
+ goto out;
+
+ /*
+ * Not perfect -- compiler might use some registers for
+ * stack/argument transfers, but all the arguments are nonnull
+ * so this is probably a good test anyway.
+ */
+ __asm volatile("" :
+ "+r"(edi),
+ "+r"(esi),
+ "+r"(edx),
+ "+r"(ecx),
+ "+r"(eax)
+ :: "memory");
+
+ error = posix_spawn(&pid, path, &fileacts, &attr, argv, envp);
+ if (error)
+ goto out;
+
+out: posix_spawnattr_destroy(&attr);
+ posix_spawn_file_actions_destroy(&fileacts);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
diff --git a/kernel/arch/i386/execregs.h b/kernel/arch/i386/execregs.h
new file mode 100644
index 000000000000..f512bbabc1c7
--- /dev/null
+++ b/kernel/arch/i386/execregs.h
@@ -0,0 +1,69 @@
+/* $NetBSD: execregs.h,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_I386_EXECREGS_H
+#define TESTS_KERNEL_ARCH_I386_EXECREGS_H
+
+#include <sys/cdefs.h>
+
+#define NEXECREGS 6
+
+#ifndef _LOCORE
+
+#include <unistd.h>
+
+/*
+ * Ordered by struct trapframe in sys/arch/i386/include/frame.h for
+ * convenience of auditing. Must match h_execregs.S.
+ */
+static const char *const regname[] = {
+ /* gs/fs/es/ds: segment registers, not really registers */
+ "edi",
+ "esi",
+ "ebp",
+ /* ebx: ps_strings */
+ "edx",
+ "ecx",
+ "eax",
+ /* trapno: not a register */
+ /* err: not a register */
+ /* eip: instruction pointer */
+ /* cs: segment register */
+ /* eflags */
+ /* esp: stack pointer */
+ /* ss: stack selector */
+};
+
+__CTASSERT(NEXECREGS == __arraycount(regname));
+
+int execregschild(char *);
+pid_t spawnregschild(char *, int);
+
+#endif /* _LOCORE */
+
+#endif /* TESTS_KERNEL_ARCH_I386_EXECREGS_H */
diff --git a/kernel/arch/i386/execsp.S b/kernel/arch/i386/execsp.S
new file mode 100644
index 000000000000..133af37715ad
--- /dev/null
+++ b/kernel/arch/i386/execsp.S
@@ -0,0 +1,112 @@
+/* $NetBSD: execsp.S,v 1.1 2025/04/20 22:33:13 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: execsp.S,v 1.1 2025/04/20 22:33:13 riastradh Exp $")
+
+/*
+ * void execsp_start(void (*cleanup@edx)(void), void *obj_main@ecx,
+ * struct ps_strings *ps_strings@ebx)
+ *
+ * ELF entry point. Saves the stack pointer in startsp and defers
+ * to the usual csu __start routine.
+ */
+ENTRY(execsp_start)
+ call getpc_eax
+ addl $_GLOBAL_OFFSET_TABLE_,%eax
+ movl _C_LABEL(startsp)@GOT(%eax),%eax
+ movl %esp,(%eax)
+ jmp _C_LABEL(__start)@PLT
+END(execsp_start)
+
+/*
+ * void execsp_ctor(void)
+ *
+ * ELF constructor. Saves the stack pointer in ctorsp and
+ * returns.
+ */
+ENTRY(execsp_ctor)
+ call getpc_eax
+ addl $_GLOBAL_OFFSET_TABLE_,%eax
+ movl _C_LABEL(ctorsp)@GOT(%eax),%eax
+ movl %esp,(%eax)
+ ret
+END(execsp_ctor)
+
+ /* Make execsp_ctor a constructor. */
+ .section .ctors,"aw",@progbits
+ .p2align 2
+ .long _C_LABEL(execsp_ctor)
+
+/*
+ * int main(int argc@rdi, char **argv@rsi, ...)
+ *
+ * Main function. Saves the stack pointer in mainsp and returns
+ * zero. We will call execsp_main in execsp_dtor once dtorsp has
+ * been initialized.
+ */
+ENTRY(main)
+ call getpc_eax
+ addl $_GLOBAL_OFFSET_TABLE_,%eax
+ movl _C_LABEL(mainsp)@GOT(%eax),%eax
+ movl %esp,(%eax)
+ xorl %eax,%eax
+ ret
+END(main)
+
+/*
+ * void execsp_dtor(void)
+ *
+ * ELF destructor. Saves the stack pointer in dtorsp and defers
+ * to the C execsp_main in h_execsp.c to report the stack pointers
+ * back to the t_signal_and_sp parent.
+ */
+ENTRY(execsp_dtor)
+ call getpc_eax
+ addl $_GLOBAL_OFFSET_TABLE_,%eax
+ movl _C_LABEL(dtorsp)@GOT(%eax),%eax
+ movl %esp,(%eax)
+ jmp _C_LABEL(execsp_main)@PLT
+END(execsp_dtor)
+
+ /* Make execsp_ctor a destructor. */
+ .section .dtors,"aw",@progbits
+ .p2align 2
+ .long _C_LABEL(execsp_dtor)
+
+ .text
+ _ALIGN_TEXT
+ .local getpc_eax
+ .type getpc_eax,@function
+getpc_eax:
+ movl (%esp),%eax
+ ret
+END(getpc_eax)
diff --git a/kernel/arch/i386/h_execregs.S b/kernel/arch/i386/h_execregs.S
new file mode 100644
index 000000000000..ac9b843f9d86
--- /dev/null
+++ b/kernel/arch/i386/h_execregs.S
@@ -0,0 +1,85 @@
+/* $NetBSD: h_execregs.S,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <sys/syscall.h>
+
+#include <machine/asm.h>
+
+#include "execregs.h"
+
+ENTRY(execregs_start)
+ andl $-0x4,%esp /* align stack to 4-byte boundary */
+
+ /* store registers to a buffer on stack */
+ subl $(NEXECREGS*4),%esp /* space for NEXECREGS registers */
+ movl %edi,0*4(%esp) /* order matches execregs.h */
+ movl %esi,1*4(%esp)
+ movl %ebp,2*4(%esp)
+ movl %edx,3*4(%esp)
+ movl %ecx,4*4(%esp)
+ movl %eax,5*4(%esp)
+
+ /* call write(STDOUT_FILENO, regs, sizeof(regs)) */
+ movl %esp,%eax /* eax := regs */
+ pushl $(NEXECREGS*4) /* arg2 := sizeof(regs) */
+ pushl %eax /* arg1 := regs */
+ pushl $0x1 /* arg0 := STDOUT_FILENO */
+ call execregs_write
+
+ jb 2f /* bail if write failed */
+ cmpl $(NEXECREGS*4),%eax /* bail if wrote wrong # of bytes */
+ jne 2f
+
+ /* call exit(0) */
+ pushl $0 /* arg0 := 0 */
+1: call execregs_exit
+ hlt /* paranoia */
+
+2: /* call exit(127) */
+ pushl $127 /* arg0 := 127 */
+ jmp 1b
+END(execregs_start)
+
+ENTRY(execregs_write)
+ movl $SYS_write,%eax /* syscall number */
+ int $0x80
+ retl
+END(execregs_write)
+
+ENTRY(execregs_exit)
+ movl $SYS_exit,%eax /* syscall number */
+ int $0x80
+ hlt
+END(execregs_exit)
+
+/* main stub to simplify linking */
+ENTRY(main)
+ hlt
+END(main)
diff --git a/kernel/arch/i386/signalsphandler.S b/kernel/arch/i386/signalsphandler.S
new file mode 100644
index 000000000000..418825e78ab6
--- /dev/null
+++ b/kernel/arch/i386/signalsphandler.S
@@ -0,0 +1,56 @@
+/* $NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:33:13 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:33:13 riastradh Exp $")
+
+/*
+ * signalsphandler(signo@esp[4])
+ *
+ * Signal handler. Store the stack pointer on entry at the global
+ * variable signalsp and return.
+ */
+ENTRY(signalsphandler)
+ call getpc_eax
+ addl $_GLOBAL_OFFSET_TABLE_,%eax
+ movl _C_LABEL(signalsp)@GOT(%eax),%eax
+ movl %esp,(%eax)
+ ret
+END(signalsphandler)
+
+ .text
+ _ALIGN_TEXT
+ .local getpc_eax
+ .type getpc_eax,@function
+getpc_eax:
+ movl (%esp),%eax
+ ret
+END(getpc_eax)
diff --git a/kernel/arch/i386/stack_pointer.h b/kernel/arch/i386/stack_pointer.h
new file mode 100644
index 000000000000..6c95a28ab7b6
--- /dev/null
+++ b/kernel/arch/i386/stack_pointer.h
@@ -0,0 +1,35 @@
+/* $NetBSD: stack_pointer.h,v 1.1 2025/04/20 22:33:13 riastradh Exp $ */
+
+/*
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_I386_STACK_POINTER_H
+#define TESTS_KERNEL_ARCH_I386_STACK_POINTER_H
+
+#define MISALIGN_SP __asm __volatile("addl $-1,%esp")
+#define FIX_SP __asm __volatile("addl $1,%esp")
+
+#endif /* TESTS_KERNEL_ARCH_I386_STACK_POINTER_H */
diff --git a/kernel/arch/i386/threadspfunc.S b/kernel/arch/i386/threadspfunc.S
new file mode 100644
index 000000000000..af03ff4c550e
--- /dev/null
+++ b/kernel/arch/i386/threadspfunc.S
@@ -0,0 +1,43 @@
+/* $NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $")
+
+/*
+ * void *threadspfunc(void *cookie@esp[4])
+ *
+ * pthread_create(3) function. Return the stack pointer on entry.
+ */
+ENTRY(threadspfunc)
+ mov %esp,%eax
+ ret
+END(threadspfunc)
diff --git a/kernel/arch/mips/contextspfunc.S b/kernel/arch/mips/contextspfunc.S
new file mode 100644
index 000000000000..bee0a610dc86
--- /dev/null
+++ b/kernel/arch/mips/contextspfunc.S
@@ -0,0 +1,53 @@
+/* $NetBSD: contextspfunc.S,v 1.2 2025/04/27 16:49:54 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: contextspfunc.S,v 1.2 2025/04/27 16:49:54 riastradh Exp $")
+
+#include "SYS.h"
+
+ .text
+
+/*
+ * contextspfunc()
+ *
+ * makecontext(3) function. Store the stack pointer on entry at
+ * the global variable contextsp and call contextdone.
+ */
+LEAF(contextspfunc)
+ PIC_PROLOGUE(contextspfunc) /* gp setup, sets t3 */
+
+ PTR_LA t1, _C_LABEL(contextsp) /* load t1 := &contextsp */
+ NOP_L /* load hazard */
+ PTR_S sp, 0(t1) /* store contextsp := stack pointer */
+
+ PIC_TAILCALL(contextdone)
+END(contextspfunc)
diff --git a/kernel/arch/mips/execsp.S b/kernel/arch/mips/execsp.S
new file mode 100644
index 000000000000..b4f2dcfd6e2c
--- /dev/null
+++ b/kernel/arch/mips/execsp.S
@@ -0,0 +1,118 @@
+/* $NetBSD: execsp.S,v 1.2 2025/04/27 16:49:54 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: execsp.S,v 1.2 2025/04/27 16:49:54 riastradh Exp $")
+
+#include "SYS.h"
+
+ .text
+
+/*
+ * void execsp_start(void *stackpointer@a0, void (*cleanup@a1)(void),
+ * void *obj_main@a2, struct ps_strings *ps_strings@a3)
+ *
+ * ELF entry point. Saves the stack pointer in startsp and defers
+ * to the usual csu __start routine.
+ */
+LEAF(execsp_start)
+ PIC_PROLOGUE(execsp_start) /* gp setup, sets t3 */
+
+ PTR_LA t1, _C_LABEL(startsp) /* load t1 := &startsp */
+ NOP_L /* load hazard */
+ PTR_S sp, 0(t1) /* store startsp := stack pointer */
+
+ PIC_TAILCALL(__start) /* gp restore, uses t3 */
+END(execsp_start)
+
+/*
+ * void execsp_ctor(void)
+ *
+ * ELF constructor. Saves the stack pointer in ctorsp and
+ * returns.
+ */
+LEAF(execsp_ctor)
+ PIC_PROLOGUE(execsp_ctor) /* gp setup, sets t3 */
+
+ PTR_LA t1, _C_LABEL(ctorsp) /* load t1 := &ctorsp */
+ NOP_L /* load hazard */
+ PTR_S sp, 0(t1) /* store ctorsp := stack pointer */
+
+ PIC_RETURN() /* gp restore, uses t3 */
+END(execsp_ctor)
+
+ /* Make execsp_ctor a constructor. */
+ .pushsection .ctors,"aw",@progbits
+ .p2align PTR_SCALESHIFT
+ PTR_WORD _C_LABEL(execsp_ctor)
+ .popsection
+
+/*
+ * int main(int argc@a0, char **argv@a1, ...)
+ *
+ * Main function. Saves the stack pointer in mainsp and returns
+ * zero. We will call execsp_main in execsp_dtor once dtorsp has
+ * been initialized.
+ */
+LEAF(main)
+ PIC_PROLOGUE(main) /* gp setup, sets t3 */
+
+ PTR_LA t1, _C_LABEL(mainsp) /* load t1 := &mainsp */
+ NOP_L /* load hazard */
+ PTR_S sp, 0(t1) /* store mainsp := stack pointer */
+
+ move v0, zero /* return 0 */
+
+ PIC_RETURN() /* gp restore, uses t3 */
+END(main)
+
+/*
+ * void execsp_dtor(void)
+ *
+ * ELF destructor. Saves the stack pointer in dtorsp and defers
+ * to the C execsp_main in h_execsp.c to report the stack pointers
+ * back to the t_signal_and_sp parent.
+ */
+LEAF(execsp_dtor)
+ PIC_PROLOGUE(execsp_dtor) /* gp setup, sets t3 */
+
+ PTR_LA t1, _C_LABEL(dtorsp) /* load t1 := &dtorsp */
+ NOP_L /* load hazard */
+ PTR_S sp, 0(t1) /* store dtorsp := stack pointer */
+
+ PIC_TAILCALL(execsp_main) /* gp restore, uses t3 */
+END(execsp_dtor)
+
+ /* Make execsp_ctor a destructor. */
+ .pushsection .dtors,"aw",@progbits
+ .p2align PTR_SCALESHIFT
+ PTR_WORD _C_LABEL(execsp_dtor)
+ .popsection
diff --git a/kernel/arch/mips/signalsphandler.S b/kernel/arch/mips/signalsphandler.S
new file mode 100644
index 000000000000..e742c2c95701
--- /dev/null
+++ b/kernel/arch/mips/signalsphandler.S
@@ -0,0 +1,53 @@
+/* $NetBSD: signalsphandler.S,v 1.2 2025/04/27 16:49:54 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: signalsphandler.S,v 1.2 2025/04/27 16:49:54 riastradh Exp $")
+
+#include "SYS.h"
+
+ .text
+
+/*
+ * signalsphandler(signo@a0)
+ *
+ * Signal handler. Store the stack pointer on entry at the global
+ * variable signalsp and return.
+ */
+LEAF(signalsphandler)
+ PIC_PROLOGUE(signalsphandler) /* gp setup, sets t3 */
+
+ PTR_LA t1, _C_LABEL(signalsp) /* load t1 := &signalsp */
+ NOP_L /* load hazard */
+ PTR_S sp, 0(t1) /* store signalsp := stack pointer */
+
+ PIC_RETURN()
+END(signalsphandler)
diff --git a/kernel/arch/mips/stack_pointer.h b/kernel/arch/mips/stack_pointer.h
new file mode 100644
index 000000000000..288c58928526
--- /dev/null
+++ b/kernel/arch/mips/stack_pointer.h
@@ -0,0 +1,40 @@
+/* $NetBSD: stack_pointer.h,v 1.2 2025/04/21 14:17:38 rin Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_MIPS_STACK_POINTER_H
+#define TESTS_KERNEL_ARCH_MIPS_STACK_POINTER_H
+
+#ifdef __mips_o32
+#define MISALIGN_SP __asm __volatile("addiu $sp,$sp,-1" ::: "memory")
+#define FIX_SP __asm __volatile("addiu $sp,$sp,1" ::: "memory")
+#else
+#define MISALIGN_SP __asm __volatile("daddiu $sp,$sp,-1" ::: "memory")
+#define FIX_SP __asm __volatile("daddiu $sp,$sp,1" ::: "memory")
+#endif
+
+#endif /* TESTS_KERNEL_ARCH_MIPS_STACK_POINTER_H */
diff --git a/kernel/arch/mips/threadspfunc.S b/kernel/arch/mips/threadspfunc.S
new file mode 100644
index 000000000000..a42362fee67d
--- /dev/null
+++ b/kernel/arch/mips/threadspfunc.S
@@ -0,0 +1,46 @@
+/* $NetBSD: threadspfunc.S,v 1.2 2025/04/21 03:47:32 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: threadspfunc.S,v 1.2 2025/04/21 03:47:32 riastradh Exp $")
+
+ .text
+ .set noreorder
+
+/*
+ * void *threadspfunc(void *cookie@a0)
+ *
+ * pthread_create(3) function. Return the stack pointer on entry.
+ */
+LEAF(threadspfunc)
+ j ra
+ move v0, sp
+END(threadspfunc)
diff --git a/kernel/arch/riscv/contextspfunc.S b/kernel/arch/riscv/contextspfunc.S
new file mode 100644
index 000000000000..7f405123deb3
--- /dev/null
+++ b/kernel/arch/riscv/contextspfunc.S
@@ -0,0 +1,45 @@
+/* $NetBSD: contextspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: contextspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $")
+
+/*
+ * contextspfunc()
+ *
+ * makecontext(3) function. Store the stack pointer on entry at
+ * the global variable contextsp and call contextdone.
+ */
+ENTRY(contextspfunc)
+ PTR_LA t0, _C_LABEL(contextsp) /* t0 := &contextsp */
+ PTR_S sp, 0(t0) /* contextsp := sp */
+ tail _C_LABEL(contextdone) /* tail call contextdone */
+END(contextspfunc)
diff --git a/kernel/arch/riscv/execsp.S b/kernel/arch/riscv/execsp.S
new file mode 100644
index 000000000000..d045cbf0d3af
--- /dev/null
+++ b/kernel/arch/riscv/execsp.S
@@ -0,0 +1,100 @@
+/* $NetBSD: execsp.S,v 1.1 2025/04/20 22:34:07 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: execsp.S,v 1.1 2025/04/20 22:34:07 riastradh Exp $")
+
+/*
+ * void execsp_start(void (*cleanup@a0)(void),
+ * struct ps_strings *ps_strings@a1)
+ *
+ * ELF entry point. Saves the stack pointer in startsp and defers
+ * to the usual csu __start routine.
+ */
+ENTRY(execsp_start)
+ .option push
+ .option norelax /* Don't optimize this into `mv gp, gp'! */
+ lla gp, __global_pointer$
+ .option pop
+
+ PTR_LA t0, _C_LABEL(startsp) /* t0 := &startsp */
+ PTR_S sp, 0(t0) /* startsp := sp */
+ tail _C_LABEL(__start) /* tail call __start */
+END(execsp_start)
+
+/*
+ * void execsp_ctor(void)
+ *
+ * ELF constructor. Saves the stack pointer in ctorsp and
+ * returns.
+ */
+ENTRY(execsp_ctor)
+ PTR_LA t0, _C_LABEL(ctorsp) /* t0 := &ctorsp */
+ PTR_S sp, 0(t0) /* ctorsp := sp */
+ ret
+END(execsp_ctor)
+
+ /* Make execsp_ctor a constructor. */
+ .section .init_array,"aw"
+ .p2align PTR_SCALESHIFT
+ PTR_WORD _C_LABEL(execsp_ctor)
+
+/*
+ * int main(int argc@a0, char **argv@a1, ...)
+ *
+ * Main function. Saves the stack pointer in mainsp and returns
+ * zero. We will call execsp_main in execsp_dtor once dtorsp has
+ * been initialized.
+ */
+ENTRY(main)
+ PTR_LA t0, _C_LABEL(mainsp) /* t0 := &mainsp */
+ PTR_S sp, 0(t0) /* mainsp := sp */
+ li a0, 0 /* return 0 */
+ ret
+END(main)
+
+/*
+ * void execsp_dtor(void)
+ *
+ * ELF destructor. Saves the stack pointer in dtorsp and defers
+ * to the C execsp_main in h_execsp.c to report the stack pointers
+ * back to the t_signal_and_sp parent.
+ */
+ENTRY(execsp_dtor)
+ PTR_LA t0, _C_LABEL(dtorsp) /* t0 := &dtorsp */
+ PTR_S sp, 0(t0) /* dtorsp := sp */
+ tail _C_LABEL(execsp_main) /* tail call execsp_main */
+END(execsp_dtor)
+
+ /* Make execsp_ctor a destructor. */
+ .section .fini_array,"aw"
+ .p2align PTR_SCALESHIFT
+ PTR_WORD _C_LABEL(execsp_dtor)
diff --git a/kernel/arch/riscv/signalsphandler.S b/kernel/arch/riscv/signalsphandler.S
new file mode 100644
index 000000000000..6a5d2f752ee2
--- /dev/null
+++ b/kernel/arch/riscv/signalsphandler.S
@@ -0,0 +1,45 @@
+/* $NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:34:07 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:34:07 riastradh Exp $")
+
+/*
+ * signalsphandler(signo@a0)
+ *
+ * Signal handler. Store the stack pointer on entry at the global
+ * variable signalsp and return.
+ */
+ENTRY(signalsphandler)
+ PTR_LA t0, _C_LABEL(signalsp) /* t0 := &signalsp */
+ PTR_S sp, 0(t0) /* signalsp := sp */
+ ret
+END(signalsphandler)
diff --git a/kernel/arch/riscv/stack_pointer.h b/kernel/arch/riscv/stack_pointer.h
new file mode 100644
index 000000000000..22c246e4a86a
--- /dev/null
+++ b/kernel/arch/riscv/stack_pointer.h
@@ -0,0 +1,35 @@
+/* $NetBSD: stack_pointer.h,v 1.1 2025/04/20 22:34:07 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_RISCV_STACK_POINTER_H
+#define TESTS_KERNEL_ARCH_RISCV_STACK_POINTER_H
+
+#define MISALIGN_SP __asm __volatile("addi sp,sp,-1" ::: "memory")
+#define FIX_SP __asm __volatile("addi sp,sp,1" ::: "memory")
+
+#endif /* TESTS_KERNEL_ARCH_RISCV_STACK_POINTER_H */
diff --git a/kernel/arch/riscv/threadspfunc.S b/kernel/arch/riscv/threadspfunc.S
new file mode 100644
index 000000000000..30291ad2eb73
--- /dev/null
+++ b/kernel/arch/riscv/threadspfunc.S
@@ -0,0 +1,43 @@
+/* $NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:44 riastradh Exp $")
+
+/*
+ * void *threadspfunc(void *cookie@o0)
+ *
+ * pthread_create(3) function. Return the stack pointer on entry.
+ */
+ENTRY(threadspfunc)
+ mv a0, sp /* return sp */
+ ret /* return to caller */
+END(threadspfunc)
diff --git a/kernel/arch/sh3/asm.h b/kernel/arch/sh3/asm.h
new file mode 100644
index 000000000000..16389b5c299e
--- /dev/null
+++ b/kernel/arch/sh3/asm.h
@@ -0,0 +1,58 @@
+/* $NetBSD: asm.h,v 1.1 2025/04/26 22:34:52 uwe Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_SH3_ASM_H
+#define TESTS_KERNEL_ARCH_SH3_ASM_H
+
+#include <machine/asm.h>
+
+/*
+ * We define convenience macros to hide the difference between direct
+ * and PIC function calls, but with variable accesses it gets a bit
+ * more unwieldy, so don't impose this on the general audience
+ */
+
+#ifdef __PIC__
+
+#define VAR_DATUM(v) .long v@GOT
+
+#define MOVL_VAR(label, reg) \
+ mov.l label, r0; \
+ mov.l @(r0, r12), reg
+
+#else
+
+#define VAR_DATUM(v) .long v
+
+#define MOVL_VAR(label, reg) \
+ mov.l label, reg; \
+
+#endif
+
+
+#endif /* TESTS_KERNEL_ARCH_SH3_ASM_H */
diff --git a/kernel/arch/sh3/contextspfunc.S b/kernel/arch/sh3/contextspfunc.S
new file mode 100644
index 000000000000..51e91133417e
--- /dev/null
+++ b/kernel/arch/sh3/contextspfunc.S
@@ -0,0 +1,55 @@
+/* $NetBSD: contextspfunc.S,v 1.1 2025/04/26 22:34:52 uwe Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include "asm.h"
+
+RCSID("$NetBSD: contextspfunc.S,v 1.1 2025/04/26 22:34:52 uwe Exp $")
+
+
+/*
+ * void contextspfunc()
+ *
+ * makecontext(3) function. Store the stack pointer on entry at
+ * the global variable contextsp and call contextdone.
+ */
+ENTRY(contextspfunc)
+ mov sp, r1
+ PIC_PROLOGUE(.L_GOT)
+
+ MOVL_VAR(.L_contextsp, r0)
+ mov.l r1, @r0
+
+ mov.l .L_contextdone, r0
+1: JUMP r0
+ PIC_EPILOGUE_SLOT
+
+ .p2align 2
+.L_GOT: PIC_GOT_DATUM
+.L_contextsp: VAR_DATUM(contextsp)
+.L_contextdone: CALL_DATUM(contextdone, 1b)
+ SET_ENTRY_SIZE(contextspfunc)
diff --git a/kernel/arch/sh3/execsp.S b/kernel/arch/sh3/execsp.S
new file mode 100644
index 000000000000..639ed4e6487b
--- /dev/null
+++ b/kernel/arch/sh3/execsp.S
@@ -0,0 +1,146 @@
+/* $NetBSD: execsp.S,v 1.2 2025/04/27 00:03:46 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include "asm.h"
+
+RCSID("$NetBSD: execsp.S,v 1.2 2025/04/27 00:03:46 riastradh Exp $")
+
+
+/*
+ * void execsp_start()
+ *
+ * ELF entry point. Saves the stack pointer in startsp and defers
+ * to the usual csu __start routine.
+ *
+ * See sys/arch/sh3/sh3/sh3_machdep.c setregs()
+ */
+ENTRY(execsp_start)
+ mov sp, r1 // for consistency, don't need to
+ PIC_PROLOGUE_NOSAVE(.L_start_GOT)
+
+ MOVL_VAR(.L_startsp, r0)
+ mov.l r1, @r0
+
+ mov.l .L___start, r0
+1: JUMP r0
+ nop
+
+ .p2align 2
+.L_start_GOT: PIC_GOT_DATUM
+.L_startsp: VAR_DATUM(startsp)
+.L___start: CALL_DATUM(__start, 1b)
+ SET_ENTRY_SIZE(execsp_start)
+
+
+/*
+ * void execsp_ctor(void)
+ *
+ * ELF constructor. Saves the stack pointer in ctorsp and
+ * returns.
+ */
+ENTRY(execsp_ctor)
+ mov sp, r1
+ PIC_PROLOGUE(.L_ctor_GOT)
+
+ MOVL_VAR(.L_ctorsp, r0)
+ mov.l r1, @r0
+
+ rts
+ PIC_EPILOGUE_SLOT
+
+ .p2align 2
+.L_ctor_GOT: PIC_GOT_DATUM
+.L_ctorsp: VAR_DATUM(ctorsp)
+ SET_ENTRY_SIZE(execsp_ctor)
+
+ /* Make execsp_ctor a constructor. */
+ .pushsection .ctors, "aw", @progbits
+ .p2align 2
+ .long _C_LABEL(execsp_ctor)
+ .popsection
+
+
+/*
+ * int main(int argc, char **argv, ...)
+ *
+ * Main function. Saves the stack pointer in mainsp and returns
+ * zero. We will call execsp_main in execsp_dtor once dtorsp has
+ * been initialized.
+ */
+ENTRY(main)
+ mov sp, r1
+ PIC_PROLOGUE(.L_main_GOT)
+
+ MOVL_VAR(.L_mainsp, r0)
+ mov.l r1, @r0
+
+ PIC_EPILOGUE
+ rts
+ mov #0, r0
+
+ .p2align 2
+.L_main_GOT: PIC_GOT_DATUM
+.L_mainsp: VAR_DATUM(mainsp)
+ SET_ENTRY_SIZE(main)
+
+
+/*
+ * void execsp_dtor(void)
+ *
+ * ELF destructor. Saves the stack pointer in dtorsp and defers
+ * to the C execsp_main in h_execsp.c to report the stack pointers
+ * back to the t_signal_and_sp parent.
+ */
+ENTRY(execsp_dtor)
+ mov sp, r1
+ sts.l pr, @-sp
+ PIC_PROLOGUE(.L_dtor_GOT)
+
+ MOVL_VAR(.L_dtorsp, r0)
+ mov.l r1, @r0
+
+ mov.l .L_execsp_main, r0
+1: CALL r0
+ nop
+
+ PIC_EPILOGUE
+ lds.l @sp+, pr
+ rts
+ nop
+
+ .p2align 2
+.L_dtor_GOT: PIC_GOT_DATUM
+.L_dtorsp: VAR_DATUM(dtorsp)
+.L_execsp_main: CALL_DATUM(execsp_main, 1b)
+ SET_ENTRY_SIZE(execsp_dtor)
+
+ /* Make execsp_ctor a destructor. */
+ .pushsection .dtors, "aw", @progbits
+ .p2align 2
+ .long _C_LABEL(execsp_dtor)
+ .popsection
diff --git a/kernel/arch/sh3/h_execregs.S b/kernel/arch/sh3/h_execregs.S
new file mode 100644
index 000000000000..d7c91161c34a
--- /dev/null
+++ b/kernel/arch/sh3/h_execregs.S
@@ -0,0 +1,86 @@
+/* $NetBSD: h_execregs.S,v 1.1 2025/04/27 02:24:07 uwe Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+#include <machine/asm.h>
+#include <machine/mcontext.h>
+#include <sys/syscall.h>
+
+
+// ELF entry point
+ENTRY(execregs_start)
+ // __gregset_t r; // mcontext (but general regs only)
+ mov.l sp, @-sp
+ mov.l r0, @-sp
+ mov.l r1, @-sp
+ mov.l r2, @-sp
+ mov.l r3, @-sp
+ mov.l r4, @-sp
+ mov.l r5, @-sp
+ mov.l r6, @-sp
+ mov.l r7, @-sp
+ mov.l r8, @-sp
+ mov.l r9, @-sp
+ mov.l r10, @-sp
+ mov.l r11, @-sp
+ mov.l r12, @-sp
+ mov.l r13, @-sp
+ mov.l r14, @-sp
+ sts.l pr, @-sp
+ sts.l mach, @-sp
+ sts.l macl, @-sp
+ mov #0, r0
+ mov.l r0, @-sp // _REG_SR is privileged
+ mova .Lend, r0 // _REG_PC
+ mov.l @r0, r1
+ sub r1, r0
+ mov.l r0, @-sp
+ stc.l gbr, @-sp
+
+ // write(STDOUT_FILENO, &r, sizeof(__gregset_t))
+ mov #1, r4
+ mov sp, r5
+ mov #(_NGREG * 4), r6
+ mov #SYS_write, r0
+ trapa #0x80
+
+ // _exit(0)
+ mov #0, r4
+ mov #SYS_exit, r0
+ trapa #0x80
+
+ .p2align 2
+.Lend: .long .Lend - execregs_start
+ SET_ENTRY_SIZE(execregs_start)
+
+
+// main stub to simplify linking
+ENTRY(main)
+ rts
+ mov #0, r0
+ SET_ENTRY_SIZE(main)
diff --git a/kernel/arch/sh3/signalsphandler.S b/kernel/arch/sh3/signalsphandler.S
new file mode 100644
index 000000000000..e0a86ae40558
--- /dev/null
+++ b/kernel/arch/sh3/signalsphandler.S
@@ -0,0 +1,61 @@
+/* $NetBSD: signalsphandler.S,v 1.2 2025/04/26 23:49:55 uwe Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include "asm.h"
+RCSID("$NetBSD: signalsphandler.S,v 1.2 2025/04/26 23:49:55 uwe Exp $")
+
+
+/*
+ * void signalsphandler(int signo)
+ *
+ * Signal handler. Store the stack pointer on entry at the global
+ * variable signalsp and return.
+ */
+ENTRY(signalsphandler)
+ mov sp, r1
+#ifdef __PIC__
+ // PR kern/59327: don't touch stack as SP may be misaligned
+ // and as SuperH is a strict alignment architecture, we will
+ // get SIGBUS if we try to save registers on the stack
+ mov r12, r2
+#endif
+ PIC_PROLOGUE_NOSAVE(.L_GOT)
+
+ MOVL_VAR(.L_signalsp, r0)
+ mov.l r1, @r0
+
+#ifdef __PIC__
+ mov r2, r12
+#endif
+ rts
+ nop
+
+ .p2align 2
+.L_GOT: PIC_GOT_DATUM
+.L_signalsp: VAR_DATUM(signalsp)
+ SET_ENTRY_SIZE(signalsphandler)
diff --git a/kernel/arch/sh3/stack_pointer.h b/kernel/arch/sh3/stack_pointer.h
new file mode 100644
index 000000000000..ed3366602f56
--- /dev/null
+++ b/kernel/arch/sh3/stack_pointer.h
@@ -0,0 +1,35 @@
+/* $NetBSD: stack_pointer.h,v 1.1 2025/04/26 22:34:52 uwe Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_SH3_STACK_POINTER_H
+#define TESTS_KERNEL_ARCH_SH3_STACK_POINTER_H
+
+#define MISALIGN_SP __asm __volatile("add #-1, sp" ::: "memory")
+#define FIX_SP __asm __volatile("add #+1, sp" ::: "memory")
+
+#endif /* TESTS_KERNEL_ARCH_SH3_STACK_POINTER_H */
diff --git a/kernel/arch/sh3/threadspfunc.S b/kernel/arch/sh3/threadspfunc.S
new file mode 100644
index 000000000000..de065e54191b
--- /dev/null
+++ b/kernel/arch/sh3/threadspfunc.S
@@ -0,0 +1,41 @@
+/* $NetBSD: threadspfunc.S,v 1.1 2025/04/26 22:34:52 uwe Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include "asm.h"
+RCSID("$NetBSD: threadspfunc.S,v 1.1 2025/04/26 22:34:52 uwe Exp $")
+
+
+/*
+ * void *threadspfunc(void *cookie)
+ *
+ * pthread_create(3) function. Return the stack pointer on entry.
+ */
+ENTRY(threadspfunc)
+ rts
+ mov sp, r0
+ SET_ENTRY_SIZE(threadspfunc)
diff --git a/kernel/arch/sparc/contextspfunc.S b/kernel/arch/sparc/contextspfunc.S
new file mode 100644
index 000000000000..a24185cabd73
--- /dev/null
+++ b/kernel/arch/sparc/contextspfunc.S
@@ -0,0 +1,64 @@
+/* $NetBSD: contextspfunc.S,v 1.1 2025/04/21 02:33:45 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: contextspfunc.S,v 1.1 2025/04/21 02:33:45 riastradh Exp $")
+
+#ifdef __PIC__
+#define SETHI(label, got, reg) \
+ set label, reg; /* reg := &label - &GOT */ \
+ ld [got + reg], reg /* reg := &label */
+#define LO(label, reg) \
+ reg
+#else
+#define SETHI(label, got, reg) \
+ sethi %hi(label), reg /* reg := &label - %lo(label) */
+#define LO(label, reg) \
+ reg + %lo(label)
+#endif
+
+ .text
+
+/*
+ * contextspfunc()
+ *
+ * makecontext(3) function. Store the stack pointer on entry at
+ * the global variable contextsp and call contextdone.
+ */
+ENTRY(contextspfunc)
+ /* Reminder: o6 is frame pointer, o7 + 8 is return address. */
+ PIC_PROLOGUE(%g1, %o5) /* g1 := &GOT, clobber o5 */
+ SETHI(_C_LABEL(contextsp), %g1, %o5) /* o5 := &contextsp */
+ call _C_LABEL(contextdone) /* jump to contextdone */
+ st %sp, [LO(_C_LABEL(contextsp), %o5)] /* contextsp := sp */
+ /* don't care what happens here, caller must never return */
+ ta 1 /* Tcc, trap always */
+END(contextspfunc)
diff --git a/kernel/arch/sparc/execsp.S b/kernel/arch/sparc/execsp.S
new file mode 100644
index 000000000000..4b225dd6d550
--- /dev/null
+++ b/kernel/arch/sparc/execsp.S
@@ -0,0 +1,123 @@
+/* $NetBSD: execsp.S,v 1.1 2025/04/20 22:33:41 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: execsp.S,v 1.1 2025/04/20 22:33:41 riastradh Exp $")
+
+#ifdef __PIC__
+#define SETHI(label, got, reg) \
+ set label, reg; /* reg := &label - &GOT */ \
+ ld [got + reg], reg /* reg := &label */
+#define LO(label, reg) \
+ reg
+#else
+#define SETHI(label, got, reg) \
+ sethi %hi(label), reg /* reg := &label - %lo(label) */
+#define LO(label, reg) \
+ reg + %lo(label)
+#endif
+
+ .text
+
+/*
+ * void execsp_start(struct ps_strings *ps_strings@g1,
+ * void *obj_main@g2, void (*cleanup@g3)(void))
+ *
+ * ELF entry point. Saves the stack pointer in startsp and defers
+ * to the usual csu __start routine.
+ */
+ENTRY(execsp_start)
+ PIC_PROLOGUE(%o1, %o2) /* o1 := GOT, clobber o2 */
+ SETHI(_C_LABEL(startsp), %o1, %o2) /* o2 := &startup */
+ call _C_LABEL(__start) /* jump to start via PLT */
+ st %sp, [LO(_C_LABEL(startsp), %o2)] /* startsp := sp */
+ /* don't care what happens here, caller must never return */
+ ta 1 /* Tcc, trap always */
+END(execsp_start)
+
+/*
+ * void execsp_ctor(void)
+ *
+ * ELF constructor. Saves the stack pointer in ctorsp and
+ * returns.
+ */
+ENTRY(execsp_ctor)
+ /* Reminder: o6 is frame pointer, o7 + 8 is return address. */
+ PIC_PROLOGUE(%g1, %o5) /* g1 := &GOT, clobber o5 */
+ SETHI(_C_LABEL(ctorsp), %g1, %o5) /* o5 := &ctorsp */
+ retl /* return to caller */
+ st %sp, [LO(_C_LABEL(ctorsp), %o5)] /* ctorsp := sp */
+END(execsp_ctor)
+
+ /* Make execsp_ctor a constructor. */
+ .pushsection .ctors,"aw",@progbits
+ .p2align 2
+ .long _C_LABEL(execsp_ctor)
+ .popsection
+
+/*
+ * int main(int argc@a0, char **argv@a1, ...)
+ *
+ * Main function. Saves the stack pointer in mainsp and returns
+ * zero. We will call execsp_main in execsp_dtor once dtorsp has
+ * been initialized.
+ */
+ENTRY(main)
+ /* Reminder: o6 is frame pointer, o7 + 8 is return address. */
+ PIC_PROLOGUE(%g1, %o5) /* g1 := &GOT, clobber o5 */
+ SETHI(_C_LABEL(mainsp), %g1, %o5) /* o5 := &mainsp */
+ st %sp, [LO(_C_LABEL(mainsp), %o5)] /* mainsp := sp */
+ retl /* return to caller */
+ mov 0, %o0 /* return 0 */
+END(main)
+
+/*
+ * void execsp_dtor(void)
+ *
+ * ELF destructor. Saves the stack pointer in dtorsp and defers
+ * to the C execsp_main in h_execsp.c to report the stack pointers
+ * back to the t_signal_and_sp parent.
+ */
+ENTRY(execsp_dtor)
+ /* Reminder: o6 is frame pointer, o7 + 8 is return address. */
+ PIC_PROLOGUE(%g1, %o5) /* g1 := &GOT, clobber o5 */
+ SETHI(_C_LABEL(dtorsp), %g1, %o5) /* o5 := &dtorsp - &GOT */
+ st %sp, [LO(_C_LABEL(dtorsp), %o5)] /* dtorsp := sp */
+ mov %o7, %o5 /* save return address */
+ call _C_LABEL(execsp_main) /* tail call to execsp_main */
+ mov %o5, %o7 /* restore return address */
+END(execsp_dtor)
+
+ /* Make execsp_ctor a destructor. */
+ .pushsection .dtors,"aw",@progbits
+ .p2align 2
+ .long _C_LABEL(execsp_dtor)
+ .popsection
diff --git a/kernel/arch/sparc/signalsphandler.S b/kernel/arch/sparc/signalsphandler.S
new file mode 100644
index 000000000000..187091d23c01
--- /dev/null
+++ b/kernel/arch/sparc/signalsphandler.S
@@ -0,0 +1,62 @@
+/* $NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:33:41 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:33:41 riastradh Exp $")
+
+#ifdef __PIC__
+#define SETHI(label, got, reg) \
+ set label, reg; /* reg := &label - &GOT */ \
+ ld [got + reg], reg /* reg := &label */
+#define LO(label, reg) \
+ reg
+#else
+#define SETHI(label, got, reg) \
+ sethi %hi(label), reg /* reg := &label - %lo(label) */
+#define LO(label, reg) \
+ reg + %lo(label)
+#endif
+
+ .text
+
+/*
+ * signalsphandler(signo@o0)
+ *
+ * Signal handler. Store the stack pointer on entry at the global
+ * variable signalsp and return.
+ */
+ENTRY(signalsphandler)
+ /* Reminder: o6 is frame pointer, o7 + 8 is return address. */
+ PIC_PROLOGUE(%g1, %o5) /* g1 := &GOT, clobber o5 */
+ SETHI(_C_LABEL(signalsp), %g1, %o5) /* o5 := &signalsp */
+ retl /* return to caller */
+ st %sp, [LO(_C_LABEL(signalsp), %o5)] /* signalsp := sp */
+END(signalsphandler)
diff --git a/kernel/arch/sparc/stack_pointer.h b/kernel/arch/sparc/stack_pointer.h
new file mode 100644
index 000000000000..20c06bec77cd
--- /dev/null
+++ b/kernel/arch/sparc/stack_pointer.h
@@ -0,0 +1,35 @@
+/* $NetBSD: stack_pointer.h,v 1.1 2025/04/20 22:33:41 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_SPARC_STACK_POINTER_H
+#define TESTS_KERNEL_ARCH_SPARC_STACK_POINTER_H
+
+#define MISALIGN_SP __asm __volatile("dec %%sp" ::: "memory")
+#define FIX_SP __asm __volatile("inc %%sp" ::: "memory")
+
+#endif /* TESTS_KERNEL_ARCH_SPARC_STACK_POINTER_H */
diff --git a/kernel/arch/sparc/threadspfunc.S b/kernel/arch/sparc/threadspfunc.S
new file mode 100644
index 000000000000..794804d85741
--- /dev/null
+++ b/kernel/arch/sparc/threadspfunc.S
@@ -0,0 +1,45 @@
+/* $NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:45 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: threadspfunc.S,v 1.1 2025/04/21 02:33:45 riastradh Exp $")
+
+ .text
+
+/*
+ * void *threadspfunc(void *cookie@o0)
+ *
+ * pthread_create(3) function. Return the stack pointer on entry.
+ */
+ENTRY(threadspfunc)
+ retl /* return to caller */
+ mov %sp, %o0 /* return sp */
+END(threadspfunc)
diff --git a/kernel/arch/vax/execregs.c b/kernel/arch/vax/execregs.c
new file mode 100644
index 000000000000..414b810336d8
--- /dev/null
+++ b/kernel/arch/vax/execregs.c
@@ -0,0 +1,166 @@
+/* $NetBSD: execregs.c,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: execregs.c,v 1.1 2025/02/27 00:55:32 riastradh Exp $");
+
+#include "execregs.h"
+
+#include <errno.h>
+#include <spawn.h>
+#include <stddef.h>
+#include <unistd.h>
+
+extern char **environ;
+
+static unsigned long
+nonnull(unsigned long x)
+{
+
+ x |= x << 8;
+ x |= x << 16;
+ return x;
+}
+
+int
+execregschild(char *path)
+{
+ /* fp: frame pointer, nonnull */
+ /* ap: argument pointer, on user stack, nonnull */
+ /* sp: stack pointer, nonnull */
+ register long r0 __asm("r0") = nonnull(0x10);
+ register long r1 __asm("r1") = nonnull(1);
+ register long r2 __asm("r2") = nonnull(2);
+ register long r3 __asm("r3") = nonnull(3);
+ register long r4 __asm("r4") = nonnull(4);
+ register long r5 __asm("r5") = nonnull(5);
+ register long r6 __asm("r6") = nonnull(6);
+ register long r7 __asm("r7") = nonnull(7);
+ register long r8 __asm("r8") = nonnull(8);
+ register long r9 __asm("r9") = nonnull(9);
+ register long r10 __asm("r10") = nonnull(10);
+ register long r11 __asm("r11") = nonnull(11);
+ /* pc: user PC, will be nonnull */
+ /* psl: processor status longword, will be nonnull */
+
+ char *argv[] = {path, NULL};
+ char **envp = environ;
+
+ /*
+ * Not perfect -- compiler might use some registers for
+ * stack/argument transfers, but all the arguments are nonnull
+ * so this is probably a good test anyway.
+ */
+ __asm volatile("" :
+ "+r"(r0),
+ "+r"(r1),
+ "+r"(r2),
+ "+r"(r3),
+ "+r"(r4),
+ "+r"(r5),
+ "+r"(r6),
+ "+r"(r7),
+ "+r"(r8),
+ "+r"(r9),
+ "+r"(r10),
+ "+r"(r11)
+ :: "memory");
+
+ return execve(path, argv, envp);
+}
+
+pid_t
+spawnregschild(char *path, int fd)
+{
+ /* fp: frame pointer, nonnull */
+ /* ap: argument pointer, on user stack, nonnull */
+ /* sp: stack pointer, nonnull */
+ register long r0 __asm("r0") = nonnull(0x10);
+ register long r1 __asm("r1") = nonnull(1);
+ register long r2 __asm("r2") = nonnull(2);
+ register long r3 __asm("r3") = nonnull(3);
+ register long r4 __asm("r4") = nonnull(4);
+ register long r5 __asm("r5") = nonnull(5);
+ register long r6 __asm("r6") = nonnull(6);
+ register long r7 __asm("r7") = nonnull(7);
+ register long r8 __asm("r8") = nonnull(8);
+ register long r9 __asm("r9") = nonnull(9);
+ register long r10 __asm("r10") = nonnull(10);
+ register long r11 __asm("r11") = nonnull(11);
+ /* pc: user PC, will be nonnull */
+ /* psl: processor status longword, will be nonnull */
+
+ char *argv[] = {path, NULL};
+ char **envp = environ;
+ posix_spawn_file_actions_t fileacts;
+ posix_spawnattr_t attr;
+ pid_t pid;
+ int error;
+
+ error = posix_spawn_file_actions_init(&fileacts);
+ if (error)
+ goto out;
+ error = posix_spawn_file_actions_adddup2(&fileacts, fd, STDOUT_FILENO);
+ if (error)
+ goto out;
+ error = posix_spawnattr_init(&attr);
+ if (error)
+ goto out;
+
+ /*
+ * Not perfect -- compiler might use some registers for
+ * stack/argument transfers, but all the arguments are nonnull
+ * so this is probably a good test anyway.
+ */
+ __asm volatile("" :
+ "+r"(r0),
+ "+r"(r1),
+ "+r"(r2),
+ "+r"(r3),
+ "+r"(r4),
+ "+r"(r5),
+ "+r"(r6),
+ "+r"(r7),
+ "+r"(r8),
+ "+r"(r9),
+ "+r"(r10),
+ "+r"(r11)
+ :: "memory");
+
+ error = posix_spawn(&pid, path, &fileacts, &attr, argv, envp);
+ if (error)
+ goto out;
+
+out: posix_spawnattr_destroy(&attr);
+ posix_spawn_file_actions_destroy(&fileacts);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
diff --git a/kernel/arch/vax/execregs.h b/kernel/arch/vax/execregs.h
new file mode 100644
index 000000000000..882bcd1b6702
--- /dev/null
+++ b/kernel/arch/vax/execregs.h
@@ -0,0 +1,77 @@
+/* $NetBSD: execregs.h,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_VAX_EXECREGS_H
+#define TESTS_KERNEL_ARCH_VAX_EXECREGS_H
+
+#include <sys/cdefs.h>
+
+#define NEXECREGS 12
+
+#ifndef _LOCORE
+
+#include <unistd.h>
+
+/*
+ * The order matches that in struct trapframe in
+ * sys/arch/vax/include/trap.h
+ *
+ * Must match h_execregs.S.
+ *
+ * See also sys/arch/vax/vax/trap.c:setregs()
+ */
+static const char *const regname[] = {
+ "fp", /* Stack frame pointer */
+ "ap", /* Argument pointer on user stack */
+ /* sp: stack pointer */
+ "r0", /* General registers saved upon trap/syscall */
+ "r1",
+ "r2",
+ "r3",
+ "r4",
+ "r5",
+ /* r6: initial stack pointer */
+ "r7",
+ "r8",
+ /* r9: ps_strings */
+ "r10",
+ "r11",
+ /* trap: type of trap, not a register */
+ /* code: trap specific code, not a register */
+ /* pc: user PC */
+ /* psl: processor status longword */
+};
+
+__CTASSERT(NEXECREGS == __arraycount(regname));
+
+int execregschild(char *);
+pid_t spawnregschild(char *, int);
+
+#endif /* _LOCORE */
+
+#endif /* TESTS_KERNEL_ARCH_VAX_EXECREGS_H */
diff --git a/kernel/arch/vax/h_execregs.S b/kernel/arch/vax/h_execregs.S
new file mode 100644
index 000000000000..27c5c2052867
--- /dev/null
+++ b/kernel/arch/vax/h_execregs.S
@@ -0,0 +1,87 @@
+/* $NetBSD: h_execregs.S,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <sys/syscall.h>
+
+#include <machine/asm.h>
+
+#include "execregs.h"
+
+#define REGSIZE 4
+#define BUFSIZE (NEXECREGS * REGSIZE)
+#define SLOT(n) (n)*REGSIZE(%sp)
+
+ENTRY(execregs_start, 0)
+ /* store registers to a buffer on stack */
+ subl2 $BUFSIZE,%sp /* space for NEXECREGS registers */
+ movl %fp,SLOT(0) /* order matches execregs.h */
+ movl %ap,SLOT(1)
+ /* sp: stack pointer */
+ movl %r0,SLOT(2)
+ movl %r1,SLOT(3)
+ movl %r2,SLOT(4)
+ movl %r3,SLOT(5)
+ movl %r4,SLOT(6)
+ movl %r5,SLOT(7)
+ /* r6: initial stack pointer */
+ movl %r7,SLOT(8)
+ movl %r8,SLOT(9)
+ /* r9: ps_strings */
+ movl %r10,SLOT(10)
+ movl %r11,SLOT(11)
+
+ /* call write(STDOUT_FILENO, regs, sizeof(regs)) */
+ pushl $BUFSIZE /* arg2 := sizeof(regs) */
+ pushal 4(%sp) /* arg1 := regs */
+ pushl $1 /* arg0 := STDOUT_FILENO */
+ pushl $3 /* number of arguments */
+ movl %sp,%ap /* argument pointer */
+ chmk $SYS_write
+
+ bcs 2f /* bail if write failed */
+ cmpl $BUFSIZE,%r0 /* bail if wrote wrong # of bytes */
+ bneq 2f
+
+ /* call exit(0) */
+ pushl $0 /* arg0 := 0 */
+1: pushl $1 /* number of arguments */
+ movl %sp,%ap /* argument pointer */
+ chmk $SYS_exit
+ .word 0xffff /* paranoia -- illegal opcode */
+
+2: /* call exit(127) */
+ pushl $127 /* arg0 := 127 */
+ jmp 1b
+END(execregs_start)
+
+/* main stub to simplify linking */
+ENTRY(main, 0)
+ .word 0xffff /* illegal opcode */
+END(main)
diff --git a/kernel/arch/x86_64/contextspfunc.S b/kernel/arch/x86_64/contextspfunc.S
new file mode 100644
index 000000000000..d01e1dcdcaf3
--- /dev/null
+++ b/kernel/arch/x86_64/contextspfunc.S
@@ -0,0 +1,55 @@
+/* $NetBSD: contextspfunc.S,v 1.1 2025/04/21 02:33:45 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: contextspfunc.S,v 1.1 2025/04/21 02:33:45 riastradh Exp $")
+
+/*
+ * contextspfunc()
+ *
+ * makecontext(3) function. Store the stack pointer on entry at
+ * the global variable contextsp and call contextdone.
+ */
+ENTRY(contextspfunc)
+ /*
+ * `The end of the input argument area shall be aligned on a
+ * [16-byte] boundary. In other words, the value of (%rsp + 8)
+ * is always a multiple of 16 when control is transferred to
+ * the function entry point.'
+ *
+ * To make it convenient for t_signal_and_sp.c, we subtract 8
+ * from %rsp in order to get something congruent to zero modulo
+ * the stack alignemnt.
+ */
+ movq %rsp,_C_LABEL(contextsp)(%rip)
+ addq $-8,_C_LABEL(contextsp)(%rip)
+ call _C_LABEL(contextdone)
+END(contextspfunc)
diff --git a/kernel/arch/x86_64/execregs.c b/kernel/arch/x86_64/execregs.c
new file mode 100644
index 000000000000..fad1b40daa5e
--- /dev/null
+++ b/kernel/arch/x86_64/execregs.c
@@ -0,0 +1,156 @@
+/* $NetBSD: execregs.c,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: execregs.c,v 1.1 2025/02/27 00:55:32 riastradh Exp $");
+
+#include "execregs.h"
+
+#include <errno.h>
+#include <spawn.h>
+#include <stddef.h>
+#include <unistd.h>
+
+extern char **environ;
+
+static unsigned long
+nonnull(unsigned long x)
+{
+
+ x |= x << 8;
+ x |= x << 16;
+ x |= x << 32;
+ return x;
+}
+
+int
+execregschild(char *path)
+{
+ /* rdi: used to pass exec arg0, nonnull anyway (path) */
+ /* rsi: used to pass exec arg1, nonnull anyway (argv) */
+ /* rdx: used to pass exec arg2, nonnull anyway (environ) */
+ register long r10 __asm("r10") = nonnull(10);
+ register long r8 __asm("r8") = nonnull(8);
+ register long r9 __asm("r9") = nonnull(9);
+ register long rcx __asm("rcx") = nonnull('c');
+ register long r11 __asm("r11") = nonnull(11);
+ register long r12 __asm("r12") = nonnull(12);
+ register long r13 __asm("r13") = nonnull(13);
+ register long r14 __asm("r14") = nonnull(14);
+ register long r15 __asm("r15") = nonnull(15);
+ /* rbp: frame pointer, can't touch that here, but it'll be nonnull */
+ /* rbx: ps_strings, passed to child */
+ register long rax __asm("rax") = nonnull('a');
+
+ char *argv[] = {path, NULL};
+ char **envp = environ;
+
+ /*
+ * Not perfect -- compiler might use some registers for
+ * stack/argument transfers, but all the arguments are nonnull
+ * so this is probably a good test anyway.
+ */
+ __asm volatile("" :
+ "+r"(r10),
+ "+r"(r8),
+ "+r"(r9),
+ "+r"(rcx),
+ "+r"(r11),
+ "+r"(r12),
+ "+r"(r13),
+ "+r"(r14),
+ "+r"(r15),
+ "+r"(rax)
+ :: "memory");
+
+ return execve(path, argv, envp);
+}
+
+pid_t
+spawnregschild(char *path, int fd)
+{
+ /* rdi: used to pass posix_spawn arg0, nonnull anyway (&pid) */
+ /* rsi: used to pass posix_spawn arg1, nonnull anyway (path) */
+ /* rdx: used to pass posix_spawn arg2, nonnull anyway (&fileacts) */
+ register long r10 __asm("r10") = nonnull(10);
+ /* r8: used to pass posix_spawn arg4, nonnull anyway (argv) */
+ /* r9: used to pass posix_spawn arg5, nonnull anyway (environ) */
+ /* rcx: used to pass posix_spawn arg3, nonnull anyway (&attr) */
+ register long r11 __asm("r11") = nonnull(11);
+ register long r12 __asm("r12") = nonnull(12);
+ register long r13 __asm("r13") = nonnull(13);
+ register long r14 __asm("r14") = nonnull(14);
+ register long r15 __asm("r15") = nonnull(15);
+ /* rbp: frame pointer, can't touch that here, but it'll be nonnull */
+ /* rbx: ps_strings, passed to child */
+ register long rax __asm("rax") = nonnull('a');
+
+ char *argv[] = {path, NULL};
+ char **envp = environ;
+ posix_spawn_file_actions_t fileacts;
+ posix_spawnattr_t attr;
+ pid_t pid;
+ int error;
+
+ error = posix_spawn_file_actions_init(&fileacts);
+ if (error)
+ goto out;
+ error = posix_spawn_file_actions_adddup2(&fileacts, fd, STDOUT_FILENO);
+ if (error)
+ goto out;
+ error = posix_spawnattr_init(&attr);
+ if (error)
+ goto out;
+
+ /*
+ * Not perfect -- compiler might use some registers for
+ * stack/argument transfers, but all the arguments are nonnull
+ * so this is probably a good test anyway.
+ */
+ __asm volatile("" :
+ "+r"(r10),
+ "+r"(r11),
+ "+r"(r12),
+ "+r"(r13),
+ "+r"(r14),
+ "+r"(r15),
+ "+r"(rax)
+ :: "memory");
+
+ error = posix_spawn(&pid, path, &fileacts, &attr, argv, envp);
+ if (error)
+ goto out;
+
+out: posix_spawnattr_destroy(&attr);
+ posix_spawn_file_actions_destroy(&fileacts);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
diff --git a/kernel/arch/x86_64/execregs.h b/kernel/arch/x86_64/execregs.h
new file mode 100644
index 000000000000..904991777483
--- /dev/null
+++ b/kernel/arch/x86_64/execregs.h
@@ -0,0 +1,81 @@
+/* $NetBSD: execregs.h,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_X86_64_EXECREGS_H
+#define TESTS_KERNEL_ARCH_X86_64_EXECREGS_H
+
+#include <sys/cdefs.h>
+
+#define NEXECREGS 14
+
+#ifndef _LOCORE
+
+#include <unistd.h>
+
+/*
+ * Ordered by _FRAME_REG in sys/arch/amd64/include/frame_regs.h for
+ * convenience of auditing. Must match h_execregs.S.
+ */
+static const char *const regname[] = {
+ "rdi",
+ "rsi",
+ "rdx",
+ "r10",
+ "r8",
+ "r9",
+ /* arg6: syscall arg from stack, not a real register */
+ /* arg7: syscall arg from stack, not a real register */
+ /* arg8: syscall arg from stack, not a real register */
+ /* arg9: syscall arg from stack, not a real register */
+ "rcx",
+ "r11",
+ "r12",
+ "r13",
+ "r14",
+ "r15",
+ "rbp",
+ /* rbx: ps_strings */
+ "rax",
+ /* gs/fs/es/ds: segment registers, not really registers */
+ /* trapno: not a register */
+ /* err: not a register */
+ /* rip: instruction pointer */
+ /* cs: segment register */
+ /* rflags */
+ /* rsp: stack pointer */
+ /* ss: stack selector */
+};
+
+__CTASSERT(NEXECREGS == __arraycount(regname));
+
+int execregschild(char *);
+pid_t spawnregschild(char *, int);
+
+#endif /* _LOCORE */
+
+#endif /* TESTS_KERNEL_ARCH_X86_64_EXECREGS_H */
diff --git a/kernel/arch/x86_64/execsp.S b/kernel/arch/x86_64/execsp.S
new file mode 100644
index 000000000000..d351dfb2d9e8
--- /dev/null
+++ b/kernel/arch/x86_64/execsp.S
@@ -0,0 +1,111 @@
+/* $NetBSD: execsp.S,v 1.2 2025/04/20 22:31:25 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: execsp.S,v 1.2 2025/04/20 22:31:25 riastradh Exp $")
+
+/*
+ * void execsp_start(void (*cleanup@rbx)(void), void *obj_main@rcx,
+ * struct ps_strings *ps_strings@rbx)
+ *
+ * ELF entry point. Saves the stack pointer in startsp and defers
+ * to the usual csu __start routine.
+ */
+ENTRY(execsp_start)
+ movq %rsp,_C_LABEL(startsp)(%rip)
+ /*
+ * No adjustment like in main because entry point is special
+ * and the amd64 csu __start routine takes care of it.
+ *
+ * XXX Why don't we just arrange to align it in the kernel
+ * anyway?
+ */
+ jmp _C_LABEL(__start)
+END(execsp_start)
+
+/*
+ * void execsp_ctor(void)
+ *
+ * ELF constructor. Saves the stack pointer in ctorsp and
+ * returns.
+ */
+ENTRY(execsp_ctor)
+ /*
+ * `The end of the input argument area shall be aligned on a
+ * [16-byte] boundary. In other words, the value of (%rsp + 8)
+ * is always a multiple of 16 when control is transferred to
+ * the function entry point.'
+ *
+ * To make it convenient for t_signal_and_sp.c, we subtract 8
+ * from %rsp in order to get something congruent to zero modulo
+ * the stack alignemnt.
+ */
+ movq %rsp,_C_LABEL(ctorsp)(%rip)
+ addq $-8,_C_LABEL(ctorsp)(%rip)
+ ret
+END(execsp_ctor)
+
+ /* Make execsp_ctor a constructor. */
+ .section .ctors,"aw",@progbits
+ .p2align 3
+ .quad _C_LABEL(execsp_ctor)
+
+/*
+ * int main(int argc@rdi, char **argv@rsi, ...)
+ *
+ * Main function. Saves the stack pointer in mainsp and returns
+ * zero. We will call execsp_main in execsp_dtor once dtorsp has
+ * been initialized.
+ */
+ENTRY(main)
+ movq %rsp,_C_LABEL(mainsp)(%rip)
+ addq $-8,_C_LABEL(mainsp)(%rip)
+ xorl %eax,%eax
+ ret
+END(main)
+
+/*
+ * void execsp_dtor(void)
+ *
+ * ELF destructor. Saves the stack pointer in dtorsp and defers
+ * to the C execsp_main in h_execsp.c to report the stack pointers
+ * back to the t_signal_and_sp parent.
+ */
+ENTRY(execsp_dtor)
+ movq %rsp,_C_LABEL(dtorsp)(%rip)
+ addq $-8,_C_LABEL(dtorsp)(%rip)
+ jmp _C_LABEL(execsp_main)
+END(execsp_dtor)
+
+ /* Make execsp_ctor a destructor. */
+ .section .dtors,"aw",@progbits
+ .p2align 3
+ .quad _C_LABEL(execsp_dtor)
diff --git a/kernel/arch/x86_64/h_execregs.S b/kernel/arch/x86_64/h_execregs.S
new file mode 100644
index 000000000000..638f73940f06
--- /dev/null
+++ b/kernel/arch/x86_64/h_execregs.S
@@ -0,0 +1,82 @@
+/* $NetBSD: h_execregs.S,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <sys/syscall.h>
+
+#include <machine/asm.h>
+
+#include "execregs.h"
+
+ENTRY(execregs_start)
+ andq $-0x10,%rsp /* align stack to 16-byte boundary */
+
+ /* store registers to a buffer on stack */
+ subq $(NEXECREGS*8),%rsp /* space for NEXECREGS registers */
+ movq %rdi,0*8(%rsp) /* order matches execregs.h */
+ movq %rsi,1*8(%rsp)
+ movq %rdx,2*8(%rsp)
+ movq %r10,3*8(%rsp)
+ movq %r8,4*8(%rsp)
+ movq %r9,5*8(%rsp)
+ movq %rcx,6*8(%rsp)
+ movq %r11,7*8(%rsp)
+ movq %r12,8*8(%rsp)
+ movq %r13,9*8(%rsp)
+ movq %r14,10*8(%rsp)
+ movq %r15,11*8(%rsp)
+ movq %rbp,12*8(%rsp)
+ movq %rax,13*8(%rsp)
+
+ /* call write(STDOUT_FILENO, regs, sizeof(regs)) */
+ movl $0x1,%edi /* arg0 := STDOUT_FILENO */
+ movq %rsp,%rsi /* arg1 := regs */
+ movl $(NEXECREGS*8),%edx /* arg2 := sizeof(regs) */
+ movl $SYS_write,%eax /* syscall number */
+ syscall
+
+ jb 2f /* bail if write failed */
+ cmpq $(NEXECREGS*8),%rax /* bail if wrote wrong # of bytes */
+ jne 2f
+
+ /* call exit(0) */
+ xorl %edi,%edi /* arg0 := 0 */
+1: movl $SYS_exit,%eax /* syscall number */
+ syscall
+ hlt /* paranoia */
+
+2: /* call exit(127) */
+ movl $127,%edi /* arg0 := 127 */
+ jmp 1b
+END(execregs_start)
+
+/* main stub to simplify linking */
+ENTRY(main)
+ hlt
+END(main)
diff --git a/kernel/arch/x86_64/signalsphandler.S b/kernel/arch/x86_64/signalsphandler.S
new file mode 100644
index 000000000000..b53cb005d0b0
--- /dev/null
+++ b/kernel/arch/x86_64/signalsphandler.S
@@ -0,0 +1,55 @@
+/* $NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:31:01 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: signalsphandler.S,v 1.1 2025/04/20 22:31:01 riastradh Exp $")
+
+/*
+ * signalsphandler(signo@rdi)
+ *
+ * Signal handler. Store the stack pointer on entry at the global
+ * variable signalsp and return.
+ */
+ENTRY(signalsphandler)
+ /*
+ * `The end of the input argument area shall be aligned on a
+ * [16-byte] boundary. In other words, the value of (%rsp + 8)
+ * is always a multiple of 16 when control is transferred to
+ * the function entry point.'
+ *
+ * To make it convenient for t_signal_and_sp.c, we subtract 8
+ * from %rsp in order to get something congruent to zero modulo
+ * the stack alignemnt.
+ */
+ movq %rsp,_C_LABEL(signalsp)(%rip)
+ addq $-8,_C_LABEL(signalsp)(%rip)
+ ret
+END(signalsphandler)
diff --git a/kernel/arch/x86_64/stack_pointer.h b/kernel/arch/x86_64/stack_pointer.h
new file mode 100644
index 000000000000..6ea297cf97d9
--- /dev/null
+++ b/kernel/arch/x86_64/stack_pointer.h
@@ -0,0 +1,35 @@
+/* $NetBSD: stack_pointer.h,v 1.1 2025/04/20 22:31:01 riastradh Exp $ */
+
+/*
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef TESTS_KERNEL_ARCH_X86_64_STACK_POINTER_H
+#define TESTS_KERNEL_ARCH_X86_64_STACK_POINTER_H
+
+#define MISALIGN_SP __asm __volatile("addq $-1,%rsp")
+#define FIX_SP __asm __volatile("addq $1,%rsp")
+
+#endif /* TESTS_KERNEL_ARCH_X86_64_STACK_POINTER_H */
diff --git a/kernel/arch/x86_64/threadspfunc.S b/kernel/arch/x86_64/threadspfunc.S
new file mode 100644
index 000000000000..c939f36b408a
--- /dev/null
+++ b/kernel/arch/x86_64/threadspfunc.S
@@ -0,0 +1,54 @@
+/* $NetBSD: threadspfunc.S,v 1.2 2025/04/21 12:06:08 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LOCORE
+
+#include <machine/asm.h>
+
+RCSID("$NetBSD: threadspfunc.S,v 1.2 2025/04/21 12:06:08 riastradh Exp $")
+
+/*
+ * void *threadspfunc(void *cookie@rdi)
+ *
+ * pthread_create(3) function. Return the stack pointer on entry.
+ */
+ENTRY(threadspfunc)
+ /*
+ * `The end of the input argument area shall be aligned on a
+ * [16-byte] boundary. In other words, the value of (%rsp + 8)
+ * is always a multiple of 16 when control is transferred to
+ * the function entry point.'
+ *
+ * To make it convenient for t_signal_and_sp.c, we subtract 8
+ * from %rsp in order to get something congruent to zero modulo
+ * the stack alignemnt.
+ */
+ movq %rsp,%rax
+ addq $-8,%rax
+ ret
+END(threadspfunc)