Module Name:    src
Committed By:   mgorny
Date:           Fri Oct  9 17:43:30 UTC 2020

Modified Files:
        src/tests/lib/libc/sys: t_ptrace_x86_wait.h

Log Message:
Add tests for x87 FPU registers

Reviewed by kamil


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/tests/lib/libc/sys/t_ptrace_x86_wait.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/lib/libc/sys/t_ptrace_x86_wait.h
diff -u src/tests/lib/libc/sys/t_ptrace_x86_wait.h:1.26 src/tests/lib/libc/sys/t_ptrace_x86_wait.h:1.27
--- src/tests/lib/libc/sys/t_ptrace_x86_wait.h:1.26	Fri Oct  9 17:43:07 2020
+++ src/tests/lib/libc/sys/t_ptrace_x86_wait.h	Fri Oct  9 17:43:30 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: t_ptrace_x86_wait.h,v 1.26 2020/10/09 17:43:07 mgorny Exp $	*/
+/*	$NetBSD: t_ptrace_x86_wait.h,v 1.27 2020/10/09 17:43:30 mgorny Exp $	*/
 
 /*-
  * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc.
@@ -2186,6 +2186,21 @@ union x86_test_register {
 	uint32_t u32;
 };
 
+struct x86_test_fpu_registers {
+	struct {
+		uint64_t mantissa;
+		uint16_t sign_exp;
+	} __aligned(16) st[8];
+
+	uint16_t cw;
+	uint16_t sw;
+	uint16_t tw;
+	uint8_t tw_abridged;
+	uint16_t opcode;
+	union fp_addr ip;
+	union fp_addr dp;
+};
+
 enum x86_test_regset {
 	TEST_GPREGS,
 	TEST_FPREGS,
@@ -2201,6 +2216,7 @@ enum x86_test_registers {
 	GPREGS_64,
 	GPREGS_64_R8,
 	/* TEST_FPREGS/TEST_XMMREGS */
+	FPREGS_FPU,
 	FPREGS_MM,
 	FPREGS_XMM,
 	/* TEST_XSTATE */
@@ -2419,6 +2435,79 @@ static __inline void set_gp64_r8_regs(co
 #endif
 }
 
+static __inline void get_fpu_regs(struct x86_test_fpu_registers *out)
+{
+	struct save87 fsave;
+	struct fxsave fxsave;
+
+	__CTASSERT(sizeof(out->st[0]) == 16);
+
+	__asm__ __volatile__(
+		"finit\n\t"
+		"int3\n\t"
+#if defined(__x86_64__)
+		"fxsave64 %2\n\t"
+#else
+		"fxsave %2\n\t"
+#endif
+		"fnstenv %1\n\t"
+		"fnclex\n\t"
+		"fstpt 0x00(%0)\n\t"
+		"fstpt 0x10(%0)\n\t"
+		"fstpt 0x20(%0)\n\t"
+		"fstpt 0x30(%0)\n\t"
+		"fstpt 0x40(%0)\n\t"
+		"fstpt 0x50(%0)\n\t"
+		"fstpt 0x60(%0)\n\t"
+		"fstpt 0x70(%0)\n\t"
+		:
+		: "a"(out->st), "m"(fsave), "m"(fxsave)
+		: "st", "memory"
+	);
+
+	FORKEE_ASSERT(fsave.s87_cw == fxsave.fx_cw);
+	FORKEE_ASSERT(fsave.s87_sw == fxsave.fx_sw);
+
+	/* fsave contains full tw */
+	out->cw = fsave.s87_cw;
+	out->sw = fsave.s87_sw;
+	out->tw = fsave.s87_tw;
+	out->tw_abridged = fxsave.fx_tw;
+	out->opcode = fxsave.fx_opcode;
+	out->ip = fxsave.fx_ip;
+	out->dp = fxsave.fx_dp;
+}
+
+/* used as single-precision float */
+uint32_t x86_test_zero = 0;
+
+static __inline void set_fpu_regs(const struct x86_test_fpu_registers *data)
+{
+	__CTASSERT(sizeof(data->st[0]) == 16);
+
+	__asm__ __volatile__(
+		"finit\n\t"
+		"fldcw %1\n\t"
+		/* load on stack in reverse order to make it easier to read */
+		"fldt 0x70(%0)\n\t"
+		"fldt 0x60(%0)\n\t"
+		"fldt 0x50(%0)\n\t"
+		"fldt 0x40(%0)\n\t"
+		"fldt 0x30(%0)\n\t"
+		"fldt 0x20(%0)\n\t"
+		"fldt 0x10(%0)\n\t"
+		"fldt 0x00(%0)\n\t"
+		/* free st7 */
+		"ffree %%st(7)\n\t"
+		/* this should trigger a divide-by-zero */
+		"fdivs (%2)\n\t"
+		"int3\n\t"
+		:
+		: "a"(&data->st), "m"(data->cw), "b"(&x86_test_zero)
+		: "st"
+	);
+}
+
 __attribute__((target("mmx")))
 static __inline void get_mm_regs(union x86_test_register out[])
 {
@@ -2712,6 +2801,54 @@ x86_register_test(enum x86_test_regset r
 		   0x262524232221201F, 0x2E2D2C2B2A292827, }},
 	};
 
