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