selftests/powerpc: Add ptrace tests for VSX, VMX registers
authorAnshuman Khandual <khandual@linux.vnet.ibm.com>
Fri, 30 Sep 2016 02:32:59 +0000 (10:32 +0800)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 17 Nov 2016 06:11:51 +0000 (17:11 +1100)
This patch adds ptrace interface test for VSX, VMX registers.
This also adds ptrace interface based helper functions related
to VSX, VMX registers access. This also adds some assembly
helper functions related to VSX and VMX registers.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Signed-off-by: Simon Guo <wei.guo.simon@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
tools/testing/selftests/powerpc/lib/reg.S
tools/testing/selftests/powerpc/ptrace/.gitignore
tools/testing/selftests/powerpc/ptrace/Makefile
tools/testing/selftests/powerpc/ptrace/ptrace-vsx.c [new file with mode: 0644]
tools/testing/selftests/powerpc/ptrace/ptrace-vsx.h [new file with mode: 0644]
tools/testing/selftests/powerpc/ptrace/ptrace.h

index b6aee2f79454b80ec0bff14726fdefa110a798b7..0dc44f0da065191b71fd886a25c15c574fbbeed8 100644 (file)
@@ -130,3 +130,268 @@ FUNC_START(store_fpr_single_precision)
        stfs 31, 31*4(3)
        blr
 FUNC_END(store_fpr_single_precision)
