0001
0002
0003
0004
0005
0006
0007 #include "ptrace.h"
0008 #include "tm.h"
0009
0010
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
0045 "mflr 31;"
0046 "bl 4f;"
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
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 }