1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Ptrace test for VMX/VSX registers |
4 | * |
5 | * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. |
6 | */ |
7 | #include "ptrace.h" |
8 | #include "ptrace-vsx.h" |
9 | |
10 | /* Tracer and Tracee Shared Data */ |
11 | int shm_id; |
12 | int *cptr, *pptr; |
13 | |
14 | unsigned long fp_load[VEC_MAX]; |
15 | unsigned long fp_load_new[VEC_MAX]; |
16 | unsigned long fp_store[VEC_MAX]; |
17 | |
18 | void vsx(void) |
19 | { |
20 | int ret; |
21 | |
22 | cptr = (int *)shmat(shm_id, NULL, 0); |
23 | loadvsx(p: fp_load, tmp: 0); |
24 | cptr[1] = 1; |
25 | |
26 | while (!cptr[0]) |
27 | asm volatile("" : : : "memory" ); |
28 | shmdt((void *) cptr); |
29 | |
30 | storevsx(p: fp_store, tmp: 0); |
31 | ret = compare_vsx_vmx(store: fp_store, load: fp_load_new); |
32 | if (ret) |
33 | exit(1); |
34 | exit(0); |
35 | } |
36 | |
37 | int trace_vsx(pid_t child) |
38 | { |
39 | unsigned long vsx[VSX_MAX]; |
40 | unsigned long vmx[VMX_MAX + 2][2]; |
41 | |
42 | FAIL_IF(start_trace(child)); |
43 | FAIL_IF(show_vsx(child, vsx)); |
44 | FAIL_IF(validate_vsx(vsx, load: fp_load)); |
45 | FAIL_IF(show_vmx(child, vmx)); |
46 | FAIL_IF(validate_vmx(vmx, load: fp_load)); |
47 | |
48 | memset(vsx, 0, sizeof(vsx)); |
49 | memset(vmx, 0, sizeof(vmx)); |
50 | load_vsx_vmx(load: fp_load_new, vsx, vmx); |
51 | |
52 | FAIL_IF(write_vsx(child, vsx)); |
53 | FAIL_IF(write_vmx(child, vmx)); |
54 | FAIL_IF(stop_trace(child)); |
55 | |
56 | return TEST_PASS; |
57 | } |
58 | |
59 | int ptrace_vsx(void) |
60 | { |
61 | pid_t pid; |
62 | int ret, status, i; |
63 | |
64 | SKIP_IF_MSG(!have_hwcap(PPC_FEATURE_HAS_VSX), "Don't have VSX" ); |
65 | |
66 | shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); |
67 | |
68 | for (i = 0; i < VEC_MAX; i++) |
69 | fp_load[i] = i + rand(); |
70 | |
71 | for (i = 0; i < VEC_MAX; i++) |
72 | fp_load_new[i] = i + 2 * rand(); |
73 | |
74 | pid = fork(); |
75 | if (pid < 0) { |
76 | perror("fork() failed" ); |
77 | return TEST_FAIL; |
78 | } |
79 | |
80 | if (pid == 0) |
81 | vsx(); |
82 | |
83 | if (pid) { |
84 | pptr = (int *)shmat(shm_id, NULL, 0); |
85 | while (!pptr[1]) |
86 | asm volatile("" : : : "memory" ); |
87 | |
88 | ret = trace_vsx(child: pid); |
89 | if (ret) { |
90 | kill(pid, SIGTERM); |
91 | shmdt((void *)pptr); |
92 | shmctl(shm_id, IPC_RMID, NULL); |
93 | return TEST_FAIL; |
94 | } |
95 | |
96 | pptr[0] = 1; |
97 | shmdt((void *)pptr); |
98 | |
99 | ret = wait(&status); |
100 | shmctl(shm_id, IPC_RMID, NULL); |
101 | if (ret != pid) { |
102 | printf("Child's exit status not captured\n" ); |
103 | return TEST_FAIL; |
104 | } |
105 | |
106 | return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : |
107 | TEST_PASS; |
108 | } |
109 | return TEST_PASS; |
110 | } |
111 | |
112 | int main(int argc, char *argv[]) |
113 | { |
114 | return test_harness(ptrace_vsx, "ptrace_vsx" ); |
115 | } |
116 | |