Module Name: src
Committed By: riastradh
Date: Fri Feb 28 16:08:19 UTC 2025
Modified Files:
src/tests/kernel: Makefile t_execregs.c
src/tests/kernel/arch/hppa: execregs.c execregs.h h_execregs.S
Log Message:
t_execregs: Test some more registers on hppa.
Looks like we're missing zeroing of floating-point registers too, as
well as the carry/borrow and divide step correction bits in the
semi-secret PSW register.
Unfortunately, while investigating this, I discovered that qemu's
hppa implementation doesn't implement fpu traps even if the fpu is
disabled (relevant bits of CR 10 `CCR', Coprocessor Control Register,
are cleared), which breaks fpu switching on NetBSD. So I can't test
properly this myself. We should maybe just change NetBSD from lazy
fpu switching to eager fpu switching anyway to thwart Spectre-class
attacks if there's any hppa hardware out there that does speculative
execution.
PR kern/59084: exec/spawn leaks register content
To generate a diff of this commit:
cvs rdiff -u -r1.85 -r1.86 src/tests/kernel/Makefile
cvs rdiff -u -r1.1 -r1.2 src/tests/kernel/t_execregs.c
cvs rdiff -u -r1.1 -r1.2 src/tests/kernel/arch/hppa/execregs.c \
src/tests/kernel/arch/hppa/execregs.h \
src/tests/kernel/arch/hppa/h_execregs.S
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/tests/kernel/Makefile
diff -u src/tests/kernel/Makefile:1.85 src/tests/kernel/Makefile:1.86
--- src/tests/kernel/Makefile:1.85 Thu Feb 27 00:55:31 2025
+++ src/tests/kernel/Makefile Fri Feb 28 16:08:19 2025
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.85 2025/02/27 00:55:31 riastradh Exp $
+# $NetBSD: Makefile,v 1.86 2025/02/28 16:08:19 riastradh Exp $
NOMAN= # defined
@@ -138,6 +138,7 @@ LDADD.h_segv+= -lm
ARCHDIR:= ${.PARSEDIR}/arch/${MACHINE_ARCH}
.PATH: ${ARCHDIR}
CPPFLAGS.t_execregs.c+= -I${ARCHDIR}
+CPPFLAGS.t_execregs.c+= -I${.CURDIR}/../lib/libc/gen # isqemu.h
CPPFLAGS.t_execregs.c+= -DHAVE_EXECREGS_TEST
SRCS.t_execregs+= t_execregs.c
SRCS.t_execregs+= execregs.c
Index: src/tests/kernel/t_execregs.c
diff -u src/tests/kernel/t_execregs.c:1.1 src/tests/kernel/t_execregs.c:1.2
--- src/tests/kernel/t_execregs.c:1.1 Thu Feb 27 00:55:31 2025
+++ src/tests/kernel/t_execregs.c Fri Feb 28 16:08:19 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: t_execregs.c,v 1.1 2025/02/27 00:55:31 riastradh Exp $ */
+/* $NetBSD: t_execregs.c,v 1.2 2025/02/28 16:08:19 riastradh Exp $ */
/*-
* Copyright (c) 2025 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: t_execregs.c,v 1.1 2025/02/27 00:55:31 riastradh Exp $");
+__RCSID("$NetBSD: t_execregs.c,v 1.2 2025/02/28 16:08:19 riastradh Exp $");
#include <sys/wait.h>
@@ -42,6 +42,7 @@ __RCSID("$NetBSD: t_execregs.c,v 1.1 202
#ifdef HAVE_EXECREGS_TEST
#include "execregs.h"
+#include "isqemu.h"
#include "h_macros.h"
static void
@@ -71,6 +72,13 @@ checkregs(const register_t regs[static N
{
unsigned i;
+#ifdef __hppa__
+ if (isQEMU()) {
+ atf_tc_expect_fail("PR port-hppa/59114: hppa:"
+ " eager fpu switching for qemu and/or spectre mitigation");
+ }
+#endif
+
#if defined(__hppa__) || \
defined(__ia64__) || \
defined(__vax__) || \
Index: src/tests/kernel/arch/hppa/execregs.c
diff -u src/tests/kernel/arch/hppa/execregs.c:1.1 src/tests/kernel/arch/hppa/execregs.c:1.2
--- src/tests/kernel/arch/hppa/execregs.c:1.1 Thu Feb 27 00:55:32 2025
+++ src/tests/kernel/arch/hppa/execregs.c Fri Feb 28 16:08:19 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: execregs.c,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+/* $NetBSD: execregs.c,v 1.2 2025/02/28 16:08:19 riastradh Exp $ */
/*-
* Copyright (c) 2025 The NetBSD Foundation, Inc.
@@ -27,13 +27,14 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: execregs.c,v 1.1 2025/02/27 00:55:32 riastradh Exp $");
+__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;
@@ -47,6 +48,105 @@ nonnull(unsigned long x)
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)
{
@@ -111,6 +211,9 @@ execregschild(char *path)
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
@@ -230,6 +333,9 @@ spawnregschild(char *path, int fd)
if (error)
goto out;
+ setfpregs();
+ setpsw();
+
/*
* Not perfect -- compiler might use some registers for
* stack/argument transfers, but all the arguments are nonnull
Index: src/tests/kernel/arch/hppa/execregs.h
diff -u src/tests/kernel/arch/hppa/execregs.h:1.1 src/tests/kernel/arch/hppa/execregs.h:1.2
--- src/tests/kernel/arch/hppa/execregs.h:1.1 Thu Feb 27 00:55:32 2025
+++ src/tests/kernel/arch/hppa/execregs.h Fri Feb 28 16:08:19 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: execregs.h,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+/* $NetBSD: execregs.h,v 1.2 2025/02/28 16:08:19 riastradh Exp $ */
/*-
* Copyright (c) 2025 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
-#define NEXECREGS 31
+#define NEXECREGS 96
#ifndef _LOCORE
@@ -77,6 +77,74 @@ static const char *const regname[] = {
"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));
Index: src/tests/kernel/arch/hppa/h_execregs.S
diff -u src/tests/kernel/arch/hppa/h_execregs.S:1.1 src/tests/kernel/arch/hppa/h_execregs.S:1.2
--- src/tests/kernel/arch/hppa/h_execregs.S:1.1 Thu Feb 27 00:55:32 2025
+++ src/tests/kernel/arch/hppa/h_execregs.S Fri Feb 28 16:08:19 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: h_execregs.S,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */
+/* $NetBSD: h_execregs.S,v 1.2 2025/02/28 16:08:19 riastradh Exp $ */
/*-
* Copyright (c) 2025 The NetBSD Foundation, Inc.
@@ -99,6 +99,45 @@ _ENTRY(execregs_start)
/* 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 */