+
+/* VMX/VSX registers - unsigned long buf[128] */
+FUNC_START(loadvsx)
+       lis     4, 0
+       LXVD2X  (0,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (1,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (2,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (3,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (4,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (5,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (6,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (7,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (8,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (9,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (10,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (11,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (12,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (13,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (14,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (15,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (16,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (17,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (18,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (19,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (20,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (21,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (22,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (23,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (24,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (25,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (26,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (27,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (28,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (29,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (30,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (31,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (32,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (33,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (34,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (35,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (36,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (37,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (38,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (39,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (40,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (41,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (42,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (43,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (44,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (45,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (46,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (47,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (48,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (49,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (50,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (51,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (52,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (53,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (54,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (55,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (56,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (57,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (58,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (59,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (60,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (61,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (62,(4),(3))
+       addi    4, 4, 16
+       LXVD2X  (63,(4),(3))
+       blr
+FUNC_END(loadvsx)
+
+FUNC_START(storevsx)
+       lis     4, 0
+       STXVD2X (0,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (1,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (2,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (3,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (4,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (5,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (6,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (7,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (8,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (9,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (10,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (11,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (12,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (13,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (14,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (15,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (16,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (17,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (18,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (19,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (20,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (21,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (22,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (23,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (24,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (25,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (26,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (27,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (28,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (29,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (30,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (31,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (32,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (33,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (34,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (35,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (36,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (37,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (38,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (39,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (40,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (41,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (42,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (43,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (44,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (45,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (46,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (47,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (48,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (49,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (50,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (51,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (52,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (53,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (54,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (55,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (56,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (57,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (58,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (59,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (60,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (61,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (62,(4),(3))
+       addi    4, 4, 16
+       STXVD2X (63,(4),(3))
+       blr
+FUNC_END(storevsx)
index 7b3383a2fc305c6a3874d4bc88070fe0eb3a6f88..720c002859d808455b061ad45d3e27d617e9d9fd 100644 (file)
@@ -4,3 +4,4 @@ ptrace-tm-spd-gpr
 ptrace-tar
 ptrace-tm-tar
 ptrace-tm-spd-tar
+ptrace-vsx
index 66accb29ea1944a17528c7a64fe4cf1c1309d0ed..18790ff44588f1b256ed1d3876d5e28dc0ece572 100644 (file)
@@ -1,5 +1,5 @@
 TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \
-              ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar
+              ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx
 
 include ../../lib.mk
 
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.c b/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.c
new file mode 100644 (file)
index 0000000..04084ee
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Ptrace test for VMX/VSX registers
+ *
+ * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include "ptrace.h"
+#include "ptrace-vsx.h"
+
+/* Tracer and Tracee Shared Data */
+int shm_id;
+int *cptr, *pptr;
+
+unsigned long fp_load[VEC_MAX];
+unsigned long fp_load_new[VEC_MAX];
+unsigned long fp_store[VEC_MAX];
+
+void vsx(void)
+{
+       int ret;
+
+       cptr = (int *)shmat(shm_id, NULL, 0);
+       loadvsx(fp_load, 0);
+       cptr[1] = 1;
+
+       while (!cptr[0])
+               asm volatile("" : : : "memory");
+       shmdt((void *) cptr);
+
+       storevsx(fp_store, 0);
+       ret = compare_vsx_vmx(fp_store, fp_load_new);
+       if (ret)
+               exit(1);
+       exit(0);
+}
+
+int trace_vsx(pid_t child)
+{
+       unsigned long vsx[VSX_MAX];
+       unsigned long vmx[VMX_MAX + 2][2];
+
+       FAIL_IF(start_trace(child));
+       FAIL_IF(show_vsx(child, vsx));
+       FAIL_IF(validate_vsx(vsx, fp_load));
+       FAIL_IF(show_vmx(child, vmx));
+       FAIL_IF(validate_vmx(vmx, fp_load));
+
+       memset(vsx, 0, sizeof(vsx));
+       memset(vmx, 0, sizeof(vmx));
+       load_vsx_vmx(fp_load_new, vsx, vmx);
+
+       FAIL_IF(write_vsx(child, vsx));
+       FAIL_IF(write_vmx(child, vmx));
+       FAIL_IF(stop_trace(child));
+
+       return TEST_PASS;
+}
+
+int ptrace_vsx(void)
+{
+       pid_t pid;
+       int ret, status, i;
+
+       shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
+
+       for (i = 0; i < VEC_MAX; i++)
+               fp_load[i] = i + rand();
+
+       for (i = 0; i < VEC_MAX; i++)
+               fp_load_new[i] = i + 2 * rand();
+
+       pid = fork();
+       if (pid < 0) {
+               perror("fork() failed");
+               return TEST_FAIL;
+       }
+
+       if (pid == 0)
+               vsx();
+
+       if (pid) {
+               pptr = (int *)shmat(shm_id, NULL, 0);
+               while (!pptr[1])
+                       asm volatile("" : : : "memory");
+
+               ret = trace_vsx(pid);
+               if (ret) {
+                       kill(pid, SIGTERM);
+                       shmdt((void *)pptr);
+                       shmctl(shm_id, IPC_RMID, NULL);
+                       return TEST_FAIL;
+               }
+
+               pptr[0] = 1;
+               shmdt((void *)pptr);
+
+               ret = wait(&status);
+               shmctl(shm_id, IPC_RMID, NULL);
+               if (ret != pid) {
+                       printf("Child's exit status not captured\n");
+                       return TEST_FAIL;
+               }
+
+               return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
+                       TEST_PASS;
+       }
+       return TEST_PASS;
+}
+
+int main(int argc, char *argv[])
+{
+       return test_harness(ptrace_vsx, "ptrace_vsx");
+}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.h b/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.h
new file mode 100644 (file)
index 0000000..f4e4b42
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#define VEC_MAX 128
+#define VSX_MAX 32
+#define VMX_MAX 32
+
+/*
+ * unsigned long vsx[32]
+ * unsigned long load[128]
+ */
+int validate_vsx(unsigned long *vsx, unsigned long *load)
+{
+       int i;
+
+       for (i = 0; i < VSX_MAX; i++) {
+               if (vsx[i] != load[2 * i + 1]) {
+                       printf("vsx[%d]: %lx load[%d] %lx\n",
+                                       i, vsx[i], 2 * i + 1, load[2 * i + 1]);
+                       return TEST_FAIL;
+               }
+       }
+       return TEST_PASS;
+}
+
+/*
+ * unsigned long vmx[32][2]
+ * unsigned long load[128]
+ */
+int validate_vmx(unsigned long vmx[][2], unsigned long *load)
+{
+       int i;
+
+       for (i = 0; i < VMX_MAX; i++) {
+               #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+               if ((vmx[i][0] != load[64 + 2 * i]) ||
+                               (vmx[i][1] != load[65 + 2 * i])) {
+                       printf("vmx[%d][0]: %lx load[%d] %lx\n",
+                                       i, vmx[i][0], 64 + 2 * i,
+                                       load[64 + 2 * i]);
+                       printf("vmx[%d][1]: %lx load[%d] %lx\n",
+                                       i, vmx[i][1], 65 + 2 * i,
+                                       load[65 + 2 * i]);
+                       return TEST_FAIL;
+               }
+               #else  /*
+                       * In LE each value pair is stored in an
+                       * alternate manner.
+                       */
+               if ((vmx[i][0] != load[65 + 2 * i]) ||
+                               (vmx[i][1] != load[64 + 2 * i])) {
+                       printf("vmx[%d][0]: %lx load[%d] %lx\n",
+                                       i, vmx[i][0], 65 + 2 * i,
+                                       load[65 + 2 * i]);
+                       printf("vmx[%d][1]: %lx load[%d] %lx\n",
+                                       i, vmx[i][1], 64 + 2 * i,
+                                       load[64 + 2 * i]);
+                       return TEST_FAIL;
+               }
+               #endif
+       }
+       return TEST_PASS;
+}
+
+/*
+ * unsigned long store[128]
+ * unsigned long load[128]
+ */
+int compare_vsx_vmx(unsigned long *store, unsigned long *load)
+{
+       int i;
+
+       for (i = 0; i < VSX_MAX; i++) {
+               if (store[1 + 2 * i] != load[1 + 2 * i]) {
+                       printf("store[%d]: %lx load[%d] %lx\n",
+                                       1 + 2 * i, store[i],
+                                       1 + 2 * i, load[i]);
+                       return TEST_FAIL;
+               }
+       }
+
+       #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+       for (i = 64; i < VEC_MAX; i++) {
+               if (store[i] != load[i]) {
+                       printf("store[%d]: %lx load[%d] %lx\n",
+                                       i, store[i], i, load[i]);
+                       return TEST_FAIL;
+               }
+       }
+       #else   /* In LE each value pair is stored in an alternate manner */
+       for (i = 64; i < VEC_MAX; i++) {
+               if (!(i % 2) && (store[i] != load[i+1])) {
+                       printf("store[%d]: %lx load[%d] %lx\n",
+                                       i, store[i], i+1, load[i+1]);
+                       return TEST_FAIL;
+               }
+               if ((i % 2) && (store[i] != load[i-1])) {
+                       printf("here store[%d]: %lx load[%d] %lx\n",
+                                       i, store[i], i-1, load[i-1]);
+                       return TEST_FAIL;
+               }
+       }
+       #endif
+       return TEST_PASS;
+}
+
+void load_vsx_vmx(unsigned long *load, unsigned long *vsx,
+               unsigned long vmx[][2])
+{
+       int i;
+
+       for (i = 0; i < VSX_MAX; i++)
+               vsx[i] = load[1 + 2 * i];
+
+       for (i = 0; i < VMX_MAX; i++) {
+               vmx[i][0] = load[64 + 2 * i];
+               vmx[i][1] = load[65 + 2 * i];
+       }
+}
+
+void loadvsx(void *p, int tmp);
+void storevsx(void *p, int tmp);
index fee71b8c1e750af63025cf442c5e7a4494936fad..9aa0498ac738403b713a8a336a7c56bacdbb6f0e 100644 (file)
@@ -486,6 +486,125 @@ int write_ckpt_gpr(pid_t child, unsigned long val)
        return TEST_PASS;
 }
 
+/* VMX */
+int show_vmx(pid_t child, unsigned long vmx[][2])
+{
+       int ret;
+
+       ret = ptrace(PTRACE_GETVRREGS, child, 0, vmx);
+       if (ret) {
+               perror("ptrace(PTRACE_GETVRREGS) failed");
+               return TEST_FAIL;
+       }
+       return TEST_PASS;
+}
+
+int show_vmx_ckpt(pid_t child, unsigned long vmx[][2])
+{
+       unsigned long regs[34][2];
+       struct iovec iov;
+       int ret;
+
+       iov.iov_base = (u64 *) regs;
+       iov.iov_len = sizeof(regs);
+       ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVMX, &iov);
+       if (ret) {
+               perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVMX) failed");
+               return TEST_FAIL;
+       }
+       memcpy(vmx, regs, sizeof(regs));
+       return TEST_PASS;
+}
+
+
+int write_vmx(pid_t child, unsigned long vmx[][2])
+{
+       int ret;
+
+       ret = ptrace(PTRACE_SETVRREGS, child, 0, vmx);
+       if (ret) {
+               perror("ptrace(PTRACE_SETVRREGS) failed");
+               return TEST_FAIL;
+       }
+       return TEST_PASS;
+}
+
+int write_vmx_ckpt(pid_t child, unsigned long vmx[][2])
+{
+       unsigned long regs[34][2];
+       struct iovec iov;
+       int ret;
+
+       memcpy(regs, vmx, sizeof(regs));
+       iov.iov_base = (u64 *) regs;
+       iov.iov_len = sizeof(regs);
+       ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVMX, &iov);
+       if (ret) {
+               perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVMX) failed");
+               return TEST_FAIL;
+       }
+       return TEST_PASS;
+}
+
+/* VSX */
+int show_vsx(pid_t child, unsigned long *vsx)
+{
+       int ret;
+
+       ret = ptrace(PTRACE_GETVSRREGS, child, 0, vsx);
+       if (ret) {
+               perror("ptrace(PTRACE_GETVSRREGS) failed");
+               return TEST_FAIL;
+       }
+       return TEST_PASS;
+}
+
+int show_vsx_ckpt(pid_t child, unsigned long *vsx)
+{
+       unsigned long regs[32];
+       struct iovec iov;
+       int ret;
+
+       iov.iov_base = (u64 *) regs;
+       iov.iov_len = sizeof(regs);
+       ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVSX, &iov);
+       if (ret) {
+               perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVSX) failed");
+               return TEST_FAIL;
+       }
+       memcpy(vsx, regs, sizeof(regs));
+       return TEST_PASS;
+}
+
+int write_vsx(pid_t child, unsigned long *vsx)
+{
+       int ret;
+
+       ret = ptrace(PTRACE_SETVSRREGS, child, 0, vsx);
+       if (ret) {
+               perror("ptrace(PTRACE_SETVSRREGS) failed");
+               return TEST_FAIL;
+       }
+       return TEST_PASS;
+}
+
+int write_vsx_ckpt(pid_t child, unsigned long *vsx)
+{
+       unsigned long regs[32];
+       struct iovec iov;
+       int ret;
+
+       memcpy(regs, vsx, sizeof(regs));
+       iov.iov_base = (u64 *) regs;
+       iov.iov_len = sizeof(regs);
+       ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVSX, &iov);
+       if (ret) {
+               perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVSX) failed");
+               return TEST_FAIL;
+       }
+       return TEST_PASS;
+}
+
 /* Analyse TEXASR after TM failure */
 inline unsigned long get_tfiar(void)
 {