Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Ptrace test TM SPR registers
0004  *
0005  * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
0006  */
0007 #include "ptrace.h"
0008 #include "tm.h"
0009 
0010 /* Tracee and tracer shared data */
0011 struct shared {
0012     int flag;
0013     struct tm_spr_regs regs;
0014 };
0015 unsigned long tfhar;
0016 
0017 int shm_id;
0018 struct shared *cptr, *pptr;
0019 
0020 int shm_id1;
0021 int *cptr1, *pptr1;
0022 
0023 #define TM_KVM_SCHED   0xe0000001ac000001
0024 int validate_tm_spr(struct tm_spr_regs *regs)
0025 {
0026     FAIL_IF(regs->tm_tfhar != tfhar);
0027     FAIL_IF((regs->tm_texasr == TM_KVM_SCHED) && (regs->tm_tfiar != 0));
0028 
0029     return TEST_PASS;
0030 }
0031 
0032 void tm_spr(void)
0033 {
0034     unsigned long result, texasr;
0035     int ret;
0036 
0037     cptr = (struct shared *)shmat(shm_id, NULL, 0);
0038     cptr1 = (int *)shmat(shm_id1, NULL, 0);
0039 
0040 trans:
0041     cptr1[0] = 0;
0042     asm __volatile__(
0043         "1: ;"
0044         /* TM failover handler should follow "tbegin.;" */
0045         "mflr 31;"
0046         "bl 4f;"    /* $ = TFHAR - 12 */
0047         "4: ;"
0048         "mflr %[tfhar];"
0049         "mtlr 31;"
0050 
0051         "tbegin.;"
0052         "beq 2f;"
0053 
0054         "tsuspend.;"
0055         "li 8, 1;"
0056         "sth 8, 0(%[cptr1]);"
0057         "tresume.;"
0058         "b .;"
0059 
0060         "tend.;"
0061         "li 0, 0;"
0062         "ori %[res], 0, 0;"
0063         "b 3f;"
0064 
0065         "2: ;"
0066 
0067         "li 0, 1;"
0068         "ori %[res], 0, 0;"
0069         "mfspr %[texasr], %[sprn_texasr];"
0070 
0071         "3: ;"
0072         : [tfhar] "=r" (tfhar), [res] "=r" (result),
0073         [texasr] "=r" (texasr), [cptr1] "=b" (cptr1)
0074         : [sprn_texasr] "i"  (SPRN_TEXASR)
0075         : "memory", "r0", "r8", "r31"
0076         );
0077 
0078     /* There are 2 32bit instructions before tbegin. */
0079     tfhar += 12;
0080 
0081     if (result) {
0082         if (!cptr->flag)
0083             goto trans;
0084 
0085         ret = validate_tm_spr((struct tm_spr_regs *)&cptr->regs);
0086         shmdt((void *)cptr);
0087         shmdt((void *)cptr1);
0088         if (ret)
0089             exit(1);
0090         exit(0);
0091     }
0092     shmdt((void *)cptr);
0093     shmdt((void *)cptr1);
0094     exit(1);
0095 }
0096 
0097 int trace_tm_spr(pid_t child)
0098 {
0099     FAIL_IF(start_trace(child));
0100     FAIL_IF(show_tm_spr(child, (struct tm_spr_regs *)&pptr->regs));
0101 
0102     printf("TFHAR: %lx TEXASR: %lx TFIAR: %lx\n", pptr->regs.tm_tfhar,
0103                 pptr->regs.tm_texasr, pptr->regs.tm_tfiar);
0104 
0105     pptr->flag = 1;
0106     FAIL_IF(stop_trace(child));
0107 
0108     return TEST_PASS;
0109 }
0110 
0111 int ptrace_tm_spr(void)
0112 {
0113     pid_t pid;
0114     int ret, status;
0115 
0116     SKIP_IF(!have_htm());
0117     SKIP_IF(htm_is_synthetic());
0118     shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT);
0119     shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
0120     pid = fork();
0121     if (pid < 0) {
0122         perror("fork() failed");
0123         return TEST_FAIL;
0124     }
0125 
0126     if (pid == 0)
0127         tm_spr();
0128 
0129     if (pid) {
0130         pptr = (struct shared *)shmat(shm_id, NULL, 0);
0131         pptr1 = (int *)shmat(shm_id1, NULL, 0);
0132 
0133         while (!pptr1[0])
0134             asm volatile("" : : : "memory");
0135         ret = trace_tm_spr(pid);
0136         if (ret) {
0137             kill(pid, SIGKILL);
0138             shmdt((void *)pptr);
0139             shmdt((void *)pptr1);
0140             shmctl(shm_id, IPC_RMID, NULL);
0141             shmctl(shm_id1, IPC_RMID, NULL);
0142             return TEST_FAIL;
0143         }
0144 
0145         shmdt((void *)pptr);
0146         shmdt((void *)pptr1);
0147         ret = wait(&status);
0148         shmctl(shm_id, IPC_RMID, NULL);
0149         shmctl(shm_id1, IPC_RMID, NULL);
0150         if (ret != pid) {
0151             printf("Child's exit status not captured\n");
0152             return TEST_FAIL;
0153         }
0154 
0155         return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
0156             TEST_PASS;
0157     }
0158     return TEST_PASS;
0159 }
0160 
0161 int main(int argc, char *argv[])
0162 {
0163     return test_harness(ptrace_tm_spr, "ptrace_tm_spr");
0164 }