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 }
136