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