Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / tools / testing / selftests / powerpc / ptrace / ptrace-tm-spr.c
blobe64cdb04cecf7fc52d0f48ad849f1da6c478bb92
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Ptrace test TM SPR registers
5 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
6 */
7 #include "ptrace.h"
8 #include "tm.h"
10 /* Tracee and tracer shared data */
11 struct shared {
12 int flag;
13 struct tm_spr_regs regs;
15 unsigned long tfhar;
17 int shm_id;
18 struct shared *cptr, *pptr;
20 int shm_id1;
21 int *cptr1, *pptr1;
23 #define TM_KVM_SCHED 0xe0000001ac000001
24 int validate_tm_spr(struct tm_spr_regs *regs)
26 FAIL_IF(regs->tm_tfhar != tfhar);
27 FAIL_IF((regs->tm_texasr == TM_KVM_SCHED) && (regs->tm_tfiar != 0));
29 return TEST_PASS;
32 void tm_spr(void)
34 unsigned long result, texasr;
35 int ret;
37 cptr = (struct shared *)shmat(shm_id, NULL, 0);
38 cptr1 = (int *)shmat(shm_id1, NULL, 0);
40 trans:
41 cptr1[0] = 0;
42 asm __volatile__(
43 "1: ;"
44 /* TM failover handler should follow "tbegin.;" */
45 "mflr 31;"
46 "bl 4f;" /* $ = TFHAR - 12 */
47 "4: ;"
48 "mflr %[tfhar];"
49 "mtlr 31;"
51 "tbegin.;"
52 "beq 2f;"
54 "tsuspend.;"
55 "li 8, 1;"
56 "sth 8, 0(%[cptr1]);"
57 "tresume.;"
58 "b .;"
60 "tend.;"
61 "li 0, 0;"
62 "ori %[res], 0, 0;"
63 "b 3f;"
65 "2: ;"
67 "li 0, 1;"
68 "ori %[res], 0, 0;"
69 "mfspr %[texasr], %[sprn_texasr];"
71 "3: ;"
72 : [tfhar] "=r" (tfhar), [res] "=r" (result),
73 [texasr] "=r" (texasr), [cptr1] "=b" (cptr1)
74 : [sprn_texasr] "i" (SPRN_TEXASR)
75 : "memory", "r0", "r8", "r31"
78 /* There are 2 32bit instructions before tbegin. */
79 tfhar += 12;
81 if (result) {
82 if (!cptr->flag)
83 goto trans;
85 ret = validate_tm_spr((struct tm_spr_regs *)&cptr->regs);
86 shmdt((void *)cptr);
87 shmdt((void *)cptr1);
88 if (ret)
89 exit(1);
90 exit(0);
92 shmdt((void *)cptr);
93 shmdt((void *)cptr1);
94 exit(1);
97 int trace_tm_spr(pid_t child)
99 FAIL_IF(start_trace(child));
100 FAIL_IF(show_tm_spr(child, (struct tm_spr_regs *)&pptr->regs));
102 printf("TFHAR: %lx TEXASR: %lx TFIAR: %lx\n", pptr->regs.tm_tfhar,
103 pptr->regs.tm_texasr, pptr->regs.tm_tfiar);
105 pptr->flag = 1;
106 FAIL_IF(stop_trace(child));
108 return TEST_PASS;
111 int ptrace_tm_spr(void)
113 pid_t pid;
114 int ret, status;
116 SKIP_IF_MSG(!have_htm(), "Don't have transactional memory");
117 SKIP_IF_MSG(htm_is_synthetic(), "Transactional memory is synthetic");
118 shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT);
119 shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
120 pid = fork();
121 if (pid < 0) {
122 perror("fork() failed");
123 return TEST_FAIL;
126 if (pid == 0)
127 tm_spr();
129 if (pid) {
130 pptr = (struct shared *)shmat(shm_id, NULL, 0);
131 pptr1 = (int *)shmat(shm_id1, NULL, 0);
133 while (!pptr1[0])
134 asm volatile("" : : : "memory");
135 ret = trace_tm_spr(pid);
136 if (ret) {
137 kill(pid, SIGKILL);
138 shmdt((void *)pptr);
139 shmdt((void *)pptr1);
140 shmctl(shm_id, IPC_RMID, NULL);
141 shmctl(shm_id1, IPC_RMID, NULL);
142 return TEST_FAIL;
145 shmdt((void *)pptr);
146 shmdt((void *)pptr1);
147 ret = wait(&status);
148 shmctl(shm_id, IPC_RMID, NULL);
149 shmctl(shm_id1, IPC_RMID, NULL);
150 if (ret != pid) {
151 printf("Child's exit status not captured\n");
152 return TEST_FAIL;
155 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
156 TEST_PASS;
158 return TEST_PASS;
161 int main(int argc, char *argv[])
163 return test_harness(ptrace_tm_spr, "ptrace_tm_spr");