tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[PATCH 3/4] Combine x86 register tests into unified test function
Reduce the code duplication and improve maintainability of x86 register
tests by combining all of them to a single base function.
---
tests/lib/libc/sys/t_ptrace_amd64_wait.h | 406 +---
tests/lib/libc/sys/t_ptrace_i386_wait.h | 335 +--
tests/lib/libc/sys/t_ptrace_x86_wait.h | 2417 ++++++++++------------
3 files changed, 1103 insertions(+), 2055 deletions(-)
diff --git a/tests/lib/libc/sys/t_ptrace_amd64_wait.h b/tests/lib/libc/sys/t_ptrace_amd64_wait.h
index 1ea17ea1ec1a..0f410f3600d0 100644
--- a/tests/lib/libc/sys/t_ptrace_amd64_wait.h
+++ b/tests/lib/libc/sys/t_ptrace_amd64_wait.h
@@ -111,415 +111,11 @@ ATF_TC_BODY(x86_64_regs1, tc)
TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
}
-ATF_TC(x86_64_regs_gp_read);
-ATF_TC_HEAD(x86_64_regs_gp_read, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set general-purpose reg values from debugged program and read "
- "them via PT_GETREGS, comparing values against expected.");
-}
-
-ATF_TC_BODY(x86_64_regs_gp_read, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct reg gpr;
-
- const uint64_t rax = 0x0001020304050607;
- const uint64_t rbx = 0x1011121314151617;
- const uint64_t rcx = 0x2021222324252627;
- const uint64_t rdx = 0x3031323334353637;
- const uint64_t rsi = 0x4041424344454647;
- const uint64_t rdi = 0x5051525354555657;
- const uint64_t rsp = 0x6061626364656667;
- const uint64_t rbp = 0x7071727374757677;
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
-
- __asm__ __volatile__(
- /* rbp & rbp are a bit tricky, we must not clobber them */
- "movq %%rsp, %%r8\n\t"
- "movq %%rbp, %%r9\n\t"
- "movq %6, %%rsp\n\t"
- "movq %7, %%rbp\n\t"
- "\n\t"
- "int3\n\t"
- "\n\t"
- "movq %%r8, %%rsp\n\t"
- "movq %%r9, %%rbp\n\t"
- :
- : "a"(rax), "b"(rbx), "c"(rcx), "d"(rdx), "S"(rsi), "D"(rdi),
- "i"(rsp), "i"(rbp)
- : "%r8", "%r9"
- );
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- DPRINTF("Call GETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RAX], rax);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBX], rbx);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RCX], rcx);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDX], rdx);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSI], rsi);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDI], rdi);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSP], rsp);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBP], rbp);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_64_regs_gp_write);
-ATF_TC_HEAD(x86_64_regs_gp_write, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set general-purpose reg values into a debugged program via "
- "PT_SETREGS and compare the result against expected.");
-}
-
-ATF_TC_BODY(x86_64_regs_gp_write, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct reg gpr;
-
- const uint64_t rax = 0x0001020304050607;
- const uint64_t rbx = 0x1011121314151617;
- const uint64_t rcx = 0x2021222324252627;
- const uint64_t rdx = 0x3031323334353637;
- const uint64_t rsi = 0x4041424344454647;
- const uint64_t rdi = 0x5051525354555657;
- const uint64_t rsp = 0x6061626364656667;
- const uint64_t rbp = 0x7071727374757677;
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
- uint64_t v_rax, v_rbx, v_rcx, v_rdx, v_rsi, v_rdi, v_rsp, v_rbp;
-
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
-
- __asm__ __volatile__(
- /* save rsp & rbp */
- "movq %%rsp, %4\n\t"
- "movq %%rbp, %5\n\t"
- "\n\t"
- /* fill registers with clobber pattern */
- "movq %8, %%rax\n\t"
- "movq %8, %%rbx\n\t"
- "movq %8, %%rcx\n\t"
- "movq %8, %%rdx\n\t"
- "movq %8, %%rsp\n\t"
- "movq %8, %%rbp\n\t"
- "movq %8, %%rsi\n\t"
- "movq %8, %%rdi\n\t"
- "\n\t"
- "int3\n\t"
- "\n\t"
- /* swap saved & current rsp & rbp */
- "xchgq %%rsp, %4\n\t"
- "xchgq %%rbp, %5\n\t"
- : "=a"(v_rax), "=b"(v_rbx), "=c"(v_rcx), "=d"(v_rdx), "=r"(v_rsp),
- "=r"(v_rbp), "=S"(v_rsi), "=D"(v_rdi)
- : "g"(fill)
- :
- );
-
- DPRINTF("Before comparing results\n");
- FORKEE_ASSERT_EQ(v_rax, rax);
- FORKEE_ASSERT_EQ(v_rbx, rbx);
- FORKEE_ASSERT_EQ(v_rcx, rcx);
- FORKEE_ASSERT_EQ(v_rdx, rdx);
- FORKEE_ASSERT_EQ(v_rsi, rsi);
- FORKEE_ASSERT_EQ(v_rdi, rdi);
- FORKEE_ASSERT_EQ(v_rsp, rsp);
- FORKEE_ASSERT_EQ(v_rbp, rbp);
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- DPRINTF("Call GETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
- gpr.regs[_REG_RAX] = rax;
- gpr.regs[_REG_RBX] = rbx;
- gpr.regs[_REG_RCX] = rcx;
- gpr.regs[_REG_RDX] = rdx;
- gpr.regs[_REG_RSI] = rsi;
- gpr.regs[_REG_RDI] = rdi;
- gpr.regs[_REG_RSP] = rsp;
- gpr.regs[_REG_RBP] = rbp;
-
- DPRINTF("Call SETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_64_regs_r8_read);
-ATF_TC_HEAD(x86_64_regs_r8_read, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set r8..r15 reg values from debugged program and read "
- "them via PT_GETREGS, comparing values against expected.");
-}
-
-ATF_TC_BODY(x86_64_regs_r8_read, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct reg gpr;
-
- const uint64_t r8[] = {
- 0x0001020304050607,
- 0x1011121314151617,
- 0x2021222324252627,
- 0x3031323334353637,
- 0x4041424344454647,
- 0x5051525354555657,
- 0x6061626364656667,
- 0x7071727374757677,
- };
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
-
- __asm__ __volatile__(
- "movq 0x00(%%rbx), %%r8\n\t"
- "movq 0x08(%%rbx), %%r9\n\t"
- "movq 0x10(%%rbx), %%r10\n\t"
- "movq 0x18(%%rbx), %%r11\n\t"
- "movq 0x20(%%rbx), %%r12\n\t"
- "movq 0x28(%%rbx), %%r13\n\t"
- "movq 0x30(%%rbx), %%r14\n\t"
- "movq 0x38(%%rbx), %%r15\n\t"
- "int3\n\t"
- :
- : "b"(r8)
- : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
- );
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- DPRINTF("Call GETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R8], r8[0]);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R9], r8[1]);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R10], r8[2]);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R11], r8[3]);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R12], r8[4]);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R13], r8[5]);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R14], r8[6]);
- ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R15], r8[7]);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_64_regs_r8_write);
-ATF_TC_HEAD(x86_64_regs_r8_write, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set r8..r15 reg values into a debugged program via "
- "PT_SETREGS and compare the result against expected.");
-}
-
-ATF_TC_BODY(x86_64_regs_r8_write, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct reg gpr;
-
- const uint64_t r8[] = {
- 0x0001020304050607,
- 0x1011121314151617,
- 0x2021222324252627,
- 0x3031323334353637,
- 0x4041424344454647,
- 0x5051525354555657,
- 0x6061626364656667,
- 0x7071727374757677,
- };
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
- uint64_t v_r8[8];
-
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
-
- __asm__ __volatile__(
- /* fill registers with clobber pattern */
- "movq %1, %%r8\n\t"
- "movq %1, %%r9\n\t"
- "movq %1, %%r10\n\t"
- "movq %1, %%r11\n\t"
- "movq %1, %%r12\n\t"
- "movq %1, %%r13\n\t"
- "movq %1, %%r14\n\t"
- "movq %1, %%r15\n\t"
- "\n\t"
- "int3\n\t"
- "\n\t"
- "movq %%r8, 0x00(%0)\n\t"
- "movq %%r9, 0x08(%0)\n\t"
- "movq %%r10, 0x10(%0)\n\t"
- "movq %%r11, 0x18(%0)\n\t"
- "movq %%r12, 0x20(%0)\n\t"
- "movq %%r13, 0x28(%0)\n\t"
- "movq %%r14, 0x30(%0)\n\t"
- "movq %%r15, 0x38(%0)\n\t"
- :
- : "a"(v_r8), "m"(fill)
- : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
- );
-
- DPRINTF("Before comparing results\n");
- FORKEE_ASSERT_EQ(v_r8[0], r8[0]);
- FORKEE_ASSERT_EQ(v_r8[1], r8[1]);
- FORKEE_ASSERT_EQ(v_r8[2], r8[2]);
- FORKEE_ASSERT_EQ(v_r8[3], r8[3]);
- FORKEE_ASSERT_EQ(v_r8[4], r8[4]);
- FORKEE_ASSERT_EQ(v_r8[5], r8[5]);
- FORKEE_ASSERT_EQ(v_r8[6], r8[6]);
- FORKEE_ASSERT_EQ(v_r8[7], r8[7]);
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- DPRINTF("Call GETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
- gpr.regs[_REG_R8] = r8[0];
- gpr.regs[_REG_R9] = r8[1];
- gpr.regs[_REG_R10] = r8[2];
- gpr.regs[_REG_R11] = r8[3];
- gpr.regs[_REG_R12] = r8[4];
- gpr.regs[_REG_R13] = r8[5];
- gpr.regs[_REG_R14] = r8[6];
- gpr.regs[_REG_R15] = r8[7];
-
- DPRINTF("Call SETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
/// ----------------------------------------------------------------------------
#define ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64() \
- ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs1); \
- ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_gp_read); \
- ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_gp_write); \
- ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_r8_read); \
- ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_r8_write);
+ ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs1);
#else
#define ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64()
#endif
diff --git a/tests/lib/libc/sys/t_ptrace_i386_wait.h b/tests/lib/libc/sys/t_ptrace_i386_wait.h
index 7250f4eb66db..8db74261bb35 100644
--- a/tests/lib/libc/sys/t_ptrace_i386_wait.h
+++ b/tests/lib/libc/sys/t_ptrace_i386_wait.h
@@ -101,341 +101,8 @@ ATF_TC_BODY(i386_regs1, tc)
TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
}
-ATF_TC(i386_regs_gp_read);
-ATF_TC_HEAD(i386_regs_gp_read, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set general-purpose reg values from debugged program and read "
- "them via PT_GETREGS, comparing values against expected.");
-}
-
-ATF_TC_BODY(i386_regs_gp_read, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct reg gpr;
-
- const uint32_t eax = 0x00010203;
- const uint32_t ebx = 0x10111213;
- const uint32_t ecx = 0x20212223;
- const uint32_t edx = 0x30313233;
- const uint32_t esi = 0x40414243;
- const uint32_t edi = 0x50515253;
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
-
- __asm__ __volatile__(
- "int3\n\t"
- :
- : "a"(eax), "b"(ebx), "c"(ecx), "d"(edx), "S"(esi), "D"(edi)
- :
- );
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- DPRINTF("Call GETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
- ATF_CHECK_EQ((uint32_t)gpr.r_eax, eax);
- ATF_CHECK_EQ((uint32_t)gpr.r_ebx, ebx);
- ATF_CHECK_EQ((uint32_t)gpr.r_ecx, ecx);
- ATF_CHECK_EQ((uint32_t)gpr.r_edx, edx);
- ATF_CHECK_EQ((uint32_t)gpr.r_esi, esi);
- ATF_CHECK_EQ((uint32_t)gpr.r_edi, edi);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(i386_regs_gp_write);
-ATF_TC_HEAD(i386_regs_gp_write, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set general-purpose reg values into a debugged program via "
- "PT_SETREGS and compare the result against expected.");
-}
-
-ATF_TC_BODY(i386_regs_gp_write, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct reg gpr;
-
- const uint32_t eax = 0x00010203;
- const uint32_t ebx = 0x10111213;
- const uint32_t ecx = 0x20212223;
- const uint32_t edx = 0x30313233;
- const uint32_t esi = 0x40414243;
- const uint32_t edi = 0x50515253;
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- const uint64_t fill = 0x0F0F0F0F;
- uint32_t v_eax, v_ebx, v_ecx, v_edx, v_esi, v_edi;
-
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
-
- __asm__ __volatile__(
- /* fill registers with clobber pattern */
- "movl %6, %%eax\n\t"
- "movl %6, %%ebx\n\t"
- "movl %6, %%ecx\n\t"
- "movl %6, %%edx\n\t"
- "movl %6, %%esi\n\t"
- "movl %6, %%edi\n\t"
- "\n\t"
- "int3\n\t"
- : "=a"(v_eax), "=b"(v_ebx), "=c"(v_ecx), "=d"(v_edx), "=S"(v_esi),
- "=D"(v_edi)
- : "g"(fill)
- :
- );
-
- DPRINTF("Before comparing results\n");
- FORKEE_ASSERT_EQ(v_eax, eax);
- FORKEE_ASSERT_EQ(v_ebx, ebx);
- FORKEE_ASSERT_EQ(v_ecx, ecx);
- FORKEE_ASSERT_EQ(v_edx, edx);
- FORKEE_ASSERT_EQ(v_esi, esi);
- FORKEE_ASSERT_EQ(v_edi, edi);
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- DPRINTF("Call GETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
- gpr.r_eax = eax;
- gpr.r_ebx = ebx;
- gpr.r_ecx = ecx;
- gpr.r_edx = edx;
- gpr.r_esi = esi;
- gpr.r_edi = edi;
-
- DPRINTF("Call SETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(i386_regs_ebp_esp_read);
-ATF_TC_HEAD(i386_regs_ebp_esp_read, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set EBP & ESP reg values from debugged program and read "
- "them via PT_GETREGS, comparing values against expected.");
-}
-
-ATF_TC_BODY(i386_regs_ebp_esp_read, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct reg gpr;
-
- const uint32_t esp = 0x60616263;
- const uint32_t ebp = 0x70717273;
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
-
- __asm__ __volatile__(
- /* ebp & ebp are a bit tricky, we must not clobber them */
- "movl %%esp, %%eax\n\t"
- "movl %%ebp, %%ebx\n\t"
- "movl %0, %%esp\n\t"
- "movl %1, %%ebp\n\t"
- "\n\t"
- "int3\n\t"
- "\n\t"
- "movl %%eax, %%esp\n\t"
- "movl %%ebx, %%ebp\n\t"
- :
- : "ri"(esp), "ri"(ebp)
- : "%eax", "%ebx"
- );
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- DPRINTF("Call GETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
- ATF_CHECK_EQ((uint32_t)gpr.r_esp, esp);
- ATF_CHECK_EQ((uint32_t)gpr.r_ebp, ebp);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(i386_regs_ebp_esp_write);
-ATF_TC_HEAD(i386_regs_ebp_esp_write, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set EBP & ESP reg values into a debugged program via "
- "PT_SETREGS and compare the result against expected.");
-}
-
-ATF_TC_BODY(i386_regs_ebp_esp_write, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct reg gpr;
-
- const uint32_t esp = 0x60616263;
- const uint32_t ebp = 0x70717273;
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- const uint64_t fill = 0x0F0F0F0F;
- uint32_t v_esp, v_ebp;
-
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
-
- __asm__ __volatile__(
- /* save original ebp & esp using our output registers */
- "movl %%esp, %0\n\t"
- "movl %%ebp, %1\n\t"
- /* fill them with clobber pattern */
- "movl %2, %%esp\n\t"
- "movl %2, %%ebp\n\t"
- "\n\t"
- "int3\n\t"
- "\n\t"
- /* restore ebp & esp, and save the result */
- "xchgl %%esp, %0\n\t"
- "xchgl %%ebp, %1\n\t"
- : "=r"(v_esp), "=r"(v_ebp)
- : "g"(fill)
- :
- );
-
- DPRINTF("Before comparing results\n");
- FORKEE_ASSERT_EQ(v_esp, esp);
- FORKEE_ASSERT_EQ(v_ebp, ebp);
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- DPRINTF("Call GETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
- gpr.r_esp = esp;
- gpr.r_ebp = ebp;
-
- DPRINTF("Call SETREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
#define ATF_TP_ADD_TCS_PTRACE_WAIT_I386() \
- ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs1); \
- ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_gp_read); \
- ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_gp_write); \
- ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_ebp_esp_read); \
- ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_ebp_esp_write);
+ ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs1);
#else
#define ATF_TP_ADD_TCS_PTRACE_WAIT_I386()
#endif
diff --git a/tests/lib/libc/sys/t_ptrace_x86_wait.h b/tests/lib/libc/sys/t_ptrace_x86_wait.h
index 6d177d4624e9..4572e3eb8b23 100644
--- a/tests/lib/libc/sys/t_ptrace_x86_wait.h
+++ b/tests/lib/libc/sys/t_ptrace_x86_wait.h
@@ -2189,1273 +2189,400 @@ ATF_TC_BODY(x86_cve_2018_8897, tc)
TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
}
-ATF_TC(x86_regs_mm_read);
-ATF_TC_HEAD(x86_regs_mm_read, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set MMX (mm0..mm7) reg values from debugged program and read "
- "them via PT_GETFPREGS, comparing values against expected.");
-}
+/// ----------------------------------------------------------------------------
-__attribute__((target("mmx")))
-static __inline void set_mm_regs(const uint64_t mm[])
+union x86_test_register {
+ struct {
+ uint64_t a, b, c, d;
+ } ymm;
+ struct {
+ uint64_t a, b;
+ } xmm;
+ uint64_t u64;
+ uint32_t u32;
+};
+
+enum x86_test_regset {
+ TEST_GPREGS,
+ TEST_FPREGS,
+ TEST_XMMREGS,
+ TEST_XSTATE
+};
+
+/* Please keep them grouped by acceptable x86_test_regset. */
+enum x86_test_registers {
+ /* TEST_GPREGS */
+ GPREGS_32,
+ GPREGS_32_EBP_ESP,
+ GPREGS_64,
+ GPREGS_64_R8,
+ /* TEST_FPREGS/TEST_XMMREGS */
+ FPREGS_MM,
+ FPREGS_XMM,
+ /* TEST_XSTATE */
+ FPREGS_YMM
+};
+
+enum x86_test_regmode {
+ TEST_GETREGS,
+ TEST_SETREGS
+};
+
+static __inline void get_gp32_regs(union x86_test_register out[])
{
+#if defined(__i386__)
+ const uint32_t fill = 0x0F0F0F0F;
+
__asm__ __volatile__(
- "movq 0x00(%0), %%mm0\n\t"
- "movq 0x08(%0), %%mm1\n\t"
- "movq 0x10(%0), %%mm2\n\t"
- "movq 0x18(%0), %%mm3\n\t"
- "movq 0x20(%0), %%mm4\n\t"
- "movq 0x28(%0), %%mm5\n\t"
- "movq 0x30(%0), %%mm6\n\t"
- "movq 0x38(%0), %%mm7\n\t"
+ /* fill registers with clobber pattern */
+ "movl %6, %%eax\n\t"
+ "movl %6, %%ebx\n\t"
+ "movl %6, %%ecx\n\t"
+ "movl %6, %%edx\n\t"
+ "movl %6, %%esi\n\t"
+ "movl %6, %%edi\n\t"
+ "\n\t"
"int3\n\t"
- :
- : "b"(mm)
- : "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
+ : "=a"(out[0].u32), "=b"(out[1].u32), "=c"(out[2].u32),
+ "=d"(out[3].u32), "=S"(out[4].u32), "=D"(out[5].u32)
+ : "g"(fill)
);
+#else
+ __unreachable();
+#endif
}
-ATF_TC_BODY(x86_regs_mm_read, tc)
+static __inline void set_gp32_regs(const union x86_test_register data[])
{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct fpreg fpr;
-
- const uint64_t mm[] = {
- 0x0001020304050607,
- 0x1011121314151617,
- 0x2021222324252627,
- 0x3031323334353637,
- 0x4041424344454647,
- 0x5051525354555657,
- 0x6061626364656667,
- 0x7071727374757677,
- };
-
- /* verify whether MMX is supported here */
- DPRINTF("Before invoking cpuid\n");
- {
- unsigned int eax, ebx, ecx, edx;
- if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
- atf_tc_skip("CPUID is not supported by the CPU");
-
- DPRINTF("cpuid: EDX = %08x\n", edx);
-
- if (!(edx & bit_MMX))
- atf_tc_skip("MMX is not supported by the CPU");
- }
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
- set_mm_regs(mm);
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- DPRINTF("Call GETFPREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
-
-#if defined(__x86_64__)
-#define MM_REG(n) fpr.fxstate.fx_87_ac[n].r.f87_mantissa
+#if defined(__i386__)
+ __asm__ __volatile__(
+ "int3\n\t"
+ :
+ : "a"(data[0].u32), "b"(data[1].u32), "c"(data[2].u32),
+ "d"(data[3].u32), "S"(data[4].u32), "D"(data[5].u32)
+ :
+ );
#else
-#define MM_REG(n) fpr.fstate.s87_ac[n].f87_mantissa
+ __unreachable();
#endif
-
- ATF_CHECK_EQ(MM_REG(0), mm[0]);
- ATF_CHECK_EQ(MM_REG(1), mm[1]);
- ATF_CHECK_EQ(MM_REG(2), mm[2]);
- ATF_CHECK_EQ(MM_REG(3), mm[3]);
- ATF_CHECK_EQ(MM_REG(4), mm[4]);
- ATF_CHECK_EQ(MM_REG(5), mm[5]);
- ATF_CHECK_EQ(MM_REG(6), mm[6]);
- ATF_CHECK_EQ(MM_REG(7), mm[7]);
-
-#undef MM_REG
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
}
-__attribute__((target("mmx")))
-static __inline void get_mm_regs(uint64_t v_mm[])
+static __inline void get_gp32_ebp_esp_regs(union x86_test_register out[])
{
- const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
+#if defined(__i386__)
+ const uint32_t fill = 0x0F0F0F0F;
__asm__ __volatile__(
- /* fill registers with clobber pattern */
- "movq %1, %%mm0\n\t"
- "movq %1, %%mm1\n\t"
- "movq %1, %%mm2\n\t"
- "movq %1, %%mm3\n\t"
- "movq %1, %%mm4\n\t"
- "movq %1, %%mm5\n\t"
- "movq %1, %%mm6\n\t"
- "movq %1, %%mm7\n\t"
+ /* save original ebp & esp using our output registers */
+ "movl %%esp, %0\n\t"
+ "movl %%ebp, %1\n\t"
+ /* fill them with clobber pattern */
+ "movl %2, %%esp\n\t"
+ "movl %2, %%ebp\n\t"
"\n\t"
"int3\n\t"
"\n\t"
- "movq %%mm0, 0x00(%0)\n\t"
- "movq %%mm1, 0x08(%0)\n\t"
- "movq %%mm2, 0x10(%0)\n\t"
- "movq %%mm3, 0x18(%0)\n\t"
- "movq %%mm4, 0x20(%0)\n\t"
- "movq %%mm5, 0x28(%0)\n\t"
- "movq %%mm6, 0x30(%0)\n\t"
- "movq %%mm7, 0x38(%0)\n\t"
+ /* restore ebp & esp, and save the result */
+ "xchgl %%esp, %0\n\t"
+ "xchgl %%ebp, %1\n\t"
+ : "=r"(out[0].u32), "=r"(out[1].u32)
+ : "g"(fill)
:
- : "a"(v_mm), "m"(fill)
- : "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
);
-}
-
-ATF_TC(x86_regs_mm_write);
-ATF_TC_HEAD(x86_regs_mm_write, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set mm0..mm7 reg values into a debugged program via "
- "PT_SETFPREGS and compare the result against expected.");
-}
-
-ATF_TC_BODY(x86_regs_mm_write, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct fpreg fpr;
-
- const uint64_t mm[] = {
- 0x0001020304050607,
- 0x1011121314151617,
- 0x2021222324252627,
- 0x3031323334353637,
- 0x4041424344454647,
- 0x5051525354555657,
- 0x6061626364656667,
- 0x7071727374757677,
- };
-
- /* verify whether MMX is supported here */
- DPRINTF("Before invoking cpuid\n");
- {
- unsigned int eax, ebx, ecx, edx;
- if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
- atf_tc_skip("CPUID is not supported by the CPU");
-
- DPRINTF("cpuid: EDX = %08x\n", edx);
-
- if (!(edx & bit_MMX))
- atf_tc_skip("MMX is not supported by the CPU");
- }
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- uint64_t v_mm[8];
-
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
- get_mm_regs(v_mm);
-
- DPRINTF("Before comparing results\n");
- FORKEE_ASSERT_EQ(v_mm[0], mm[0]);
- FORKEE_ASSERT_EQ(v_mm[1], mm[1]);
- FORKEE_ASSERT_EQ(v_mm[2], mm[2]);
- FORKEE_ASSERT_EQ(v_mm[3], mm[3]);
- FORKEE_ASSERT_EQ(v_mm[4], mm[4]);
- FORKEE_ASSERT_EQ(v_mm[5], mm[5]);
- FORKEE_ASSERT_EQ(v_mm[6], mm[6]);
- FORKEE_ASSERT_EQ(v_mm[7], mm[7]);
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- DPRINTF("Call GETFPREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
-
-#if defined(__x86_64__)
-#define MM_REG(n) fpr.fxstate.fx_87_ac[n].r.f87_mantissa
#else
-#define MM_REG(n) fpr.fstate.s87_ac[n].f87_mantissa
+ __unreachable();
#endif
-
- MM_REG(0) = mm[0];
- MM_REG(1) = mm[1];
- MM_REG(2) = mm[2];
- MM_REG(3) = mm[3];
- MM_REG(4) = mm[4];
- MM_REG(5) = mm[5];
- MM_REG(6) = mm[6];
- MM_REG(7) = mm[7];
-
-#undef MM_REG
-
- DPRINTF("Call SETFPREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
}
-__attribute__((target("sse")))
-static __inline void set_xmm_regs(const void* xmm)
+static __inline void set_gp32_ebp_esp_regs(const union x86_test_register data[])
{
+#if defined(__i386__)
__asm__ __volatile__(
- "movaps 0x00(%0), %%xmm0\n\t"
- "movaps 0x10(%0), %%xmm1\n\t"
- "movaps 0x20(%0), %%xmm2\n\t"
- "movaps 0x30(%0), %%xmm3\n\t"
- "movaps 0x40(%0), %%xmm4\n\t"
- "movaps 0x50(%0), %%xmm5\n\t"
- "movaps 0x60(%0), %%xmm6\n\t"
- "movaps 0x70(%0), %%xmm7\n\t"
-#if defined(__x86_64__)
- "movaps 0x80(%0), %%xmm8\n\t"
- "movaps 0x90(%0), %%xmm9\n\t"
- "movaps 0xA0(%0), %%xmm10\n\t"
- "movaps 0xB0(%0), %%xmm11\n\t"
- "movaps 0xC0(%0), %%xmm12\n\t"
- "movaps 0xD0(%0), %%xmm13\n\t"
- "movaps 0xE0(%0), %%xmm14\n\t"
- "movaps 0xF0(%0), %%xmm15\n\t"
-#endif
+ /* ebp & ebp are a bit tricky, we must not clobber them */
+ "movl %%esp, %%eax\n\t"
+ "movl %%ebp, %%ebx\n\t"
+ "movl %0, %%esp\n\t"
+ "movl %1, %%ebp\n\t"
+ "\n\t"
"int3\n\t"
+ "\n\t"
+ "movl %%eax, %%esp\n\t"
+ "movl %%ebx, %%ebp\n\t"
:
- : "b"(xmm)
- : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
- "%xmm7"
-#if defined(__x86_64__)
- , "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13",
- "%xmm14", "%xmm15"
-#endif
+ : "ri"(data[0].u32), "ri"(data[1].u32)
+ : "%eax", "%ebx"
);
+#else
+ __unreachable();
+#endif
}
-ATF_TC(x86_regs_xmm_read);
-ATF_TC_HEAD(x86_regs_xmm_read, tc)
+static __inline void get_gp64_regs(union x86_test_register out[])
{
- atf_tc_set_md_var(tc, "descr",
- "Set xmm0..xmm15 (..xmm7 on i386) reg values from debugged program "
- "and read them via PT_GETFPREGS (PT_GETXMMREGS on i386), comparing "
- "values against expected.");
+#if defined(__x86_64__)
+ const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
+
+ __asm__ __volatile__(
+ /* save rsp & rbp */
+ "movq %%rsp, %6\n\t"
+ "movq %%rbp, %7\n\t"
+ "\n\t"
+ /* fill registers with clobber pattern */
+ "movq %8, %%rax\n\t"
+ "movq %8, %%rbx\n\t"
+ "movq %8, %%rcx\n\t"
+ "movq %8, %%rdx\n\t"
+ "movq %8, %%rsp\n\t"
+ "movq %8, %%rbp\n\t"
+ "movq %8, %%rsi\n\t"
+ "movq %8, %%rdi\n\t"
+ "\n\t"
+ "int3\n\t"
+ "\n\t"
+ /* swap saved & current rsp & rbp */
+ "xchgq %%rsp, %6\n\t"
+ "xchgq %%rbp, %7\n\t"
+ : "=a"(out[0].u64), "=b"(out[1].u64), "=c"(out[2].u64),
+ "=d"(out[3].u64), "=S"(out[4].u64), "=D"(out[5].u64),
+ "=r"(out[6].u64), "=r"(out[7].u64)
+ : "g"(fill)
+ );
+#else
+ __unreachable();
+#endif
}
-ATF_TC_BODY(x86_regs_xmm_read, tc)
+static __inline void set_gp64_regs(const union x86_test_register data[])
{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
#if defined(__x86_64__)
- struct fpreg fpr;
+ __asm__ __volatile__(
+ /* rbp & rbp are a bit tricky, we must not clobber them */
+ "movq %%rsp, %%r8\n\t"
+ "movq %%rbp, %%r9\n\t"
+ "movq %6, %%rsp\n\t"
+ "movq %7, %%rbp\n\t"
+ "\n\t"
+ "int3\n\t"
+ "\n\t"
+ "movq %%r8, %%rsp\n\t"
+ "movq %%r9, %%rbp\n\t"
+ :
+ : "a"(data[0].u64), "b"(data[1].u64), "c"(data[2].u64),
+ "d"(data[3].u64), "S"(data[4].u64), "D"(data[5].u64),
+ "r"(data[6].u64), "r"(data[7].u64)
+ : "%r8", "%r9"
+ );
#else
- struct xmmregs fpr;
+ __unreachable();
#endif
+}
- const struct {
- uint64_t a, b;
- } xmm[] __aligned(16) = {
- { 0x0706050403020100, 0x0F0E0D0C0B0A0908, },
- { 0x0807060504030201, 0x100F0E0D0C0B0A09, },
- { 0x0908070605040302, 0x11100F0E0D0C0B0A, },
- { 0x0A09080706050403, 0x1211100F0E0D0C0B, },
- { 0x0B0A090807060504, 0x131211100F0E0D0C, },
- { 0x0C0B0A0908070605, 0x14131211100F0E0D, },
- { 0x0D0C0B0A09080706, 0x1514131211100F0E, },
- { 0x0E0D0C0B0A090807, 0x161514131211100F, },
+static __inline void get_gp64_r8_regs(union x86_test_register out[])
+{
#if defined(__x86_64__)
- { 0x0F0E0D0C0B0A0908, 0x1716151413121110, },
- { 0x100F0E0D0C0B0A09, 0x1817161514131211, },
- { 0x11100F0E0D0C0B0A, 0x1918171615141312, },
- { 0x1211100F0E0D0C0B, 0x1A19181716151413, },
- { 0x131211100F0E0D0C, 0x1B1A191817161514, },
- { 0x14131211100F0E0D, 0x1C1B1A1918171615, },
- { 0x1514131211100F0E, 0x1D1C1B1A19181716, },
- { 0x161514131211100F, 0x1E1D1C1B1A191817, },
-#endif
- };
-
- /* verify whether SSE is supported here */
- DPRINTF("Before invoking cpuid\n");
- {
- unsigned int eax, ebx, ecx, edx;
- if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
- atf_tc_skip("CPUID is not supported by the CPU");
-
- DPRINTF("cpuid: EDX = %08x\n", edx);
-
- if (!(edx & bit_SSE))
- atf_tc_skip("SSE is not supported by the CPU");
- }
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
- set_xmm_regs(xmm);
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
+ const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
-#if defined(__x86_64__)
- DPRINTF("Call GETFPREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
+ __asm__ __volatile__(
+ /* fill registers with clobber pattern */
+ "movq %1, %%r8\n\t"
+ "movq %1, %%r9\n\t"
+ "movq %1, %%r10\n\t"
+ "movq %1, %%r11\n\t"
+ "movq %1, %%r12\n\t"
+ "movq %1, %%r13\n\t"
+ "movq %1, %%r14\n\t"
+ "movq %1, %%r15\n\t"
+ "\n\t"
+ "int3\n\t"
+ "\n\t"
+ "movq %%r8, 0x00(%0)\n\t"
+ "movq %%r9, 0x20(%0)\n\t"
+ "movq %%r10, 0x40(%0)\n\t"
+ "movq %%r11, 0x60(%0)\n\t"
+ "movq %%r12, 0x80(%0)\n\t"
+ "movq %%r13, 0xA0(%0)\n\t"
+ "movq %%r14, 0xC0(%0)\n\t"
+ "movq %%r15, 0xE0(%0)\n\t"
+ :
+ : "a"(out), "m"(fill)
+ : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
+ );
#else
- DPRINTF("Call GETXMMREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETXMMREGS, child, &fpr, 0) != -1);
-#endif
-
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[0], &xmm[0], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[1], &xmm[1], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[2], &xmm[2], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[3], &xmm[3], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[4], &xmm[4], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[5], &xmm[5], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[6], &xmm[6], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[7], &xmm[7], sizeof(*xmm)));
-#if defined(__x86_64__)
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[8], &xmm[8], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[9], &xmm[9], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[10], &xmm[10], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[11], &xmm[11], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[12], &xmm[12], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[13], &xmm[13], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[14], &xmm[14], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[15], &xmm[15], sizeof(*xmm)));
+ __unreachable();
#endif
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
}
-__attribute__((target("sse")))
-static __inline void get_xmm_regs(void* v_xmm)
+static __inline void set_gp64_r8_regs(const union x86_test_register data[])
{
- const struct {
- uint64_t a, b;
- } fill __aligned(16) = {0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F};
-
- __asm__ __volatile__(
- /* fill registers with clobber pattern */
- "movaps %1, %%xmm0\n\t"
- "movaps %1, %%xmm1\n\t"
- "movaps %1, %%xmm2\n\t"
- "movaps %1, %%xmm3\n\t"
- "movaps %1, %%xmm4\n\t"
- "movaps %1, %%xmm5\n\t"
- "movaps %1, %%xmm6\n\t"
- "movaps %1, %%xmm7\n\t"
-#if defined(__x86_64__)
- "movaps %1, %%xmm8\n\t"
- "movaps %1, %%xmm9\n\t"
- "movaps %1, %%xmm10\n\t"
- "movaps %1, %%xmm11\n\t"
- "movaps %1, %%xmm12\n\t"
- "movaps %1, %%xmm13\n\t"
- "movaps %1, %%xmm14\n\t"
- "movaps %1, %%xmm15\n\t"
-#endif
- "\n\t"
- "int3\n\t"
- "\n\t"
- "movaps %%xmm0, 0x00(%0)\n\t"
- "movaps %%xmm1, 0x10(%0)\n\t"
- "movaps %%xmm2, 0x20(%0)\n\t"
- "movaps %%xmm3, 0x30(%0)\n\t"
- "movaps %%xmm4, 0x40(%0)\n\t"
- "movaps %%xmm5, 0x50(%0)\n\t"
- "movaps %%xmm6, 0x60(%0)\n\t"
- "movaps %%xmm7, 0x70(%0)\n\t"
-#if defined(__x86_64__)
- "movaps %%xmm8, 0x80(%0)\n\t"
- "movaps %%xmm9, 0x90(%0)\n\t"
- "movaps %%xmm10, 0xA0(%0)\n\t"
- "movaps %%xmm11, 0xB0(%0)\n\t"
- "movaps %%xmm12, 0xC0(%0)\n\t"
- "movaps %%xmm13, 0xD0(%0)\n\t"
- "movaps %%xmm14, 0xE0(%0)\n\t"
- "movaps %%xmm15, 0xF0(%0)\n\t"
-#endif
- :
- : "a"(v_xmm), "m"(fill)
- : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7"
-#if defined(__x86_64__)
- , "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14",
- "%xmm15"
-#endif
- );
-}
-
-ATF_TC(x86_regs_xmm_write);
-ATF_TC_HEAD(x86_regs_xmm_write, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set xmm0..xmm15 (..xmm7 on i386) reg values into a debugged "
- "program via PT_SETFPREGS (PT_SETXMMREGS on i386) and compare "
- "the result against expected.");
-}
-
-ATF_TC_BODY(x86_regs_xmm_write, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
#if defined(__x86_64__)
- struct fpreg fpr;
-#else
- struct xmmregs fpr;
-#endif
-
- const struct {
- uint64_t a, b;
- } xmm[] __aligned(16) = {
- { 0x0706050403020100, 0x0F0E0D0C0B0A0908, },
- { 0x0807060504030201, 0x100F0E0D0C0B0A09, },
- { 0x0908070605040302, 0x11100F0E0D0C0B0A, },
- { 0x0A09080706050403, 0x1211100F0E0D0C0B, },
- { 0x0B0A090807060504, 0x131211100F0E0D0C, },
- { 0x0C0B0A0908070605, 0x14131211100F0E0D, },
- { 0x0D0C0B0A09080706, 0x1514131211100F0E, },
- { 0x0E0D0C0B0A090807, 0x161514131211100F, },
-#if defined(__x86_64__)
- { 0x0F0E0D0C0B0A0908, 0x1716151413121110, },
- { 0x100F0E0D0C0B0A09, 0x1817161514131211, },
- { 0x11100F0E0D0C0B0A, 0x1918171615141312, },
- { 0x1211100F0E0D0C0B, 0x1A19181716151413, },
- { 0x131211100F0E0D0C, 0x1B1A191817161514, },
- { 0x14131211100F0E0D, 0x1C1B1A1918171615, },
- { 0x1514131211100F0E, 0x1D1C1B1A19181716, },
- { 0x161514131211100F, 0x1E1D1C1B1A191817, },
-#endif
- };
-
- /* verify whether SSE is supported here */
- DPRINTF("Before invoking cpuid\n");
- {
- unsigned int eax, ebx, ecx, edx;
- if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
- atf_tc_skip("CPUID is not supported by the CPU");
-
- DPRINTF("cpuid: EDX = %08x\n", edx);
-
- if (!(edx & bit_SSE))
- atf_tc_skip("SSE is not supported by the CPU");
- }
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- struct {
- uint64_t a, b;
- } v_xmm[16] __aligned(16);
-
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
- get_xmm_regs(v_xmm);
-
- DPRINTF("Before comparing results\n");
- FORKEE_ASSERT(!memcmp(&v_xmm[0], &xmm[0], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[1], &xmm[1], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[2], &xmm[2], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[3], &xmm[3], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[4], &xmm[4], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[5], &xmm[5], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[6], &xmm[6], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[7], &xmm[7], sizeof(*xmm)));
-#if defined(__x86_64__)
- FORKEE_ASSERT(!memcmp(&v_xmm[8], &xmm[8], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[9], &xmm[9], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[10], &xmm[10], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[11], &xmm[11], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[12], &xmm[12], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[13], &xmm[13], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[14], &xmm[14], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[15], &xmm[15], sizeof(*xmm)));
-#endif
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
-#if defined(__x86_64__)
- DPRINTF("Call GETFPREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
-#else
- DPRINTF("Call GETXMMREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETXMMREGS, child, &fpr, 0) != -1);
-#endif
-
- memcpy(&fpr.fxstate.fx_xmm[0], &xmm[0], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[1], &xmm[1], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[2], &xmm[2], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[3], &xmm[3], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[4], &xmm[4], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[5], &xmm[5], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[6], &xmm[6], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[7], &xmm[7], sizeof(*xmm));
-#if defined(__x86_64__)
- memcpy(&fpr.fxstate.fx_xmm[8], &xmm[8], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[9], &xmm[9], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[10], &xmm[10], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[11], &xmm[11], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[12], &xmm[12], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[13], &xmm[13], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[14], &xmm[14], sizeof(*xmm));
- memcpy(&fpr.fxstate.fx_xmm[15], &xmm[15], sizeof(*xmm));
-#endif
-
-#if defined(__x86_64__)
- DPRINTF("Call SETFPREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
-#else
- DPRINTF("Call SETXMMREGS for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_SETXMMREGS, child, &fpr, 0) != -1);
-#endif
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_xstate_mm_read);
-ATF_TC_HEAD(x86_xstate_mm_read, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set MMX (mm0..mm7) reg values from debugged program and read "
- "them via PT_GETXSTATE, comparing values against expected.");
-}
-
-ATF_TC_BODY(x86_xstate_mm_read, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct iovec iov;
- struct xstate xst;
-
- const uint64_t mm[] = {
- 0x0001020304050607,
- 0x1011121314151617,
- 0x2021222324252627,
- 0x3031323334353637,
- 0x4041424344454647,
- 0x5051525354555657,
- 0x6061626364656667,
- 0x7071727374757677,
- };
-
- /* verify whether MMX is supported here */
- DPRINTF("Before invoking cpuid\n");
- {
- unsigned int eax, ebx, ecx, edx;
- if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
- atf_tc_skip("CPUID is not supported by the CPU");
-
- DPRINTF("cpuid: EDX = %08x\n", edx);
-
- if (!(edx & bit_MMX))
- atf_tc_skip("MMX is not supported by the CPU");
- }
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
- set_mm_regs(mm);
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- iov.iov_base = &xst;
- iov.iov_len = sizeof(xst);
-
- DPRINTF("Call GETXSTATE for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
- ATF_REQUIRE(xst.xs_rfbm & XCR0_X87);
- ATF_REQUIRE(xst.xs_xstate_bv & XCR0_X87);
-
- ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[0].r.f87_mantissa, mm[0]);
- ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[1].r.f87_mantissa, mm[1]);
- ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[2].r.f87_mantissa, mm[2]);
- ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[3].r.f87_mantissa, mm[3]);
- ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[4].r.f87_mantissa, mm[4]);
- ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[5].r.f87_mantissa, mm[5]);
- ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[6].r.f87_mantissa, mm[6]);
- ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[7].r.f87_mantissa, mm[7]);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_xstate_mm_write);
-ATF_TC_HEAD(x86_xstate_mm_write, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set mm0..mm7 reg values into a debugged program via "
- "PT_SETXSTATE and compare the result against expected.");
-}
-
-ATF_TC_BODY(x86_xstate_mm_write, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct iovec iov;
- struct xstate xst;
-
- const uint64_t mm[] = {
- 0x0001020304050607,
- 0x1011121314151617,
- 0x2021222324252627,
- 0x3031323334353637,
- 0x4041424344454647,
- 0x5051525354555657,
- 0x6061626364656667,
- 0x7071727374757677,
- };
-
- /* verify whether MMX is supported here */
- DPRINTF("Before invoking cpuid\n");
- {
- unsigned int eax, ebx, ecx, edx;
- if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
- atf_tc_skip("CPUID is not supported by the CPU");
-
- DPRINTF("cpuid: EDX = %08x\n", edx);
-
- if (!(edx & bit_MMX))
- atf_tc_skip("MMX is not supported by the CPU");
- }
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- uint64_t v_mm[8];
-
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
- get_mm_regs(v_mm);
-
- DPRINTF("Before comparing results\n");
- FORKEE_ASSERT_EQ(v_mm[0], mm[0]);
- FORKEE_ASSERT_EQ(v_mm[1], mm[1]);
- FORKEE_ASSERT_EQ(v_mm[2], mm[2]);
- FORKEE_ASSERT_EQ(v_mm[3], mm[3]);
- FORKEE_ASSERT_EQ(v_mm[4], mm[4]);
- FORKEE_ASSERT_EQ(v_mm[5], mm[5]);
- FORKEE_ASSERT_EQ(v_mm[6], mm[6]);
- FORKEE_ASSERT_EQ(v_mm[7], mm[7]);
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- iov.iov_base = &xst;
- iov.iov_len = sizeof(xst);
-
- DPRINTF("Call GETXSTATE for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
- ATF_REQUIRE(xst.xs_rfbm & XCR0_X87);
-
- xst.xs_rfbm = XCR0_X87;
- xst.xs_xstate_bv = XCR0_X87;
-
- xst.xs_fxsave.fx_87_ac[0].r.f87_mantissa = mm[0];
- xst.xs_fxsave.fx_87_ac[1].r.f87_mantissa = mm[1];
- xst.xs_fxsave.fx_87_ac[2].r.f87_mantissa = mm[2];
- xst.xs_fxsave.fx_87_ac[3].r.f87_mantissa = mm[3];
- xst.xs_fxsave.fx_87_ac[4].r.f87_mantissa = mm[4];
- xst.xs_fxsave.fx_87_ac[5].r.f87_mantissa = mm[5];
- xst.xs_fxsave.fx_87_ac[6].r.f87_mantissa = mm[6];
- xst.xs_fxsave.fx_87_ac[7].r.f87_mantissa = mm[7];
-
- DPRINTF("Call SETXSTATE for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_SETXSTATE, child, &iov, 0) != -1);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_xstate_xmm_read);
-ATF_TC_HEAD(x86_xstate_xmm_read, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set xmm0..xmm15 (..xmm7 on i386) reg values from debugged program "
- "and read them via PT_GETXSTATE, comparing values against expected.");
-}
-
-ATF_TC_BODY(x86_xstate_xmm_read, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct xstate xst;
- struct iovec iov;
-
- const struct {
- uint64_t a, b;
- } xmm[] __aligned(16) = {
- { 0x0706050403020100, 0x0F0E0D0C0B0A0908, },
- { 0x0807060504030201, 0x100F0E0D0C0B0A09, },
- { 0x0908070605040302, 0x11100F0E0D0C0B0A, },
- { 0x0A09080706050403, 0x1211100F0E0D0C0B, },
- { 0x0B0A090807060504, 0x131211100F0E0D0C, },
- { 0x0C0B0A0908070605, 0x14131211100F0E0D, },
- { 0x0D0C0B0A09080706, 0x1514131211100F0E, },
- { 0x0E0D0C0B0A090807, 0x161514131211100F, },
-#if defined(__x86_64__)
- { 0x0F0E0D0C0B0A0908, 0x1716151413121110, },
- { 0x100F0E0D0C0B0A09, 0x1817161514131211, },
- { 0x11100F0E0D0C0B0A, 0x1918171615141312, },
- { 0x1211100F0E0D0C0B, 0x1A19181716151413, },
- { 0x131211100F0E0D0C, 0x1B1A191817161514, },
- { 0x14131211100F0E0D, 0x1C1B1A1918171615, },
- { 0x1514131211100F0E, 0x1D1C1B1A19181716, },
- { 0x161514131211100F, 0x1E1D1C1B1A191817, },
-#endif
- };
-
- /* verify whether SSE is supported here */
- DPRINTF("Before invoking cpuid\n");
- {
- unsigned int eax, ebx, ecx, edx;
- if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
- atf_tc_skip("CPUID is not supported by the CPU");
-
- DPRINTF("cpuid: EDX = %08x\n", edx);
-
- if (!(edx & bit_SSE))
- atf_tc_skip("SSE is not supported by the CPU");
- }
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
- set_xmm_regs(xmm);
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- iov.iov_base = &xst;
- iov.iov_len = sizeof(xst);
-
- DPRINTF("Call GETXSTATE for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
- ATF_REQUIRE(xst.xs_rfbm & XCR0_SSE);
- ATF_REQUIRE(xst.xs_xstate_bv & XCR0_SSE);
-
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[0], &xmm[0], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[1], &xmm[1], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[2], &xmm[2], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[3], &xmm[3], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[4], &xmm[4], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[5], &xmm[5], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[6], &xmm[6], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[7], &xmm[7], sizeof(*xmm)));
-#if defined(__x86_64__)
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[8], &xmm[8], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[9], &xmm[9], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[10], &xmm[10], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[11], &xmm[11], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[12], &xmm[12], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[13], &xmm[13], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[14], &xmm[14], sizeof(*xmm)));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[15], &xmm[15], sizeof(*xmm)));
-#endif
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_xstate_xmm_write);
-ATF_TC_HEAD(x86_xstate_xmm_write, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set xmm0..xmm15 (..xmm7 on i386) reg values into a debugged "
- "program via PT_SETXSTATE and compare the result against expected.");
-}
-
-ATF_TC_BODY(x86_xstate_xmm_write, tc)
-{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct xstate xst;
- struct iovec iov;
-
- const struct {
- uint64_t a, b;
- } xmm[] __aligned(16) = {
- { 0x0706050403020100, 0x0F0E0D0C0B0A0908, },
- { 0x0807060504030201, 0x100F0E0D0C0B0A09, },
- { 0x0908070605040302, 0x11100F0E0D0C0B0A, },
- { 0x0A09080706050403, 0x1211100F0E0D0C0B, },
- { 0x0B0A090807060504, 0x131211100F0E0D0C, },
- { 0x0C0B0A0908070605, 0x14131211100F0E0D, },
- { 0x0D0C0B0A09080706, 0x1514131211100F0E, },
- { 0x0E0D0C0B0A090807, 0x161514131211100F, },
-#if defined(__x86_64__)
- { 0x0F0E0D0C0B0A0908, 0x1716151413121110, },
- { 0x100F0E0D0C0B0A09, 0x1817161514131211, },
- { 0x11100F0E0D0C0B0A, 0x1918171615141312, },
- { 0x1211100F0E0D0C0B, 0x1A19181716151413, },
- { 0x131211100F0E0D0C, 0x1B1A191817161514, },
- { 0x14131211100F0E0D, 0x1C1B1A1918171615, },
- { 0x1514131211100F0E, 0x1D1C1B1A19181716, },
- { 0x161514131211100F, 0x1E1D1C1B1A191817, },
-#endif
- };
-
- /* verify whether SSE is supported here */
- DPRINTF("Before invoking cpuid\n");
- {
- unsigned int eax, ebx, ecx, edx;
- if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
- atf_tc_skip("CPUID is not supported by the CPU");
-
- DPRINTF("cpuid: EDX = %08x\n", edx);
-
- if (!(edx & bit_SSE))
- atf_tc_skip("SSE is not supported by the CPU");
- }
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- struct {
- uint64_t a, b;
- } v_xmm[16] __aligned(16);
-
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
- get_xmm_regs(v_xmm);
-
- DPRINTF("Before comparing results\n");
- FORKEE_ASSERT(!memcmp(&v_xmm[0], &xmm[0], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[1], &xmm[1], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[2], &xmm[2], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[3], &xmm[3], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[4], &xmm[4], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[5], &xmm[5], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[6], &xmm[6], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[7], &xmm[7], sizeof(*xmm)));
-#if defined(__x86_64__)
- FORKEE_ASSERT(!memcmp(&v_xmm[8], &xmm[8], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[9], &xmm[9], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[10], &xmm[10], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[11], &xmm[11], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[12], &xmm[12], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[13], &xmm[13], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[14], &xmm[14], sizeof(*xmm)));
- FORKEE_ASSERT(!memcmp(&v_xmm[15], &xmm[15], sizeof(*xmm)));
-#endif
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- iov.iov_base = &xst;
- iov.iov_len = sizeof(xst);
-
- DPRINTF("Call GETXSTATE for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
- ATF_REQUIRE(xst.xs_rfbm & XCR0_SSE);
-
- xst.xs_rfbm = XCR0_SSE;
- xst.xs_xstate_bv = XCR0_SSE;
-
- memcpy(&xst.xs_fxsave.fx_xmm[0], &xmm[0], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[1], &xmm[1], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[2], &xmm[2], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[3], &xmm[3], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[4], &xmm[4], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[5], &xmm[5], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[6], &xmm[6], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[7], &xmm[7], sizeof(*xmm));
-#if defined(__x86_64__)
- memcpy(&xst.xs_fxsave.fx_xmm[8], &xmm[8], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[9], &xmm[9], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[10], &xmm[10], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[11], &xmm[11], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[12], &xmm[12], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[13], &xmm[13], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[14], &xmm[14], sizeof(*xmm));
- memcpy(&xst.xs_fxsave.fx_xmm[15], &xmm[15], sizeof(*xmm));
+ __asm__ __volatile__(
+ "movq 0x00(%0), %%r8\n\t"
+ "movq 0x20(%0), %%r9\n\t"
+ "movq 0x40(%0), %%r10\n\t"
+ "movq 0x60(%0), %%r11\n\t"
+ "movq 0x80(%0), %%r12\n\t"
+ "movq 0xA0(%0), %%r13\n\t"
+ "movq 0xC0(%0), %%r14\n\t"
+ "movq 0xE0(%0), %%r15\n\t"
+ "int3\n\t"
+ :
+ : "b"(data)
+ : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
+ );
+#else
+ __unreachable();
#endif
+}
- DPRINTF("Call SETXSTATE for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_SETXSTATE, child, &iov, 0) != -1);
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+__attribute__((target("mmx")))
+static __inline void get_mm_regs(union x86_test_register out[])
+{
+ const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
- validate_status_exited(status, exitval);
+ __asm__ __volatile__(
+ /* fill registers with clobber pattern */
+ "movq %1, %%mm0\n\t"
+ "movq %1, %%mm1\n\t"
+ "movq %1, %%mm2\n\t"
+ "movq %1, %%mm3\n\t"
+ "movq %1, %%mm4\n\t"
+ "movq %1, %%mm5\n\t"
+ "movq %1, %%mm6\n\t"
+ "movq %1, %%mm7\n\t"
+ "\n\t"
+ "int3\n\t"
+ "\n\t"
+ "movq %%mm0, 0x00(%0)\n\t"
+ "movq %%mm1, 0x20(%0)\n\t"
+ "movq %%mm2, 0x40(%0)\n\t"
+ "movq %%mm3, 0x60(%0)\n\t"
+ "movq %%mm4, 0x80(%0)\n\t"
+ "movq %%mm5, 0xA0(%0)\n\t"
+ "movq %%mm6, 0xC0(%0)\n\t"
+ "movq %%mm7, 0xE0(%0)\n\t"
+ :
+ : "a"(out), "m"(fill)
+ : "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
+ );
+}
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
+__attribute__((target("mmx")))
+static __inline void set_mm_regs(const union x86_test_register data[])
+{
+ __asm__ __volatile__(
+ "movq 0x00(%0), %%mm0\n\t"
+ "movq 0x20(%0), %%mm1\n\t"
+ "movq 0x40(%0), %%mm2\n\t"
+ "movq 0x60(%0), %%mm3\n\t"
+ "movq 0x80(%0), %%mm4\n\t"
+ "movq 0xA0(%0), %%mm5\n\t"
+ "movq 0xC0(%0), %%mm6\n\t"
+ "movq 0xE0(%0), %%mm7\n\t"
+ "int3\n\t"
+ :
+ : "b"(data)
+ : "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
+ );
}
-__attribute__((target("avx")))
-static __inline void set_ymm_regs(const void* ymm)
+__attribute__((target("sse")))
+static __inline void get_xmm_regs(union x86_test_register out[])
{
+ union x86_test_register fill __aligned(32) = {
+ .xmm={ 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F }
+ };
+
__asm__ __volatile__(
- "vmovaps 0x000(%0), %%ymm0\n\t"
- "vmovaps 0x020(%0), %%ymm1\n\t"
- "vmovaps 0x040(%0), %%ymm2\n\t"
- "vmovaps 0x060(%0), %%ymm3\n\t"
- "vmovaps 0x080(%0), %%ymm4\n\t"
- "vmovaps 0x0A0(%0), %%ymm5\n\t"
- "vmovaps 0x0C0(%0), %%ymm6\n\t"
- "vmovaps 0x0E0(%0), %%ymm7\n\t"
+ /* fill registers with clobber pattern */
+ "movaps %1, %%xmm0\n\t"
+ "movaps %1, %%xmm1\n\t"
+ "movaps %1, %%xmm2\n\t"
+ "movaps %1, %%xmm3\n\t"
+ "movaps %1, %%xmm4\n\t"
+ "movaps %1, %%xmm5\n\t"
+ "movaps %1, %%xmm6\n\t"
+ "movaps %1, %%xmm7\n\t"
#if defined(__x86_64__)
- "vmovaps 0x100(%0), %%ymm8\n\t"
- "vmovaps 0x120(%0), %%ymm9\n\t"
- "vmovaps 0x140(%0), %%ymm10\n\t"
- "vmovaps 0x160(%0), %%ymm11\n\t"
- "vmovaps 0x180(%0), %%ymm12\n\t"
- "vmovaps 0x1A0(%0), %%ymm13\n\t"
- "vmovaps 0x1C0(%0), %%ymm14\n\t"
- "vmovaps 0x1E0(%0), %%ymm15\n\t"
+ "movaps %1, %%xmm8\n\t"
+ "movaps %1, %%xmm9\n\t"
+ "movaps %1, %%xmm10\n\t"
+ "movaps %1, %%xmm11\n\t"
+ "movaps %1, %%xmm12\n\t"
+ "movaps %1, %%xmm13\n\t"
+ "movaps %1, %%xmm14\n\t"
+ "movaps %1, %%xmm15\n\t"
#endif
+ "\n\t"
"int3\n\t"
+ "\n\t"
+ "movaps %%xmm0, 0x000(%0)\n\t"
+ "movaps %%xmm1, 0x020(%0)\n\t"
+ "movaps %%xmm2, 0x040(%0)\n\t"
+ "movaps %%xmm3, 0x060(%0)\n\t"
+ "movaps %%xmm4, 0x080(%0)\n\t"
+ "movaps %%xmm5, 0x0A0(%0)\n\t"
+ "movaps %%xmm6, 0x0C0(%0)\n\t"
+ "movaps %%xmm7, 0x0E0(%0)\n\t"
+#if defined(__x86_64__)
+ "movaps %%xmm8, 0x100(%0)\n\t"
+ "movaps %%xmm9, 0x120(%0)\n\t"
+ "movaps %%xmm10, 0x140(%0)\n\t"
+ "movaps %%xmm11, 0x160(%0)\n\t"
+ "movaps %%xmm12, 0x180(%0)\n\t"
+ "movaps %%xmm13, 0x1A0(%0)\n\t"
+ "movaps %%xmm14, 0x1C0(%0)\n\t"
+ "movaps %%xmm15, 0x1E0(%0)\n\t"
+#endif
:
- : "b"(ymm)
- : "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6",
- "%ymm7"
+ : "a"(out), "m"(fill)
+ : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7"
#if defined(__x86_64__)
- , "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13",
- "%ymm14", "%ymm15"
+ , "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14",
+ "%xmm15"
#endif
);
}
-ATF_TC(x86_xstate_ymm_read);
-ATF_TC_HEAD(x86_xstate_ymm_read, tc)
-{
- atf_tc_set_md_var(tc, "descr",
- "Set ymm0..ymm15 (..ymm7 on i386) reg values from debugged program "
- "and read them via PT_GETXSTATE, comparing values against expected.");
-}
-
-ATF_TC_BODY(x86_xstate_ymm_read, tc)
+__attribute__((target("sse")))
+static __inline void set_xmm_regs(const union x86_test_register data[])
{
- const int exitval = 5;
- pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
- const int sigval = SIGTRAP;
- int status;
-#endif
- struct xstate xst;
- struct iovec iov;
-
- const struct {
- uint64_t a, b, c, d;
- } ymm[] __aligned(32) = {
- { 0x0706050403020100, 0x0F0E0D0C0B0A0908,
- 0x1716151413121110, 0x1F1E1D1C1B1A1918, },
- { 0x0807060504030201, 0x100F0E0D0C0B0A09,
- 0x1817161514131211, 0x201F1E1D1C1B1A19, },
- { 0x0908070605040302, 0x11100F0E0D0C0B0A,
- 0x1918171615141312, 0x21201F1E1D1C1B1A, },
- { 0x0A09080706050403, 0x1211100F0E0D0C0B,
- 0x1A19181716151413, 0x2221201F1E1D1C1B, },
- { 0x0B0A090807060504, 0x131211100F0E0D0C,
- 0x1B1A191817161514, 0x232221201F1E1D1C, },
- { 0x0C0B0A0908070605, 0x14131211100F0E0D,
- 0x1C1B1A1918171615, 0x24232221201F1E1D, },
- { 0x0D0C0B0A09080706, 0x1514131211100F0E,
- 0x1D1C1B1A19181716, 0x2524232221201F1E, },
- { 0x0E0D0C0B0A090807, 0x161514131211100F,
- 0x1E1D1C1B1A191817, 0x262524232221201F, },
+ __asm__ __volatile__(
+ "movaps 0x000(%0), %%xmm0\n\t"
+ "movaps 0x020(%0), %%xmm1\n\t"
+ "movaps 0x040(%0), %%xmm2\n\t"
+ "movaps 0x060(%0), %%xmm3\n\t"
+ "movaps 0x080(%0), %%xmm4\n\t"
+ "movaps 0x0A0(%0), %%xmm5\n\t"
+ "movaps 0x0C0(%0), %%xmm6\n\t"
+ "movaps 0x0E0(%0), %%xmm7\n\t"
#if defined(__x86_64__)
- { 0x0F0E0D0C0B0A0908, 0x1716151413121110,
- 0x1F1E1D1C1B1A1918, 0x2726252423222120, },
- { 0x100F0E0D0C0B0A09, 0x1817161514131211,
- 0x201F1E1D1C1B1A19, 0x2827262524232221, },
- { 0x11100F0E0D0C0B0A, 0x1918171615141312,
- 0x21201F1E1D1C1B1A, 0x2928272625242322, },
- { 0x1211100F0E0D0C0B, 0x1A19181716151413,
- 0x2221201F1E1D1C1B, 0x2A29282726252423, },
- { 0x131211100F0E0D0C, 0x1B1A191817161514,
- 0x232221201F1E1D1C, 0x2B2A292827262524, },
- { 0x14131211100F0E0D, 0x1C1B1A1918171615,
- 0x24232221201F1E1D, 0x2C2B2A2928272625, },
- { 0x1514131211100F0E, 0x1D1C1B1A19181716,
- 0x2524232221201F1E, 0x2D2C2B2A29282726, },
- { 0x161514131211100F, 0x1E1D1C1B1A191817,
- 0x262524232221201F, 0x2E2D2C2B2A292827, },
+ "movaps 0x100(%0), %%xmm8\n\t"
+ "movaps 0x120(%0), %%xmm9\n\t"
+ "movaps 0x140(%0), %%xmm10\n\t"
+ "movaps 0x160(%0), %%xmm11\n\t"
+ "movaps 0x180(%0), %%xmm12\n\t"
+ "movaps 0x1A0(%0), %%xmm13\n\t"
+ "movaps 0x1C0(%0), %%xmm14\n\t"
+ "movaps 0x1E0(%0), %%xmm15\n\t"
#endif
- };
-
- /* verify whether AVX is supported here */
- DPRINTF("Before invoking cpuid\n");
- {
- unsigned int eax, ebx, ecx, edx;
- if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
- atf_tc_skip("CPUID is not supported by the CPU");
-
- DPRINTF("cpuid: ECX = %08x\n", ecx);
-
- if (!(ecx & bit_AVX))
- atf_tc_skip("AVX is not supported by the CPU");
- }
-
- DPRINTF("Before forking process PID=%d\n", getpid());
- SYSCALL_REQUIRE((child = fork()) != -1);
- if (child == 0) {
- DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
- FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- DPRINTF("Before running assembly from child\n");
- set_ymm_regs(ymm);
-
- DPRINTF("Before exiting of the child process\n");
- _exit(exitval);
- }
- DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_stopped(status, sigval);
-
- iov.iov_base = &xst;
- iov.iov_len = sizeof(xst);
-
- DPRINTF("Call GETXSTATE for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
- ATF_REQUIRE(xst.xs_rfbm & XCR0_SSE);
- ATF_REQUIRE(xst.xs_rfbm & XCR0_YMM_Hi128);
- ATF_REQUIRE(xst.xs_xstate_bv & XCR0_SSE);
- ATF_REQUIRE(xst.xs_xstate_bv & XCR0_YMM_Hi128);
-
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[0], &ymm[0].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[0], &ymm[0].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[1], &ymm[1].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[1], &ymm[1].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[2], &ymm[2].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[2], &ymm[2].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[3], &ymm[3].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[3], &ymm[3].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[4], &ymm[4].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[4], &ymm[4].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[5], &ymm[5].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[5], &ymm[5].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[6], &ymm[6].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[6], &ymm[6].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[7], &ymm[7].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[7], &ymm[7].c, sizeof(*ymm)/2));
+ "int3\n\t"
+ :
+ : "b"(data)
+ : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+ "%xmm7"
#if defined(__x86_64__)
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[8], &ymm[8].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[8], &ymm[8].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[9], &ymm[9].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[9], &ymm[9].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[10], &ymm[10].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[10], &ymm[10].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[11], &ymm[11].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[11], &ymm[11].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[12], &ymm[12].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[12], &ymm[12].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[13], &ymm[13].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[13], &ymm[13].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[14], &ymm[14].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[14], &ymm[14].c, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[15], &ymm[15].a, sizeof(*ymm)/2));
- ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[15], &ymm[15].c, sizeof(*ymm)/2));
+ , "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13",
+ "%xmm14", "%xmm15"
#endif
-
- DPRINTF("Before resuming the child process where it left off and "
- "without signal to be sent\n");
- SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
- validate_status_exited(status, exitval);
-
- DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
- TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
+ );
}
__attribute__((target("avx")))
-static __inline void get_ymm_regs(void* v_ymm)
+static __inline void get_ymm_regs(union x86_test_register out[])
{
- const struct {
- uint64_t a, b, c, d;
- } fill __aligned(32) = {
- 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F,
- 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F
+ union x86_test_register fill __aligned(32) = {
+ { 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F,
+ 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F }
};
__asm__ __volatile__(
@@ -3500,7 +2627,7 @@ static __inline void get_ymm_regs(void* v_ymm)
"vmovaps %%ymm15, 0x1E0(%0)\n\t"
#endif
:
- : "a"(v_ymm), "m"(fill)
+ : "a"(out), "m"(fill)
: "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7"
#if defined(__x86_64__)
, "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13", "%ymm14",
@@ -3509,109 +2636,328 @@ static __inline void get_ymm_regs(void* v_ymm)
);
}
-ATF_TC(x86_xstate_ymm_write);
-ATF_TC_HEAD(x86_xstate_ymm_write, tc)
+__attribute__((target("avx")))
+static __inline void set_ymm_regs(const union x86_test_register data[])
{
- atf_tc_set_md_var(tc, "descr",
- "Set ymm0..ymm15 (..ymm7 on i386) reg values into a debugged "
- "program via PT_SETXSTATE and compare the result against expected.");
+ __asm__ __volatile__(
+ "vmovaps 0x000(%0), %%ymm0\n\t"
+ "vmovaps 0x020(%0), %%ymm1\n\t"
+ "vmovaps 0x040(%0), %%ymm2\n\t"
+ "vmovaps 0x060(%0), %%ymm3\n\t"
+ "vmovaps 0x080(%0), %%ymm4\n\t"
+ "vmovaps 0x0A0(%0), %%ymm5\n\t"
+ "vmovaps 0x0C0(%0), %%ymm6\n\t"
+ "vmovaps 0x0E0(%0), %%ymm7\n\t"
+#if defined(__x86_64__)
+ "vmovaps 0x100(%0), %%ymm8\n\t"
+ "vmovaps 0x120(%0), %%ymm9\n\t"
+ "vmovaps 0x140(%0), %%ymm10\n\t"
+ "vmovaps 0x160(%0), %%ymm11\n\t"
+ "vmovaps 0x180(%0), %%ymm12\n\t"
+ "vmovaps 0x1A0(%0), %%ymm13\n\t"
+ "vmovaps 0x1C0(%0), %%ymm14\n\t"
+ "vmovaps 0x1E0(%0), %%ymm15\n\t"
+#endif
+ "int3\n\t"
+ :
+ : "b"(data)
+ : "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6",
+ "%ymm7"
+#if defined(__x86_64__)
+ , "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13",
+ "%ymm14", "%ymm15"
+#endif
+ );
}
-ATF_TC_BODY(x86_xstate_ymm_write, tc)
+static void
+x86_register_test(enum x86_test_regset regset, enum x86_test_registers regs,
+ enum x86_test_regmode regmode)
{
const int exitval = 5;
pid_t child, wpid;
#if defined(TWAIT_HAVE_STATUS)
const int sigval = SIGTRAP;
int status;
+#endif
+ struct reg gpr;
+ struct fpreg fpr;
+#if defined(__i386__)
+ struct xmmregs xmm;
#endif
struct xstate xst;
struct iovec iov;
+ struct fxsave* fxs;
+ uint64_t xst_flags = 0;
+
+ const union x86_test_register expected[] __aligned(32) = {
+ {{ 0x0706050403020100, 0x0F0E0D0C0B0A0908,
+ 0x1716151413121110, 0x1F1E1D1C1B1A1918, }},
+ {{ 0x0807060504030201, 0x100F0E0D0C0B0A09,
+ 0x1817161514131211, 0x201F1E1D1C1B1A19, }},
+ {{ 0x0908070605040302, 0x11100F0E0D0C0B0A,
+ 0x1918171615141312, 0x21201F1E1D1C1B1A, }},
+ {{ 0x0A09080706050403, 0x1211100F0E0D0C0B,
+ 0x1A19181716151413, 0x2221201F1E1D1C1B, }},
+ {{ 0x0B0A090807060504, 0x131211100F0E0D0C,
+ 0x1B1A191817161514, 0x232221201F1E1D1C, }},
+ {{ 0x0C0B0A0908070605, 0x14131211100F0E0D,
+ 0x1C1B1A1918171615, 0x24232221201F1E1D, }},
+ {{ 0x0D0C0B0A09080706, 0x1514131211100F0E,
+ 0x1D1C1B1A19181716, 0x2524232221201F1E, }},
+ {{ 0x0E0D0C0B0A090807, 0x161514131211100F,
+ 0x1E1D1C1B1A191817, 0x262524232221201F, }},
+ {{ 0x0F0E0D0C0B0A0908, 0x1716151413121110,
+ 0x1F1E1D1C1B1A1918, 0x2726252423222120, }},
+ {{ 0x100F0E0D0C0B0A09, 0x1817161514131211,
+ 0x201F1E1D1C1B1A19, 0x2827262524232221, }},
+ {{ 0x11100F0E0D0C0B0A, 0x1918171615141312,
+ 0x21201F1E1D1C1B1A, 0x2928272625242322, }},
+ {{ 0x1211100F0E0D0C0B, 0x1A19181716151413,
+ 0x2221201F1E1D1C1B, 0x2A29282726252423, }},
+ {{ 0x131211100F0E0D0C, 0x1B1A191817161514,
+ 0x232221201F1E1D1C, 0x2B2A292827262524, }},
+ {{ 0x14131211100F0E0D, 0x1C1B1A1918171615,
+ 0x24232221201F1E1D, 0x2C2B2A2928272625, }},
+ {{ 0x1514131211100F0E, 0x1D1C1B1A19181716,
+ 0x2524232221201F1E, 0x2D2C2B2A29282726, }},
+ {{ 0x161514131211100F, 0x1E1D1C1B1A191817,
+ 0x262524232221201F, 0x2E2D2C2B2A292827, }},
+ };
- const struct {
- uint64_t a, b, c, d;
- } ymm[] __aligned(32) = {
- { 0x0706050403020100, 0x0F0E0D0C0B0A0908,
- 0x1716151413121110, 0x1F1E1D1C1B1A1918, },
- { 0x0807060504030201, 0x100F0E0D0C0B0A09,
- 0x1817161514131211, 0x201F1E1D1C1B1A19, },
- { 0x0908070605040302, 0x11100F0E0D0C0B0A,
- 0x1918171615141312, 0x21201F1E1D1C1B1A, },
- { 0x0A09080706050403, 0x1211100F0E0D0C0B,
- 0x1A19181716151413, 0x2221201F1E1D1C1B, },
- { 0x0B0A090807060504, 0x131211100F0E0D0C,
- 0x1B1A191817161514, 0x232221201F1E1D1C, },
- { 0x0C0B0A0908070605, 0x14131211100F0E0D,
- 0x1C1B1A1918171615, 0x24232221201F1E1D, },
- { 0x0D0C0B0A09080706, 0x1514131211100F0E,
- 0x1D1C1B1A19181716, 0x2524232221201F1E, },
- { 0x0E0D0C0B0A090807, 0x161514131211100F,
- 0x1E1D1C1B1A191817, 0x262524232221201F, },
+ bool need_32 = false, need_64 = false, need_cpuid = false;
+
+ switch (regs) {
+ case GPREGS_32:
+ case GPREGS_32_EBP_ESP:
+ need_32 = true;
+ break;
+ case GPREGS_64:
+ case GPREGS_64_R8:
+ need_64 = true;
+ break;
+ case FPREGS_MM:
+ case FPREGS_XMM:
+ case FPREGS_YMM:
+ need_cpuid = true;
+ break;
+ }
+
+ if (need_32) {
#if defined(__x86_64__)
- { 0x0F0E0D0C0B0A0908, 0x1716151413121110,
- 0x1F1E1D1C1B1A1918, 0x2726252423222120, },
- { 0x100F0E0D0C0B0A09, 0x1817161514131211,
- 0x201F1E1D1C1B1A19, 0x2827262524232221, },
- { 0x11100F0E0D0C0B0A, 0x1918171615141312,
- 0x21201F1E1D1C1B1A, 0x2928272625242322, },
- { 0x1211100F0E0D0C0B, 0x1A19181716151413,
- 0x2221201F1E1D1C1B, 0x2A29282726252423, },
- { 0x131211100F0E0D0C, 0x1B1A191817161514,
- 0x232221201F1E1D1C, 0x2B2A292827262524, },
- { 0x14131211100F0E0D, 0x1C1B1A1918171615,
- 0x24232221201F1E1D, 0x2C2B2A2928272625, },
- { 0x1514131211100F0E, 0x1D1C1B1A19181716,
- 0x2524232221201F1E, 0x2D2C2B2A29282726, },
- { 0x161514131211100F, 0x1E1D1C1B1A191817,
- 0x262524232221201F, 0x2E2D2C2B2A292827, },
+ atf_tc_skip("Test requires 32-bit mode");
#endif
- };
+ }
+ if (need_64) {
+#if defined(__i386__)
+ atf_tc_skip("Test requires 64-bit mode");
+#endif
+ }
- /* verify whether AVX is supported here */
- DPRINTF("Before invoking cpuid\n");
- {
+ if (need_cpuid) {
+ /* verify whether needed instruction sets are supported here */
unsigned int eax, ebx, ecx, edx;
+
+ DPRINTF("Before invoking cpuid\n");
if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
atf_tc_skip("CPUID is not supported by the CPU");
- DPRINTF("cpuid: ECX = %08x\n", ecx);
-
- if (!(ecx & bit_AVX))
- atf_tc_skip("AVX is not supported by the CPU");
+ DPRINTF("cpuid: ECX = %08x, EDX = %08xd\n", ecx, edx);
+
+ switch (regs) {
+ case FPREGS_YMM:
+ if (!(ecx & bit_AVX))
+ atf_tc_skip("AVX is not supported by the CPU");
+ /*FALLTHROUGH*/
+ case FPREGS_XMM:
+ if (!(edx & bit_SSE))
+ atf_tc_skip("SSE is not supported by the CPU");
+ break;
+ case FPREGS_MM:
+ if (!(edx & bit_MMX))
+ atf_tc_skip("MMX is not supported by the CPU");
+ break;
+ case GPREGS_32:
+ case GPREGS_32_EBP_ESP:
+ case GPREGS_64:
+ case GPREGS_64_R8:
+ __unreachable();
+ }
}
DPRINTF("Before forking process PID=%d\n", getpid());
SYSCALL_REQUIRE((child = fork()) != -1);
if (child == 0) {
- struct {
- uint64_t a, b, c, d;
- } v_ymm[16] __aligned(32);
+ union x86_test_register vals[16] __aligned(32);
DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
DPRINTF("Before running assembly from child\n");
- get_ymm_regs(v_ymm);
-
- DPRINTF("Before comparing results\n");
- FORKEE_ASSERT(!memcmp(&v_ymm[0], &ymm[0], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[1], &ymm[1], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[2], &ymm[2], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[3], &ymm[3], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[4], &ymm[4], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[5], &ymm[5], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[6], &ymm[6], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[7], &ymm[7], sizeof(*ymm)));
+ switch (regmode) {
+ case TEST_GETREGS:
+ switch (regs) {
+ case GPREGS_32:
+ set_gp32_regs(expected);
+ break;
+ case GPREGS_32_EBP_ESP:
+ set_gp32_ebp_esp_regs(expected);
+ break;
+ case GPREGS_64:
+ set_gp64_regs(expected);
+ break;
+ case GPREGS_64_R8:
+ set_gp64_r8_regs(expected);
+ break;
+ case FPREGS_MM:
+ set_mm_regs(expected);
+ break;
+ case FPREGS_XMM:
+ set_xmm_regs(expected);
+ break;
+ case FPREGS_YMM:
+ set_ymm_regs(expected);
+ break;
+ }
+ break;
+ case TEST_SETREGS:
+ switch (regs) {
+ case GPREGS_32:
+ get_gp32_regs(vals);
+ break;
+ case GPREGS_32_EBP_ESP:
+ get_gp32_ebp_esp_regs(vals);
+ break;
+ case GPREGS_64:
+ get_gp64_regs(vals);
+ break;
+ case GPREGS_64_R8:
+ get_gp64_r8_regs(vals);
+ break;
+ case FPREGS_MM:
+ get_mm_regs(vals);
+ break;
+ case FPREGS_XMM:
+ get_xmm_regs(vals);
+ break;
+ case FPREGS_YMM:
+ get_ymm_regs(vals);
+ break;
+ }
+
+ DPRINTF("Before comparing results\n");
+ switch (regs) {
+ case GPREGS_32:
+ FORKEE_ASSERT(!memcmp(&vals[5].u32,
+ &expected[5].u32, sizeof(vals->u32)));
+ FORKEE_ASSERT(!memcmp(&vals[4].u32,
+ &expected[4].u32, sizeof(vals->u32)));
+ FORKEE_ASSERT(!memcmp(&vals[3].u32,
+ &expected[3].u32, sizeof(vals->u32)));
+ FORKEE_ASSERT(!memcmp(&vals[2].u32,
+ &expected[2].u32, sizeof(vals->u32)));
+ /*FALLTHROUGH*/
+ case GPREGS_32_EBP_ESP:
+ FORKEE_ASSERT(!memcmp(&vals[1].u32,
+ &expected[1].u32, sizeof(vals->u32)));
+ FORKEE_ASSERT(!memcmp(&vals[0].u32,
+ &expected[0].u32, sizeof(vals->u32)));
+ break;
+ case GPREGS_64:
+ case GPREGS_64_R8:
+ case FPREGS_MM:
+ FORKEE_ASSERT(!memcmp(&vals[0].u64,
+ &expected[0].u64, sizeof(vals->u64)));
+ FORKEE_ASSERT(!memcmp(&vals[1].u64,
+ &expected[1].u64, sizeof(vals->u64)));
+ FORKEE_ASSERT(!memcmp(&vals[2].u64,
+ &expected[2].u64, sizeof(vals->u64)));
+ FORKEE_ASSERT(!memcmp(&vals[3].u64,
+ &expected[3].u64, sizeof(vals->u64)));
+ FORKEE_ASSERT(!memcmp(&vals[4].u64,
+ &expected[4].u64, sizeof(vals->u64)));
+ FORKEE_ASSERT(!memcmp(&vals[5].u64,
+ &expected[5].u64, sizeof(vals->u64)));
+ FORKEE_ASSERT(!memcmp(&vals[6].u64,
+ &expected[6].u64, sizeof(vals->u64)));
+ FORKEE_ASSERT(!memcmp(&vals[7].u64,
+ &expected[7].u64, sizeof(vals->u64)));
+ break;
+ case FPREGS_XMM:
+ FORKEE_ASSERT(!memcmp(&vals[0].xmm,
+ &expected[0].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[1].xmm,
+ &expected[1].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[2].xmm,
+ &expected[2].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[3].xmm,
+ &expected[3].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[4].xmm,
+ &expected[4].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[5].xmm,
+ &expected[5].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[6].xmm,
+ &expected[6].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[7].xmm,
+ &expected[7].xmm, sizeof(vals->xmm)));
+#if defined(__x86_64__)
+ FORKEE_ASSERT(!memcmp(&vals[8].xmm,
+ &expected[8].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[9].xmm,
+ &expected[9].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[10].xmm,
+ &expected[10].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[11].xmm,
+ &expected[11].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[12].xmm,
+ &expected[12].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[13].xmm,
+ &expected[13].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[14].xmm,
+ &expected[14].xmm, sizeof(vals->xmm)));
+ FORKEE_ASSERT(!memcmp(&vals[15].xmm,
+ &expected[15].xmm, sizeof(vals->xmm)));
+#endif
+ break;
+ case FPREGS_YMM:
+ FORKEE_ASSERT(!memcmp(&vals[0].ymm,
+ &expected[0].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[1].ymm,
+ &expected[1].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[2].ymm,
+ &expected[2].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[3].ymm,
+ &expected[3].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[4].ymm,
+ &expected[4].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[5].ymm,
+ &expected[5].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[6].ymm,
+ &expected[6].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[7].ymm,
+ &expected[7].ymm, sizeof(vals->ymm)));
#if defined(__x86_64__)
- FORKEE_ASSERT(!memcmp(&v_ymm[8], &ymm[8], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[9], &ymm[9], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[10], &ymm[10], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[11], &ymm[11], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[12], &ymm[12], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[13], &ymm[13], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[14], &ymm[14], sizeof(*ymm)));
- FORKEE_ASSERT(!memcmp(&v_ymm[15], &ymm[15], sizeof(*ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[8].ymm,
+ &expected[8].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[9].ymm,
+ &expected[9].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[10].ymm,
+ &expected[10].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[11].ymm,
+ &expected[11].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[12].ymm,
+ &expected[12].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[13].ymm,
+ &expected[13].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[14].ymm,
+ &expected[14].ymm, sizeof(vals->ymm)));
+ FORKEE_ASSERT(!memcmp(&vals[15].ymm,
+ &expected[15].ymm, sizeof(vals->ymm)));
#endif
+ break;
+ }
+ break;
+ }
DPRINTF("Before exiting of the child process\n");
_exit(exitval);
@@ -3623,55 +2969,417 @@ ATF_TC_BODY(x86_xstate_ymm_write, tc)
validate_status_stopped(status, sigval);
- iov.iov_base = &xst;
- iov.iov_len = sizeof(xst);
-
- DPRINTF("Call GETXSTATE for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
- ATF_REQUIRE(xst.xs_rfbm & XCR0_SSE);
- ATF_REQUIRE(xst.xs_rfbm & XCR0_YMM_Hi128);
-
- xst.xs_rfbm = XCR0_SSE | XCR0_YMM_Hi128;
- xst.xs_xstate_bv = XCR0_SSE | XCR0_YMM_Hi128;
-
- memcpy(&xst.xs_fxsave.fx_xmm[0], &ymm[0].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[0], &ymm[0].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[1], &ymm[1].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[1], &ymm[1].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[2], &ymm[2].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[2], &ymm[2].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[3], &ymm[3].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[3], &ymm[3].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[4], &ymm[4].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[4], &ymm[4].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[5], &ymm[5].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[5], &ymm[5].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[6], &ymm[6].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[6], &ymm[6].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[7], &ymm[7].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[7], &ymm[7].c, sizeof(*ymm)/2);
+ switch (regset) {
+ case TEST_GPREGS:
+ ATF_REQUIRE(regs < FPREGS_MM);
+ DPRINTF("Call GETREGS for the child process\n");
+ SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
+ break;
+ case TEST_XMMREGS:
+#if defined(__i386__)
+ ATF_REQUIRE(regs >= FPREGS_MM && regs < FPREGS_YMM);
+ DPRINTF("Call GETXMMREGS for the child process\n");
+ SYSCALL_REQUIRE(ptrace(PT_GETXMMREGS, child, &xmm, 0) != -1);
+ fxs = &xmm.fxstate;
+ break;
+#else
+ /*FALLTHROUGH*/
+#endif
+ case TEST_FPREGS:
+#if defined(__x86_64__)
+ ATF_REQUIRE(regs >= FPREGS_MM && regs < FPREGS_YMM);
+ fxs = &fpr.fxstate;
+#else
+ ATF_REQUIRE(regs >= FPREGS_MM && 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);
+ iov.iov_base = &xst;
+ iov.iov_len = sizeof(xst);
+
+ DPRINTF("Call GETXSTATE for the child process\n");
+ SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
+
+ switch (regs) {
+ case FPREGS_MM:
+ xst_flags |= XCR0_X87;
+ break;
+ case FPREGS_YMM:
+ xst_flags |= XCR0_YMM_Hi128;
+ /*FALLTHROUGH*/
+ case FPREGS_XMM:
+ xst_flags |= XCR0_SSE;
+ break;
+ case GPREGS_32:
+ case GPREGS_32_EBP_ESP:
+ case GPREGS_64:
+ case GPREGS_64_R8:
+ __unreachable();
+ break;
+ }
+
+ ATF_REQUIRE((xst.xs_rfbm & xst_flags) == xst_flags);
+ switch (regmode) {
+ case TEST_SETREGS:
+ xst.xs_rfbm = xst_flags;
+ xst.xs_xstate_bv = xst_flags;
+ break;
+ case TEST_GETREGS:
+ ATF_REQUIRE((xst.xs_xstate_bv & xst_flags)
+ == xst_flags);
+ break;
+ }
+
+ fxs = &xst.xs_fxsave;
+ break;
+ }
+
+#if defined(__x86_64__)
+#define MM_REG(n) fpr.fxstate.fx_87_ac[n].r.f87_mantissa
+#else
+#define MM_REG(n) fpr.fstate.s87_ac[n].f87_mantissa
+#endif
+
+ switch (regmode) {
+ case TEST_GETREGS:
+ switch (regs) {
+ case GPREGS_32:
+#if defined(__i386__)
+ ATF_CHECK_EQ((uint32_t)gpr.r_eax, expected[0].u32);
+ ATF_CHECK_EQ((uint32_t)gpr.r_ebx, expected[1].u32);
+ ATF_CHECK_EQ((uint32_t)gpr.r_ecx, expected[2].u32);
+ ATF_CHECK_EQ((uint32_t)gpr.r_edx, expected[3].u32);
+ ATF_CHECK_EQ((uint32_t)gpr.r_esi, expected[4].u32);
+ ATF_CHECK_EQ((uint32_t)gpr.r_edi, expected[5].u32);
+#endif
+ break;
+ case GPREGS_32_EBP_ESP:
+#if defined(__i386__)
+ ATF_CHECK_EQ((uint32_t)gpr.r_esp, expected[0].u32);
+ ATF_CHECK_EQ((uint32_t)gpr.r_ebp, expected[1].u32);
+#endif
+ break;
+ case GPREGS_64:
+#if defined(__x86_64__)
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RAX],
+ expected[0].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBX],
+ expected[1].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RCX],
+ expected[2].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDX],
+ expected[3].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSI],
+ expected[4].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDI],
+ expected[5].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSP],
+ expected[6].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBP],
+ expected[7].u64);
+#endif
+ break;
+ case GPREGS_64_R8:
+#if defined(__x86_64__)
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R8],
+ expected[0].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R9],
+ expected[1].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R10],
+ expected[2].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R11],
+ expected[3].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R12],
+ expected[4].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R13],
+ expected[5].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R14],
+ expected[6].u64);
+ ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R15],
+ expected[7].u64);
+#endif
+ break;
+ case FPREGS_MM:
+ if (regset == TEST_FPREGS) {
+ ATF_CHECK_EQ(MM_REG(0), expected[0].u64);
+ ATF_CHECK_EQ(MM_REG(1), expected[1].u64);
+ ATF_CHECK_EQ(MM_REG(2), expected[2].u64);
+ ATF_CHECK_EQ(MM_REG(3), expected[3].u64);
+ ATF_CHECK_EQ(MM_REG(4), expected[4].u64);
+ ATF_CHECK_EQ(MM_REG(5), expected[5].u64);
+ ATF_CHECK_EQ(MM_REG(6), expected[6].u64);
+ ATF_CHECK_EQ(MM_REG(7), expected[7].u64);
+ } else {
+ ATF_CHECK_EQ(fxs->fx_87_ac[0].r.f87_mantissa,
+ expected[0].u64);
+ ATF_CHECK_EQ(fxs->fx_87_ac[1].r.f87_mantissa,
+ expected[1].u64);
+ ATF_CHECK_EQ(fxs->fx_87_ac[2].r.f87_mantissa,
+ expected[2].u64);
+ ATF_CHECK_EQ(fxs->fx_87_ac[3].r.f87_mantissa,
+ expected[3].u64);
+ ATF_CHECK_EQ(fxs->fx_87_ac[4].r.f87_mantissa,
+ expected[4].u64);
+ ATF_CHECK_EQ(fxs->fx_87_ac[5].r.f87_mantissa,
+ expected[5].u64);
+ ATF_CHECK_EQ(fxs->fx_87_ac[6].r.f87_mantissa,
+ expected[6].u64);
+ ATF_CHECK_EQ(fxs->fx_87_ac[7].r.f87_mantissa,
+ expected[7].u64);
+ }
+ break;
+ case FPREGS_YMM:
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[0],
+ &expected[0].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[1],
+ &expected[1].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[2],
+ &expected[2].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[3],
+ &expected[3].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[4],
+ &expected[4].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[5],
+ &expected[5].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[6],
+ &expected[6].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[7],
+ &expected[7].ymm.c, sizeof(expected->ymm)/2));
+#if defined(__x86_64__)
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[8],
+ &expected[8].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[9],
+ &expected[9].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[10],
+ &expected[10].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[11],
+ &expected[11].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[12],
+ &expected[12].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[13],
+ &expected[13].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[14],
+ &expected[14].ymm.c, sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[15],
+ &expected[15].ymm.c, sizeof(expected->ymm)/2));
+#endif
+ /*FALLTHROUGH*/
+ case FPREGS_XMM:
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[0], &expected[0].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[1], &expected[1].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[2], &expected[2].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[3], &expected[3].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[4], &expected[4].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[5], &expected[5].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[6], &expected[6].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[7], &expected[7].ymm.a,
+ sizeof(expected->ymm)/2));
+#if defined(__x86_64__)
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[8], &expected[8].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[9], &expected[9].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[10], &expected[10].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[11], &expected[11].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[12], &expected[12].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[13], &expected[13].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[14], &expected[14].ymm.a,
+ sizeof(expected->ymm)/2));
+ ATF_CHECK(!memcmp(&fxs->fx_xmm[15], &expected[15].ymm.a,
+ sizeof(expected->ymm)/2));
+#endif
+ break;
+ }
+ break;
+ case TEST_SETREGS:
+ switch (regs) {
+ case GPREGS_32:
+#if defined(__i386__)
+ gpr.r_eax = expected[0].u32;
+ gpr.r_ebx = expected[1].u32;
+ gpr.r_ecx = expected[2].u32;
+ gpr.r_edx = expected[3].u32;
+ gpr.r_esi = expected[4].u32;
+ gpr.r_edi = expected[5].u32;
+#endif
+ break;
+ case GPREGS_32_EBP_ESP:
+#if defined(__i386__)
+ gpr.r_esp = expected[0].u32;
+ gpr.r_ebp = expected[1].u32;
+#endif
+ break;
+ case GPREGS_64:
+#if defined(__x86_64__)
+ gpr.regs[_REG_RAX] = expected[0].u64;
+ gpr.regs[_REG_RBX] = expected[1].u64;
+ gpr.regs[_REG_RCX] = expected[2].u64;
+ gpr.regs[_REG_RDX] = expected[3].u64;
+ gpr.regs[_REG_RSI] = expected[4].u64;
+ gpr.regs[_REG_RDI] = expected[5].u64;
+ gpr.regs[_REG_RSP] = expected[6].u64;
+ gpr.regs[_REG_RBP] = expected[7].u64;
+#endif
+ break;
+ case GPREGS_64_R8:
+#if defined(__x86_64__)
+ gpr.regs[_REG_R8] = expected[0].u64;
+ gpr.regs[_REG_R9] = expected[1].u64;
+ gpr.regs[_REG_R10] = expected[2].u64;
+ gpr.regs[_REG_R11] = expected[3].u64;
+ gpr.regs[_REG_R12] = expected[4].u64;
+ gpr.regs[_REG_R13] = expected[5].u64;
+ gpr.regs[_REG_R14] = expected[6].u64;
+ gpr.regs[_REG_R15] = expected[7].u64;
+#endif
+ break;
+ case FPREGS_MM:
+ if (regset == TEST_FPREGS) {
+ MM_REG(0) = expected[0].u64;
+ MM_REG(1) = expected[1].u64;
+ MM_REG(2) = expected[2].u64;
+ MM_REG(3) = expected[3].u64;
+ MM_REG(4) = expected[4].u64;
+ MM_REG(5) = expected[5].u64;
+ MM_REG(6) = expected[6].u64;
+ MM_REG(7) = expected[7].u64;
+ } else {
+ fxs->fx_87_ac[0].r.f87_mantissa =
+ expected[0].u64;
+ fxs->fx_87_ac[1].r.f87_mantissa =
+ expected[1].u64;
+ fxs->fx_87_ac[2].r.f87_mantissa =
+ expected[2].u64;
+ fxs->fx_87_ac[3].r.f87_mantissa =
+ expected[3].u64;
+ fxs->fx_87_ac[4].r.f87_mantissa =
+ expected[4].u64;
+ fxs->fx_87_ac[5].r.f87_mantissa =
+ expected[5].u64;
+ fxs->fx_87_ac[6].r.f87_mantissa =
+ expected[6].u64;
+ fxs->fx_87_ac[7].r.f87_mantissa =
+ expected[7].u64;
+ }
+ break;
+ case FPREGS_YMM:
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[0],
+ &expected[0].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[1],
+ &expected[1].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[2],
+ &expected[2].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[3],
+ &expected[3].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[4],
+ &expected[4].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[5],
+ &expected[5].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[6],
+ &expected[6].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[7],
+ &expected[7].ymm.c, sizeof(expected->ymm)/2);
+#if defined(__x86_64__)
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[8],
+ &expected[8].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[9],
+ &expected[9].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[10],
+ &expected[10].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[11],
+ &expected[11].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[12],
+ &expected[12].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[13],
+ &expected[13].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[14],
+ &expected[14].ymm.c, sizeof(expected->ymm)/2);
+ memcpy(&xst.xs_ymm_hi128.xs_ymm[15],
+ &expected[15].ymm.c, sizeof(expected->ymm)/2);
+#endif
+ /*FALLTHROUGH*/
+ case FPREGS_XMM:
+ memcpy(&fxs->fx_xmm[0], &expected[0].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[1], &expected[1].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[2], &expected[2].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[3], &expected[3].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[4], &expected[4].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[5], &expected[5].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[6], &expected[6].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[7], &expected[7].ymm.a,
+ sizeof(expected->ymm)/2);
#if defined(__x86_64__)
- memcpy(&xst.xs_fxsave.fx_xmm[8], &ymm[8].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[8], &ymm[8].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[9], &ymm[9].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[9], &ymm[9].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[10], &ymm[10].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[10], &ymm[10].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[11], &ymm[11].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[11], &ymm[11].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[12], &ymm[12].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[12], &ymm[12].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[13], &ymm[13].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[13], &ymm[13].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[14], &ymm[14].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[14], &ymm[14].c, sizeof(*ymm)/2);
- memcpy(&xst.xs_fxsave.fx_xmm[15], &ymm[15].a, sizeof(*ymm)/2);
- memcpy(&xst.xs_ymm_hi128.xs_ymm[15], &ymm[15].c, sizeof(*ymm)/2);
+ memcpy(&fxs->fx_xmm[8], &expected[8].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[9], &expected[9].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[10], &expected[10].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[11], &expected[11].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[12], &expected[12].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[13], &expected[13].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[14], &expected[14].ymm.a,
+ sizeof(expected->ymm)/2);
+ memcpy(&fxs->fx_xmm[15], &expected[15].ymm.a,
+ sizeof(expected->ymm)/2);
+#endif
+ break;
+ }
+
+ switch (regset) {
+ case TEST_GPREGS:
+ DPRINTF("Call SETREGS for the child process\n");
+ SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0)
+ != -1);
+ break;
+ case TEST_XMMREGS:
+#if defined(__i386__)
+ DPRINTF("Call SETXMMREGS for the child process\n");
+ SYSCALL_REQUIRE(ptrace(PT_SETXMMREGS, child, &xmm, 0)
+ != -1);
+ break;
+#else
+ /*FALLTHROUGH*/
#endif
+ case TEST_FPREGS:
+ DPRINTF("Call SETFPREGS for the child process\n");
+ SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &fpr, 0)
+ != -1);
+ break;
+ case TEST_XSTATE:
+ DPRINTF("Call SETXSTATE for the child process\n");
+ SYSCALL_REQUIRE(ptrace(PT_SETXSTATE, child, &iov, 0)
+ != -1);
+ break;
+ }
+ break;
+ }
- DPRINTF("Call SETXSTATE for the child process\n");
- SYSCALL_REQUIRE(ptrace(PT_SETXSTATE, child, &iov, 0) != -1);
+#undef MM_REG
DPRINTF("Before resuming the child process where it left off and "
"without signal to be sent\n");
@@ -3686,6 +3394,75 @@ ATF_TC_BODY(x86_xstate_ymm_write, tc)
TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
}
+#define X86_REGISTER_TEST(test, regset, regs, regmode, descr) \
+ATF_TC(test); \
+ATF_TC_HEAD(test, tc) \
+{ \
+ atf_tc_set_md_var(tc, "descr", descr); \
+} \
+ \
+ATF_TC_BODY(test, tc) \
+{ \
+ x86_register_test(regset, regs, regmode); \
+}
+
+X86_REGISTER_TEST(x86_gpregs32_read, TEST_GPREGS, GPREGS_32, TEST_GETREGS,
+ "Test reading basic 32-bit gp registers from debugged program "
+ "via PT_GETREGS.");
+X86_REGISTER_TEST(x86_gpregs32_write, TEST_GPREGS, GPREGS_32, TEST_SETREGS,
+ "Test writing basic 32-bit gp registers into debugged program "
+ "via PT_SETREGS.");
+X86_REGISTER_TEST(x86_gpregs32_ebp_esp_read, TEST_GPREGS, GPREGS_32_EBP_ESP,
+ TEST_GETREGS, "Test reading ebp & esp registers from debugged program "
+ "via PT_GETREGS.");
+X86_REGISTER_TEST(x86_gpregs32_ebp_esp_write, TEST_GPREGS, GPREGS_32_EBP_ESP,
+ TEST_SETREGS, "Test writing ebp & esp registers into debugged program "
+ "via PT_SETREGS.");
+
+X86_REGISTER_TEST(x86_gpregs64_read, TEST_GPREGS, GPREGS_64, TEST_GETREGS,
+ "Test reading basic 64-bit gp registers from debugged program "
+ "via PT_GETREGS.");
+X86_REGISTER_TEST(x86_gpregs64_write, TEST_GPREGS, GPREGS_64, TEST_SETREGS,
+ "Test writing basic 64-bit gp registers into debugged program "
+ "via PT_SETREGS.");
+X86_REGISTER_TEST(x86_gpregs64_r8_read, TEST_GPREGS, GPREGS_64_R8, TEST_GETREGS,
+ "Test reading r8..r15 registers from debugged program via PT_GETREGS.");
+X86_REGISTER_TEST(x86_gpregs64_r8_write, TEST_GPREGS, GPREGS_64_R8,
+ TEST_SETREGS, "Test writing r8..r15 registers into debugged program "
+ "via PT_SETREGS.");
+
+X86_REGISTER_TEST(x86_fpregs_mm_read, TEST_FPREGS, FPREGS_MM, TEST_GETREGS,
+ "Test reading mm0..mm7 registers from debugged program "
+ "via PT_GETFPREGS.");
+X86_REGISTER_TEST(x86_fpregs_mm_write, TEST_FPREGS, FPREGS_MM, TEST_SETREGS,
+ "Test writing mm0..mm7 registers into debugged program "
+ "via PT_SETFPREGS.");
+X86_REGISTER_TEST(x86_fpregs_xmm_read, TEST_XMMREGS, FPREGS_XMM, TEST_GETREGS,
+ "Test reading xmm0..xmm15 (..xmm7 on i386) from debugged program "
+ "via PT_GETFPREGS (PT_GETXMMREGS on i386).");
+X86_REGISTER_TEST(x86_fpregs_xmm_write, TEST_XMMREGS, FPREGS_XMM, TEST_SETREGS,
+ "Test writing xmm0..xmm15 (..xmm7 on i386) into debugged program "
+ "via PT_SETFPREGS (PT_SETXMMREGS on i386).");
+
+X86_REGISTER_TEST(x86_xstate_mm_read, TEST_XSTATE, FPREGS_MM, TEST_GETREGS,
+ "Test reading mm0..mm7 registers from debugged program "
+ "via PT_GETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_mm_write, TEST_XSTATE, FPREGS_MM, TEST_SETREGS,
+ "Test writing mm0..mm7 registers into debugged program "
+ "via PT_SETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_xmm_read, TEST_XSTATE, FPREGS_XMM, TEST_GETREGS,
+ "Test reading xmm0..xmm15 (..xmm7 on i386) from debugged program "
+ "via PT_GETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_xmm_write, TEST_XSTATE, FPREGS_XMM, TEST_SETREGS,
+ "Test writing xmm0..xmm15 (..xmm7 on i386) into debugged program "
+ "via PT_SETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_ymm_read, TEST_XSTATE, FPREGS_YMM, TEST_GETREGS,
+ "Test reading ymm0..ymm15 (..ymm7 on i386) from debugged program "
+ "via PT_GETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_ymm_write, TEST_XSTATE, FPREGS_YMM, TEST_SETREGS,
+ "Test writing ymm0..ymm15 (..ymm7 on i386) into debugged program "
+ "via PT_SETXSTATE.");
+
/// ----------------------------------------------------------------------------
#define ATF_TP_ADD_TCS_PTRACE_WAIT_X86() \
@@ -3751,10 +3528,18 @@ ATF_TC_BODY(x86_xstate_ymm_write, tc)
ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_dont_inherit_execve); \
ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_dont_inherit_execve); \
ATF_TP_ADD_TC_HAVE_DBREGS(tp, x86_cve_2018_8897); \
- ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_mm_read); \
- ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_mm_write); \
- ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_xmm_read); \
- ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_xmm_write); \
+ ATF_TP_ADD_TC(tp, x86_gpregs32_read); \
+ ATF_TP_ADD_TC(tp, x86_gpregs32_write); \
+ ATF_TP_ADD_TC(tp, x86_gpregs32_ebp_esp_read); \
+ ATF_TP_ADD_TC(tp, x86_gpregs32_ebp_esp_write); \
+ ATF_TP_ADD_TC(tp, x86_gpregs64_read); \
+ ATF_TP_ADD_TC(tp, x86_gpregs64_write); \
+ ATF_TP_ADD_TC(tp, x86_gpregs64_r8_read); \
+ ATF_TP_ADD_TC(tp, x86_gpregs64_r8_write); \
+ 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_xmm_read); \
+ ATF_TP_ADD_TC(tp, x86_fpregs_xmm_write); \
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_xmm_read); \
--
2.22.0
Home |
Main Index |
Thread Index |
Old Index