1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Ptrace test for TAR, PPR, DSCR registers |
4 | * |
5 | * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. |
6 | */ |
7 | #include "ptrace.h" |
8 | #include "ptrace-tar.h" |
9 | |
10 | /* Tracer and Tracee Shared Data */ |
11 | int shm_id; |
12 | int *cptr; |
13 | int *pptr; |
14 | |
15 | void tar(void) |
16 | { |
17 | unsigned long reg[3]; |
18 | int ret; |
19 | |
20 | cptr = (int *)shmat(shm_id, NULL, 0); |
21 | printf("%-30s TAR: %u PPR: %lx DSCR: %u\n" , |
22 | user_write, TAR_1, PPR_1, DSCR_1); |
23 | |
24 | mtspr(SPRN_TAR, TAR_1); |
25 | mtspr(SPRN_PPR, PPR_1); |
26 | mtspr(SPRN_DSCR, DSCR_1); |
27 | |
28 | cptr[2] = 1; |
29 | |
30 | /* Wait on parent */ |
31 | while (!cptr[0]) |
32 | asm volatile("" : : : "memory" ); |
33 | |
34 | reg[0] = mfspr(SPRN_TAR); |
35 | reg[1] = mfspr(SPRN_PPR); |
36 | reg[2] = mfspr(SPRN_DSCR); |
37 | |
38 | printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n" , |
39 | user_read, reg[0], reg[1], reg[2]); |
40 | |
41 | /* Unblock the parent now */ |
42 | cptr[1] = 1; |
43 | shmdt((int *)cptr); |
44 | |
45 | ret = validate_tar_registers(reg, TAR_2, PPR_2, DSCR_2); |
46 | if (ret) |
47 | exit(1); |
48 | exit(0); |
49 | } |
50 | |
51 | int trace_tar(pid_t child) |
52 | { |
53 | unsigned long reg[3]; |
54 | |
55 | FAIL_IF(start_trace(child)); |
56 | FAIL_IF(show_tar_registers(child, out: reg)); |
57 | printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n" , |
58 | ptrace_read_running, reg[0], reg[1], reg[2]); |
59 | |
60 | FAIL_IF(validate_tar_registers(reg, TAR_1, PPR_1, DSCR_1)); |
61 | FAIL_IF(stop_trace(child)); |
62 | return TEST_PASS; |
63 | } |
64 | |
65 | int trace_tar_write(pid_t child) |
66 | { |
67 | FAIL_IF(start_trace(child)); |
68 | FAIL_IF(write_tar_registers(child, TAR_2, PPR_2, DSCR_2)); |
69 | printf("%-30s TAR: %u PPR: %lx DSCR: %u\n" , |
70 | ptrace_write_running, TAR_2, PPR_2, DSCR_2); |
71 | |
72 | FAIL_IF(stop_trace(child)); |
73 | return TEST_PASS; |
74 | } |
75 | |
76 | int ptrace_tar(void) |
77 | { |
78 | pid_t pid; |
79 | int ret, status; |
80 | |
81 | // TAR was added in v2.07 |
82 | SKIP_IF_MSG(!have_hwcap2(PPC_FEATURE2_ARCH_2_07), "TAR requires ISA 2.07 compatible hardware" ); |
83 | |
84 | shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); |
85 | pid = fork(); |
86 | if (pid < 0) { |
87 | perror("fork() failed" ); |
88 | return TEST_FAIL; |
89 | } |
90 | |
91 | if (pid == 0) |
92 | tar(); |
93 | |
94 | if (pid) { |
95 | pptr = (int *)shmat(shm_id, NULL, 0); |
96 | pptr[0] = 0; |
97 | pptr[1] = 0; |
98 | |
99 | while (!pptr[2]) |
100 | asm volatile("" : : : "memory" ); |
101 | ret = trace_tar(child: pid); |
102 | if (ret) |
103 | return ret; |
104 | |
105 | ret = trace_tar_write(child: pid); |
106 | if (ret) |
107 | return ret; |
108 | |
109 | /* Unblock the child now */ |
110 | pptr[0] = 1; |
111 | |
112 | /* Wait on child */ |
113 | while (!pptr[1]) |
114 | asm volatile("" : : : "memory" ); |
115 | |
116 | shmdt((int *)pptr); |
117 | |
118 | ret = wait(&status); |
119 | shmctl(shm_id, IPC_RMID, NULL); |
120 | if (ret != pid) { |
121 | printf("Child's exit status not captured\n" ); |
122 | return TEST_PASS; |
123 | } |
124 | |
125 | return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : |
126 | TEST_PASS; |
127 | } |
128 | return TEST_PASS; |
129 | } |
130 | |
131 | int main(int argc, char *argv[]) |
132 | { |
133 | return test_harness(ptrace_tar, "ptrace_tar" ); |
134 | } |
135 | |