+	const struct x86_test_fpu_registers expected_fpu = {
+		.st = {
+			{0x8000000000000000, 0x4000}, /* +2.0 */
+			{0x3f00000000000000, 0x0000}, /* 1.654785e-4932 */
+			{0x0000000000000000, 0x0000}, /* +0 */
+			{0x0000000000000000, 0x8000}, /* -0 */
+			{0x8000000000000000, 0x7fff}, /* +inf */
+			{0x8000000000000000, 0xffff}, /* -inf */
+			{0xc000000000000000, 0xffff}, /* nan */
+			/* st(7) will be freed to test tag word better */
+			{0x0000000000000000, 0x0000}, /* +0 */
+		},
+		/* 0000 0011 0111 1011
+		 *             PU OZDI -- unmask divide-by-zero exc.
+		 *           RR --------- reserved
+		 *        PC ------------ 64-bit precision
+		 *      RC -------------- round to nearest
+		 *    I ----------------- allow interrupts (unused)
+		 */
+		.cw = 0x037b,
+		/* 1000 0000 1000 0100
+		 *            SPU OZDI -- divide-by-zero exception
+		 *           I ---------- interrupt (exception handling)
+		 *  C    CCC ------------ condition codes
+		 *   TO P --------------- top register is 0
+		 * B -------------------- FPU is busy
+		 */
+		.sw = 0x8084,
+		/* 1110 1010 0101 1000
+		 * R7R6 R5R4 R3R2 R1R0
+		 *                  nz -- non-zero (+2.0)
+		 *                sp ---- special (denormal)
+		 *           zrzr ------- zeroes
+		 *   sp spsp ------------ specials (NaN + infinities)
+		 * em ------------------- empty register
+		 */
+		.tw = 0xea58,
+		/* 0111 1111 -- registers 0 to 6 are used */
+		.tw_abridged = 0x7f,
+		/* FDIV */
+		.opcode = 0x0033,
+		/* random bits for IP/DP write test
+		 * keep it below 48 bits since it can be truncated
+		 */
+		.ip = {.fa_64 = 0x00000a9876543210},
+		.dp = {.fa_64 = 0x0000056789abcdef},
+	};
+
 	bool need_32 = false, need_64 = false, need_cpuid = false;
 
 	switch (regs) {
@@ -2723,6 +2860,8 @@ x86_register_test(enum x86_test_regset r
 	case GPREGS_64_R8:
 		need_64 = true;
 		break;
+	case FPREGS_FPU:
+		break;
 	case FPREGS_MM:
 	case FPREGS_XMM:
 	case FPREGS_YMM:
@@ -2768,6 +2907,7 @@ x86_register_test(enum x86_test_regset r
 		case GPREGS_32_EBP_ESP:
 		case GPREGS_64:
 		case GPREGS_64_R8:
+		case FPREGS_FPU:
 			__unreachable();
 		}
 	}
@@ -2776,6 +2916,7 @@ x86_register_test(enum x86_test_regset r
 	SYSCALL_REQUIRE((child = fork()) != -1);
 	if (child == 0) {
 		union x86_test_register vals[16] __aligned(32);
+		struct x86_test_fpu_registers vals_fpu;
 
 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
@@ -2797,6 +2938,9 @@ x86_register_test(enum x86_test_regset r
 			case GPREGS_64_R8:
 				set_gp64_r8_regs(expected);
 				break;
+			case FPREGS_FPU:
+				set_fpu_regs(&expected_fpu);
+				break;
 			case FPREGS_MM:
 				set_mm_regs(expected);
 				break;
@@ -2822,6 +2966,9 @@ x86_register_test(enum x86_test_regset r
 			case GPREGS_64_R8:
 				get_gp64_r8_regs(vals);
 				break;
+			case FPREGS_FPU:
+				get_fpu_regs(&vals_fpu);
+				break;
 			case FPREGS_MM:
 				get_mm_regs(vals);
 				break;
@@ -2871,6 +3018,47 @@ x86_register_test(enum x86_test_regset r
 				FORKEE_ASSERT(!memcmp(&vals[7].u64,
 				    &expected[7].u64, sizeof(vals->u64)));
 				break;
+			case FPREGS_FPU:
+				FORKEE_ASSERT(vals_fpu.cw == expected_fpu.cw);
+				FORKEE_ASSERT(vals_fpu.sw == expected_fpu.sw);
+				FORKEE_ASSERT(vals_fpu.tw == expected_fpu.tw);
+				FORKEE_ASSERT(vals_fpu.tw_abridged
+				    == expected_fpu.tw_abridged);
+				FORKEE_ASSERT(vals_fpu.ip.fa_64
+				    == expected_fpu.ip.fa_64);
+				FORKEE_ASSERT(vals_fpu.dp.fa_64
+				    == expected_fpu.dp.fa_64);
+
+				FORKEE_ASSERT(vals_fpu.st[0].sign_exp
+				    == expected_fpu.st[0].sign_exp);
+				FORKEE_ASSERT(vals_fpu.st[0].mantissa
+				    == expected_fpu.st[0].mantissa);
+				FORKEE_ASSERT(vals_fpu.st[1].sign_exp
+				    == expected_fpu.st[1].sign_exp);
+				FORKEE_ASSERT(vals_fpu.st[1].mantissa
+				    == expected_fpu.st[1].mantissa);
+				FORKEE_ASSERT(vals_fpu.st[2].sign_exp
+				    == expected_fpu.st[2].sign_exp);
+				FORKEE_ASSERT(vals_fpu.st[2].mantissa
+				    == expected_fpu.st[2].mantissa);
+				FORKEE_ASSERT(vals_fpu.st[3].sign_exp
+				    == expected_fpu.st[3].sign_exp);
+				FORKEE_ASSERT(vals_fpu.st[3].mantissa
+				    == expected_fpu.st[3].mantissa);
+				FORKEE_ASSERT(vals_fpu.st[4].sign_exp
+				    == expected_fpu.st[4].sign_exp);
+				FORKEE_ASSERT(vals_fpu.st[4].mantissa
+				    == expected_fpu.st[4].mantissa);
+				FORKEE_ASSERT(vals_fpu.st[5].sign_exp
+				    == expected_fpu.st[5].sign_exp);
+				FORKEE_ASSERT(vals_fpu.st[5].mantissa
+				    == expected_fpu.st[5].mantissa);
+				FORKEE_ASSERT(vals_fpu.st[6].sign_exp
+				    == expected_fpu.st[6].sign_exp);
+				FORKEE_ASSERT(vals_fpu.st[6].mantissa
+				    == expected_fpu.st[6].mantissa);
+				/* st(7) is left empty == undefined */
+				break;
 			case FPREGS_XMM:
 				FORKEE_ASSERT(!memcmp(&vals[0].xmm,
 				    &expected[0].xmm, sizeof(vals->xmm)));
@@ -2959,6 +3147,7 @@ x86_register_test(enum x86_test_regset r
 
 	if (regset == TEST_XSTATE) {
 		switch (regs) {
+		case FPREGS_FPU:
 		case FPREGS_MM:
 			xst_flags |= XCR0_X87;
 			break;
@@ -2980,16 +3169,19 @@ x86_register_test(enum x86_test_regset r
 	switch (regmode) {
 	case TEST_GETREGS:
 	case TEST_SETREGS:
-		switch (regset) {
-		case TEST_GPREGS:
-			ATF_REQUIRE(regs < FPREGS_MM);
+		if (regset == TEST_GPREGS || regs == FPREGS_FPU) {
 			DPRINTF("Call GETREGS for the child process\n");
 			SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0)
 			    != -1);
+		}
+
+		switch (regset) {
+		case TEST_GPREGS:
+			/* already handled above */
 			break;
 		case TEST_XMMREGS:
 #if defined(__i386__)
-			ATF_REQUIRE(regs >= FPREGS_MM && regs < FPREGS_YMM);
+			ATF_REQUIRE(regs >= FPREGS_FPU && regs < FPREGS_YMM);
 			DPRINTF("Call GETXMMREGS for the child process\n");
 			SYSCALL_REQUIRE(ptrace(PT_GETXMMREGS, child, &xmm, 0)
 			    != -1);
@@ -3000,17 +3192,17 @@ x86_register_test(enum x86_test_regset r
 #endif
 		case TEST_FPREGS:
 #if defined(__x86_64__)
-			ATF_REQUIRE(regs >= FPREGS_MM && regs < FPREGS_YMM);
+			ATF_REQUIRE(regs >= FPREGS_FPU && regs < FPREGS_YMM);
 			fxs = &fpr.fxstate;
 #else
-			ATF_REQUIRE(regs >= FPREGS_MM && regs < FPREGS_XMM);
+			ATF_REQUIRE(regs >= FPREGS_FPU && regs < FPREGS_XMM);
 #endif
 			DPRINTF("Call GETFPREGS for the child process\n");
 			SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0)
 			    != -1);
 			break;
 		case TEST_XSTATE:
-			ATF_REQUIRE(regs >= FPREGS_MM);
+			ATF_REQUIRE(regs >= FPREGS_FPU);
 			iov.iov_base = &xst;
 			iov.iov_len = sizeof(xst);
 
@@ -3045,17 +3237,20 @@ x86_register_test(enum x86_test_regset r
 		SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path,
 		    strlen(core_path)) != -1);
 
-		switch (regset) {
-		case TEST_GPREGS:
-			ATF_REQUIRE(regs < FPREGS_MM);
+		if (regset == TEST_GPREGS || regs == FPREGS_FPU) {
 			DPRINTF("Parse core file for PT_GETREGS\n");
 			ATF_REQUIRE_EQ(core_find_note(core_path,
 			    "NetBSD-CORE@*", PT_GETREGS, &gpr, sizeof(gpr)),
 			    sizeof(gpr));
+		}
+
+		switch (regset) {
+		case TEST_GPREGS:
+			/* handled above */
 			break;
 		case TEST_XMMREGS:
 #if defined(__i386__)
-			ATF_REQUIRE(regs >= FPREGS_MM && regs < FPREGS_YMM);
+			ATF_REQUIRE(regs >= FPREGS_FPU && regs < FPREGS_YMM);
 			unlink(core_path);
 			atf_tc_skip("XMMREGS not supported in core dumps");
 			break;
@@ -3064,10 +3259,10 @@ x86_register_test(enum x86_test_regset r
 #endif
 		case TEST_FPREGS:
 #if defined(__x86_64__)
-			ATF_REQUIRE(regs >= FPREGS_MM && regs < FPREGS_YMM);
+			ATF_REQUIRE(regs >= FPREGS_FPU && regs < FPREGS_YMM);
 			fxs = &fpr.fxstate;
 #else
-			ATF_REQUIRE(regs >= FPREGS_MM && regs < FPREGS_XMM);
+			ATF_REQUIRE(regs >= FPREGS_FPU && regs < FPREGS_XMM);
 #endif
 			DPRINTF("Parse core file for PT_GETFPREGS\n");
 			ATF_REQUIRE_EQ(core_find_note(core_path,
@@ -3075,7 +3270,7 @@ x86_register_test(enum x86_test_regset r
 			    sizeof(fpr));
 			break;
 		case TEST_XSTATE:
-			ATF_REQUIRE(regs >= FPREGS_MM);
+			ATF_REQUIRE(regs >= FPREGS_FPU);
 			DPRINTF("Parse core file for PT_GETXSTATE\n");
 			ATF_REQUIRE_EQ(core_find_note(core_path,
 			    "NetBSD-CORE@*", PT_GETXSTATE, &xst, sizeof(xst)),
@@ -3089,8 +3284,14 @@ x86_register_test(enum x86_test_regset r
 	}
 
 #if defined(__x86_64__)
+#define ST_EXP(n) fxs->fx_87_ac[n].r.f87_exp_sign
 #define ST_MAN(n) fxs->fx_87_ac[n].r.f87_mantissa
 #else
+#define ST_EXP(n) *(							\
+    regset == TEST_FPREGS						\
+    ? &fpr.fstate.s87_ac[n].f87_exp_sign				\
+    : &fxs->fx_87_ac[n].r.f87_exp_sign					\
+    )
 #define ST_MAN(n) *(							\
     regset == TEST_FPREGS						\
     ? &fpr.fstate.s87_ac[n].f87_mantissa				\
@@ -3158,6 +3359,68 @@ x86_register_test(enum x86_test_regset r
 			    expected[7].u64);
 #endif
 			break;
+		case FPREGS_FPU:
+#if defined(__i386__)
+			if (regset == TEST_FPREGS) {
+				/* GETFPREGS on i386 */
+				ATF_CHECK_EQ(fpr.fstate.s87_cw,
+				    expected_fpu.cw);
+				ATF_CHECK_EQ(fpr.fstate.s87_sw,
+				    expected_fpu.sw);
+#if 0 /* TODO: translation from FXSAVE is broken */
+				ATF_CHECK_EQ(fpr.fstate.s87_tw,
+				    expected_fpu.tw);
+#endif
+				ATF_CHECK_EQ(fpr.fstate.s87_opcode,
+				    expected_fpu.opcode);
+				ATF_CHECK_EQ(fpr.fstate.s87_ip.fa_32.fa_off,
+				    (uint32_t)gpr.r_eip - 3);
+				ATF_CHECK_EQ(fpr.fstate.s87_dp.fa_32.fa_off,
+				    (uint32_t)&x86_test_zero);
+				/* note: fa_seg is missing on newer CPUs */
+			} else
+#endif
+			{
+				/* amd64 or GETXSTATE on i386 */
+				ATF_CHECK_EQ(fxs->fx_cw, expected_fpu.cw);
+				ATF_CHECK_EQ(fxs->fx_sw, expected_fpu.sw);
+				ATF_CHECK_EQ(fxs->fx_tw,
+				    expected_fpu.tw_abridged);
+				ATF_CHECK_EQ(fxs->fx_opcode,
+				    expected_fpu.opcode);
+#if defined(__x86_64__)
+#if 0 /* TODO: kernel needs patching to call *XSAVE64 */
+				ATF_CHECK_EQ(fxs->fx_ip.fa_64,
+				    ((uint64_t)gpr.regs[_REG_RIP]) - 3);
+				ATF_CHECK_EQ(fxs->fx_dp.fa_64,
+				    (uint64_t)&x86_test_zero);
+#endif
+#else
+				ATF_CHECK_EQ(fxs->fx_ip.fa_32.fa_off,
+				    (uint32_t)gpr.r_eip - 3);
+				ATF_CHECK_EQ(fxs->fx_dp.fa_32.fa_off,
+				    (uint32_t)&x86_test_zero);
+				/* note: fa_seg is missing on newer CPUs */
+#endif
+			}
+
+			ATF_CHECK_EQ(ST_EXP(0), expected_fpu.st[0].sign_exp);
+			ATF_CHECK_EQ(ST_MAN(0), expected_fpu.st[0].mantissa);
+			ATF_CHECK_EQ(ST_EXP(1), expected_fpu.st[1].sign_exp);
+			ATF_CHECK_EQ(ST_MAN(1), expected_fpu.st[1].mantissa);
+			ATF_CHECK_EQ(ST_EXP(2), expected_fpu.st[2].sign_exp);
+			ATF_CHECK_EQ(ST_MAN(2), expected_fpu.st[2].mantissa);
+			ATF_CHECK_EQ(ST_EXP(3), expected_fpu.st[3].sign_exp);
+			ATF_CHECK_EQ(ST_MAN(3), expected_fpu.st[3].mantissa);
+			ATF_CHECK_EQ(ST_EXP(4), expected_fpu.st[4].sign_exp);
+			ATF_CHECK_EQ(ST_MAN(4), expected_fpu.st[4].mantissa);
+			ATF_CHECK_EQ(ST_EXP(5), expected_fpu.st[5].sign_exp);
+			ATF_CHECK_EQ(ST_MAN(5), expected_fpu.st[5].mantissa);
+			ATF_CHECK_EQ(ST_EXP(6), expected_fpu.st[6].sign_exp);
+			ATF_CHECK_EQ(ST_MAN(6), expected_fpu.st[6].mantissa);
+			ATF_CHECK_EQ(ST_EXP(7), expected_fpu.st[7].sign_exp);
+			ATF_CHECK_EQ(ST_MAN(7), expected_fpu.st[7].mantissa);
+			break;
 		case FPREGS_MM:
 			ATF_CHECK_EQ(ST_MAN(0), expected[0].u64);
 			ATF_CHECK_EQ(ST_MAN(1), expected[1].u64);
@@ -3284,6 +3547,47 @@ x86_register_test(enum x86_test_regset r
 			gpr.regs[_REG_R15] = expected[7].u64;
 #endif
 			break;
+		case FPREGS_FPU:
+#if defined(__i386__)
+			if (regset == TEST_FPREGS) {
+				/* SETFPREGS on i386 */
+				fpr.fstate.s87_cw = expected_fpu.cw;
+				fpr.fstate.s87_sw = expected_fpu.sw;
+//#if 0 /* TODO: translation from FXSAVE is broken */
+				fpr.fstate.s87_tw = expected_fpu.tw;
+//#endif
+				fpr.fstate.s87_opcode = expected_fpu.opcode;
+				fpr.fstate.s87_ip = expected_fpu.ip;
+				fpr.fstate.s87_dp = expected_fpu.dp;
+			} else
+#endif /*defined(__i386__)*/
+			{
+				/* amd64 or SETXSTATE on i386 */
+				fxs->fx_cw = expected_fpu.cw;
+				fxs->fx_sw = expected_fpu.sw;
+				fxs->fx_tw = expected_fpu.tw_abridged;
+				fxs->fx_opcode = expected_fpu.opcode;
+				fxs->fx_ip = expected_fpu.ip;
+				fxs->fx_dp = expected_fpu.dp;
+			}
+
+			ST_EXP(0) = expected_fpu.st[0].sign_exp;
+			ST_MAN(0) = expected_fpu.st[0].mantissa;
+			ST_EXP(1) = expected_fpu.st[1].sign_exp;
+			ST_MAN(1) = expected_fpu.st[1].mantissa;
+			ST_EXP(2) = expected_fpu.st[2].sign_exp;
+			ST_MAN(2) = expected_fpu.st[2].mantissa;
+			ST_EXP(3) = expected_fpu.st[3].sign_exp;
+			ST_MAN(3) = expected_fpu.st[3].mantissa;
+			ST_EXP(4) = expected_fpu.st[4].sign_exp;
+			ST_MAN(4) = expected_fpu.st[4].mantissa;
+			ST_EXP(5) = expected_fpu.st[5].sign_exp;
+			ST_MAN(5) = expected_fpu.st[5].mantissa;
+			ST_EXP(6) = expected_fpu.st[6].sign_exp;
+			ST_MAN(6) = expected_fpu.st[6].mantissa;
+			ST_EXP(7) = expected_fpu.st[7].sign_exp;
+			ST_MAN(7) = expected_fpu.st[7].mantissa;
+			break;
 		case FPREGS_MM:
 			ST_MAN(0) = expected[0].u64;
 			ST_MAN(1) = expected[1].u64;
@@ -3397,6 +3701,7 @@ x86_register_test(enum x86_test_regset r
 		break;
 	}
 
+#undef ST_EXP
 #undef ST_MAN
 
 	DPRINTF("Before resuming the child process where it left off and "
@@ -3457,6 +3762,12 @@ X86_REGISTER_TEST(x86_gpregs64_r8_write,
 X86_REGISTER_TEST(x86_gpregs64_r8_core, TEST_GPREGS, GPREGS_64_R8,
     TEST_COREDUMP, "Test reading r8..r15 registers from core dump.");
 
+X86_REGISTER_TEST(x86_fpregs_fpu_read, TEST_FPREGS, FPREGS_FPU, TEST_GETREGS,
+    "Test reading base FPU registers from debugged program via PT_GETFPREGS.");
+X86_REGISTER_TEST(x86_fpregs_fpu_write, TEST_FPREGS, FPREGS_FPU, TEST_SETREGS,
+    "Test writing base FPU registers into debugged program via PT_SETFPREGS.");
+X86_REGISTER_TEST(x86_fpregs_fpu_core, TEST_FPREGS, FPREGS_FPU, TEST_COREDUMP,
+    "Test reading base FPU registers from coredump.");
 X86_REGISTER_TEST(x86_fpregs_mm_read, TEST_FPREGS, FPREGS_MM, TEST_GETREGS,
     "Test reading mm0..mm7 registers from debugged program "
     "via PT_GETFPREGS.");
@@ -3474,6 +3785,12 @@ X86_REGISTER_TEST(x86_fpregs_xmm_write, 
 X86_REGISTER_TEST(x86_fpregs_xmm_core, TEST_XMMREGS, FPREGS_XMM, TEST_COREDUMP,
     "Test reading xmm0..xmm15 (..xmm7 on i386) from coredump.");
 
+X86_REGISTER_TEST(x86_xstate_fpu_read, TEST_XSTATE, FPREGS_FPU, TEST_GETREGS,
+    "Test reading base FPU registers from debugged program via PT_GETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_fpu_write, TEST_XSTATE, FPREGS_FPU, TEST_SETREGS,
+    "Test writing base FPU registers into debugged program via PT_SETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_fpu_core, TEST_XSTATE, FPREGS_FPU, TEST_COREDUMP,
+    "Test reading base FPU registers from core dump via XSTATE note.");
 X86_REGISTER_TEST(x86_xstate_mm_read, TEST_XSTATE, FPREGS_MM, TEST_GETREGS,
     "Test reading mm0..mm7 registers from debugged program "
     "via PT_GETXSTATE.");
@@ -3664,12 +3981,18 @@ thread_concurrent_handle_sigtrap(pid_t c
 	ATF_TP_ADD_TC(tp, x86_gpregs64_r8_read); \
 	ATF_TP_ADD_TC(tp, x86_gpregs64_r8_write); \
 	ATF_TP_ADD_TC(tp, x86_gpregs64_r8_core); \
+	ATF_TP_ADD_TC(tp, x86_fpregs_fpu_read); \
+	ATF_TP_ADD_TC(tp, x86_fpregs_fpu_write); \
+	ATF_TP_ADD_TC(tp, x86_fpregs_fpu_core); \
 	ATF_TP_ADD_TC(tp, x86_fpregs_mm_read); \
 	ATF_TP_ADD_TC(tp, x86_fpregs_mm_write); \
 	ATF_TP_ADD_TC(tp, x86_fpregs_mm_core); \
 	ATF_TP_ADD_TC(tp, x86_fpregs_xmm_read); \
 	ATF_TP_ADD_TC(tp, x86_fpregs_xmm_write); \
 	ATF_TP_ADD_TC(tp, x86_fpregs_xmm_core); \
+	ATF_TP_ADD_TC(tp, x86_xstate_fpu_read); \
+	ATF_TP_ADD_TC(tp, x86_xstate_fpu_write); \
+	ATF_TP_ADD_TC(tp, x86_xstate_fpu_core); \
 	ATF_TP_ADD_TC(tp, x86_xstate_mm_read); \
 	ATF_TP_ADD_TC(tp, x86_xstate_mm_write); \
 	ATF_TP_ADD_TC(tp, x86_xstate_mm_core); \

Reply via email to