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 */

Reply via email to