Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/powerpc: Add ptrace tests for VSX, VMX registers in suspended TM

This patch adds ptrace interface test for VSX, VMX registers
inside suspended TM context.

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>

authored by

Anshuman Khandual and committed by
Michael Ellerman
a18b55bf 11508074

+188 -1
+1
tools/testing/selftests/powerpc/ptrace/.gitignore
··· 6 6 ptrace-tm-spd-tar 7 7 ptrace-vsx 8 8 ptrace-tm-vsx 9 + ptrace-tm-spd-vsx
+2 -1
tools/testing/selftests/powerpc/ptrace/Makefile
··· 1 1 TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ 2 - ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx 2 + ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ 3 + ptrace-tm-spd-vsx 3 4 4 5 include ../../lib.mk 5 6
+185
tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c
··· 1 + /* 2 + * Ptrace test for VMX/VSX registers in the TM Suspend context 3 + * 4 + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; either version 9 + * 2 of the License, or (at your option) any later version. 10 + */ 11 + #include "ptrace.h" 12 + #include "tm.h" 13 + #include "ptrace-vsx.h" 14 + 15 + int shm_id; 16 + int *cptr, *pptr; 17 + 18 + unsigned long fp_load[VEC_MAX]; 19 + unsigned long fp_load_new[VEC_MAX]; 20 + unsigned long fp_store[VEC_MAX]; 21 + unsigned long fp_load_ckpt[VEC_MAX]; 22 + unsigned long fp_load_ckpt_new[VEC_MAX]; 23 + 24 + __attribute__((used)) void load_vsx(void) 25 + { 26 + loadvsx(fp_load, 0); 27 + } 28 + 29 + __attribute__((used)) void load_vsx_new(void) 30 + { 31 + loadvsx(fp_load_new, 0); 32 + } 33 + 34 + __attribute__((used)) void load_vsx_ckpt(void) 35 + { 36 + loadvsx(fp_load_ckpt, 0); 37 + } 38 + 39 + __attribute__((used)) void wait_parent(void) 40 + { 41 + cptr[2] = 1; 42 + while (!cptr[1]) 43 + asm volatile("" : : : "memory"); 44 + } 45 + 46 + void tm_spd_vsx(void) 47 + { 48 + unsigned long result, texasr; 49 + int ret; 50 + 51 + cptr = (int *)shmat(shm_id, NULL, 0); 52 + 53 + trans: 54 + cptr[2] = 0; 55 + asm __volatile__( 56 + "bl load_vsx_ckpt;" 57 + 58 + "1: ;" 59 + "tbegin.;" 60 + "beq 2f;" 61 + 62 + "bl load_vsx_new;" 63 + "tsuspend.;" 64 + "bl load_vsx;" 65 + "bl wait_parent;" 66 + "tresume.;" 67 + 68 + "tend.;" 69 + "li 0, 0;" 70 + "ori %[res], 0, 0;" 71 + "b 3f;" 72 + 73 + "2: ;" 74 + "li 0, 1;" 75 + "ori %[res], 0, 0;" 76 + "mfspr %[texasr], %[sprn_texasr];" 77 + 78 + "3: ;" 79 + : [res] "=r" (result), [texasr] "=r" (texasr) 80 + : [fp_load] "r" (fp_load), [fp_load_ckpt] "r" (fp_load_ckpt), 81 + [sprn_texasr] "i" (SPRN_TEXASR) 82 + : "memory", "r0", "r1", "r2", "r3", "r4", 83 + "r8", "r9", "r10", "r11" 84 + ); 85 + 86 + if (result) { 87 + if (!cptr[0]) 88 + goto trans; 89 + shmdt((void *)cptr); 90 + 91 + storevsx(fp_store, 0); 92 + ret = compare_vsx_vmx(fp_store, fp_load_ckpt_new); 93 + if (ret) 94 + exit(1); 95 + exit(0); 96 + } 97 + shmdt((void *)cptr); 98 + exit(1); 99 + } 100 + 101 + int trace_tm_spd_vsx(pid_t child) 102 + { 103 + unsigned long vsx[VSX_MAX]; 104 + unsigned long vmx[VMX_MAX + 2][2]; 105 + 106 + FAIL_IF(start_trace(child)); 107 + FAIL_IF(show_vsx(child, vsx)); 108 + FAIL_IF(validate_vsx(vsx, fp_load)); 109 + FAIL_IF(show_vmx(child, vmx)); 110 + FAIL_IF(validate_vmx(vmx, fp_load)); 111 + FAIL_IF(show_vsx_ckpt(child, vsx)); 112 + FAIL_IF(validate_vsx(vsx, fp_load_ckpt)); 113 + FAIL_IF(show_vmx_ckpt(child, vmx)); 114 + FAIL_IF(validate_vmx(vmx, fp_load_ckpt)); 115 + 116 + memset(vsx, 0, sizeof(vsx)); 117 + memset(vmx, 0, sizeof(vmx)); 118 + 119 + load_vsx_vmx(fp_load_ckpt_new, vsx, vmx); 120 + 121 + FAIL_IF(write_vsx_ckpt(child, vsx)); 122 + FAIL_IF(write_vmx_ckpt(child, vmx)); 123 + 124 + pptr[0] = 1; 125 + pptr[1] = 1; 126 + FAIL_IF(stop_trace(child)); 127 + 128 + return TEST_PASS; 129 + } 130 + 131 + int ptrace_tm_spd_vsx(void) 132 + { 133 + pid_t pid; 134 + int ret, status, i; 135 + 136 + SKIP_IF(!have_htm()); 137 + shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); 138 + 139 + for (i = 0; i < 128; i++) { 140 + fp_load[i] = 1 + rand(); 141 + fp_load_new[i] = 1 + 2 * rand(); 142 + fp_load_ckpt[i] = 1 + 3 * rand(); 143 + fp_load_ckpt_new[i] = 1 + 4 * rand(); 144 + } 145 + 146 + pid = fork(); 147 + if (pid < 0) { 148 + perror("fork() failed"); 149 + return TEST_FAIL; 150 + } 151 + 152 + if (pid == 0) 153 + tm_spd_vsx(); 154 + 155 + if (pid) { 156 + pptr = (int *)shmat(shm_id, NULL, 0); 157 + while (!pptr[2]) 158 + asm volatile("" : : : "memory"); 159 + 160 + ret = trace_tm_spd_vsx(pid); 161 + if (ret) { 162 + kill(pid, SIGKILL); 163 + shmdt((void *)pptr); 164 + shmctl(shm_id, IPC_RMID, NULL); 165 + return TEST_FAIL; 166 + } 167 + 168 + shmdt((void *)pptr); 169 + ret = wait(&status); 170 + shmctl(shm_id, IPC_RMID, NULL); 171 + if (ret != pid) { 172 + printf("Child's exit status not captured\n"); 173 + return TEST_FAIL; 174 + } 175 + 176 + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : 177 + TEST_PASS; 178 + } 179 + return TEST_PASS; 180 + } 181 + 182 + int main(int argc, char *argv[]) 183 + { 184 + return test_harness(ptrace_tm_spd_vsx, "ptrace_tm_spd_vsx"); 185 + }