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 */
12int shm_id;
13int *cptr, *pptr;
14
15float a = FPR_1;
16float b = FPR_2;
17float c = FPR_3;
18
19void 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
55int 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
72int 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
116int main(int argc, char *argv[])
117{
118	return test_harness(ptrace_gpr, "ptrace_gpr");
119}
120