165 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Ptrace test TM SPR registers4 *5 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.6 */7#include "ptrace.h"8#include "tm.h"9 10/* Tracee and tracer shared data */11struct shared {12 int flag;13 struct tm_spr_regs regs;14};15unsigned long tfhar;16 17int shm_id;18struct shared *cptr, *pptr;19 20int shm_id1;21int *cptr1, *pptr1;22 23#define TM_KVM_SCHED 0xe0000001ac00000124int validate_tm_spr(struct tm_spr_regs *regs)25{26 FAIL_IF(regs->tm_tfhar != tfhar);27 FAIL_IF((regs->tm_texasr == TM_KVM_SCHED) && (regs->tm_tfiar != 0));28 29 return TEST_PASS;30}31 32void tm_spr(void)33{34 unsigned long result, texasr;35 int ret;36 37 cptr = (struct shared *)shmat(shm_id, NULL, 0);38 cptr1 = (int *)shmat(shm_id1, NULL, 0);39 40trans: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;"50 51 "tbegin.;"52 "beq 2f;"53 54 "tsuspend.;"55 "li 8, 1;"56 "sth 8, 0(%[cptr1]);"57 "tresume.;"58 "b .;"59 60 "tend.;"61 "li 0, 0;"62 "ori %[res], 0, 0;"63 "b 3f;"64 65 "2: ;"66 67 "li 0, 1;"68 "ori %[res], 0, 0;"69 "mfspr %[texasr], %[sprn_texasr];"70 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"76 );77 78 /* There are 2 32bit instructions before tbegin. */79 tfhar += 12;80 81 if (result) {82 if (!cptr->flag)83 goto trans;84 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);91 }92 shmdt((void *)cptr);93 shmdt((void *)cptr1);94 exit(1);95}96 97int trace_tm_spr(pid_t child)98{99 FAIL_IF(start_trace(child));100 FAIL_IF(show_tm_spr(child, (struct tm_spr_regs *)&pptr->regs));101 102 printf("TFHAR: %lx TEXASR: %lx TFIAR: %lx\n", pptr->regs.tm_tfhar,103 pptr->regs.tm_texasr, pptr->regs.tm_tfiar);104 105 pptr->flag = 1;106 FAIL_IF(stop_trace(child));107 108 return TEST_PASS;109}110 111int ptrace_tm_spr(void)112{113 pid_t pid;114 int ret, status;115 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;124 }125 126 if (pid == 0)127 tm_spr();128 129 if (pid) {130 pptr = (struct shared *)shmat(shm_id, NULL, 0);131 pptr1 = (int *)shmat(shm_id1, NULL, 0);132 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;143 }144 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;153 }154 155 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :156 TEST_PASS;157 }158 return TEST_PASS;159}160 161int main(int argc, char *argv[])162{163 return test_harness(ptrace_tm_spr, "ptrace_tm_spr");164}165