1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Ptrace test for GPR/FPR registers
4  *
5  * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
6  */
7 #include "ptrace.h"
8 #include "ptrace-gpr.h"
9 #include "reg.h"
10 
11 /* Tracer and Tracee Shared Data */
12 int shm_id;
13 int *cptr, *pptr;
14 
15 float a = FPR_1;
16 float b = FPR_2;
17 float c = FPR_3;
18 
19 void gpr(void)
20 {
21 	unsigned long gpr_buf[18];
22 	float fpr_buf[32];
23 
24 	cptr = (int *)shmat(shm_id, NULL, 0);
25 
26 	asm __volatile__(
27 		ASM_LOAD_GPR_IMMED(gpr_1)
28 		ASM_LOAD_FPR_SINGLE_PRECISION(flt_1)
29 		:
30 		: [gpr_1]"i"(GPR_1), [flt_1] "b" (&a)
31 		: "memory", "r6", "r7", "r8", "r9", "r10",
32 		"r11", "r12", "r13", "r14", "r15", "r16", "r17",
33 		"r18", "r19", "r20", "r21", "r22", "r23", "r24",
34 		"r25", "r26", "r27", "r28", "r29", "r30", "r31"
35 		);
36 
37 	cptr[1] = 1;
38 
39 	while (!cptr[0])
40 		asm volatile("" : : : "memory");
41 
42 	shmdt((void *)cptr);
43 	store_gpr(gpr_buf);
44 	store_fpr_single_precision(fpr_buf);
45 
46 	if (validate_gpr(gpr_buf, GPR_3))
47 		exit(1);
48 
49 	if (validate_fpr_float(fpr_buf, c))
50 		exit(1);
51 
52 	exit(0);
53 }
54 
55 int trace_gpr(pid_t child)
56 {
57 	unsigned long gpr[18];
58 	unsigned long fpr[32];
59 
60 	FAIL_IF(start_trace(child));
61 	FAIL_IF(show_gpr(child, gpr));
62 	FAIL_IF(validate_gpr(gpr, GPR_1));
63 	FAIL_IF(show_fpr(child, fpr));
64 	FAIL_IF(validate_fpr(fpr, FPR_1_REP));
65 	FAIL_IF(write_gpr(child, GPR_3));
66 	FAIL_IF(write_fpr(child, FPR_3_REP));
67 	FAIL_IF(stop_trace(child));
68 
69 	return TEST_PASS;
70 }
71 
72 int ptrace_gpr(void)
73 {
74 	pid_t pid;
75 	int ret, status;
76 
77 	shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
78 	pid = fork();
79 	if (pid < 0) {
80 		perror("fork() failed");
81 		return TEST_FAIL;
82 	}
83 	if (pid == 0)
84 		gpr();
85 
86 	if (pid) {
87 		pptr = (int *)shmat(shm_id, NULL, 0);
88 		while (!pptr[1])
89 			asm volatile("" : : : "memory");
90 
91 		ret = trace_gpr(pid);
92 		if (ret) {
93 			kill(pid, SIGTERM);
94 			shmdt((void *)pptr);
95 			shmctl(shm_id, IPC_RMID, NULL);
96 			return TEST_FAIL;
97 		}
98 
99 		pptr[0] = 1;
100 		shmdt((void *)pptr);
101 
102 		ret = wait(&status);
103 		shmctl(shm_id, IPC_RMID, NULL);
104 		if (ret != pid) {
105 			printf("Child's exit status not captured\n");
106 			return TEST_FAIL;
107 		}
108 
109 		return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
110 			TEST_PASS;
111 	}
112 
113 	return TEST_PASS;
114 }
115 
116 int main(int argc, char *argv[])
117 {
118 	return test_harness(ptrace_gpr, "ptrace_gpr");
119 }
120