12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
25bdac52fSAnshuman Khandual /*
35bdac52fSAnshuman Khandual * Ptrace test TM SPR registers
45bdac52fSAnshuman Khandual *
55bdac52fSAnshuman Khandual * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
65bdac52fSAnshuman Khandual */
75bdac52fSAnshuman Khandual #include "ptrace.h"
85bdac52fSAnshuman Khandual #include "tm.h"
95bdac52fSAnshuman Khandual
105bdac52fSAnshuman Khandual /* Tracee and tracer shared data */
115bdac52fSAnshuman Khandual struct shared {
125bdac52fSAnshuman Khandual int flag;
135bdac52fSAnshuman Khandual struct tm_spr_regs regs;
145bdac52fSAnshuman Khandual };
155bdac52fSAnshuman Khandual unsigned long tfhar;
165bdac52fSAnshuman Khandual
175bdac52fSAnshuman Khandual int shm_id;
185bdac52fSAnshuman Khandual struct shared *cptr, *pptr;
195bdac52fSAnshuman Khandual
205bdac52fSAnshuman Khandual int shm_id1;
215bdac52fSAnshuman Khandual int *cptr1, *pptr1;
225bdac52fSAnshuman Khandual
235bdac52fSAnshuman Khandual #define TM_KVM_SCHED 0xe0000001ac000001
validate_tm_spr(struct tm_spr_regs * regs)245bdac52fSAnshuman Khandual int validate_tm_spr(struct tm_spr_regs *regs)
255bdac52fSAnshuman Khandual {
265bdac52fSAnshuman Khandual FAIL_IF(regs->tm_tfhar != tfhar);
275bdac52fSAnshuman Khandual FAIL_IF((regs->tm_texasr == TM_KVM_SCHED) && (regs->tm_tfiar != 0));
285bdac52fSAnshuman Khandual
295bdac52fSAnshuman Khandual return TEST_PASS;
305bdac52fSAnshuman Khandual }
315bdac52fSAnshuman Khandual
tm_spr(void)325bdac52fSAnshuman Khandual void tm_spr(void)
335bdac52fSAnshuman Khandual {
345bdac52fSAnshuman Khandual unsigned long result, texasr;
355bdac52fSAnshuman Khandual int ret;
365bdac52fSAnshuman Khandual
375bdac52fSAnshuman Khandual cptr = (struct shared *)shmat(shm_id, NULL, 0);
385bdac52fSAnshuman Khandual cptr1 = (int *)shmat(shm_id1, NULL, 0);
395bdac52fSAnshuman Khandual
405bdac52fSAnshuman Khandual trans:
415bdac52fSAnshuman Khandual cptr1[0] = 0;
425bdac52fSAnshuman Khandual asm __volatile__(
435bdac52fSAnshuman Khandual "1: ;"
445bdac52fSAnshuman Khandual /* TM failover handler should follow "tbegin.;" */
455bdac52fSAnshuman Khandual "mflr 31;"
465bdac52fSAnshuman Khandual "bl 4f;" /* $ = TFHAR - 12 */
475bdac52fSAnshuman Khandual "4: ;"
485bdac52fSAnshuman Khandual "mflr %[tfhar];"
495bdac52fSAnshuman Khandual "mtlr 31;"
505bdac52fSAnshuman Khandual
515bdac52fSAnshuman Khandual "tbegin.;"
525bdac52fSAnshuman Khandual "beq 2f;"
535bdac52fSAnshuman Khandual
545bdac52fSAnshuman Khandual "tsuspend.;"
555bdac52fSAnshuman Khandual "li 8, 1;"
565bdac52fSAnshuman Khandual "sth 8, 0(%[cptr1]);"
575bdac52fSAnshuman Khandual "tresume.;"
585bdac52fSAnshuman Khandual "b .;"
595bdac52fSAnshuman Khandual
605bdac52fSAnshuman Khandual "tend.;"
615bdac52fSAnshuman Khandual "li 0, 0;"
625bdac52fSAnshuman Khandual "ori %[res], 0, 0;"
635bdac52fSAnshuman Khandual "b 3f;"
645bdac52fSAnshuman Khandual
655bdac52fSAnshuman Khandual "2: ;"
665bdac52fSAnshuman Khandual
675bdac52fSAnshuman Khandual "li 0, 1;"
685bdac52fSAnshuman Khandual "ori %[res], 0, 0;"
695bdac52fSAnshuman Khandual "mfspr %[texasr], %[sprn_texasr];"
705bdac52fSAnshuman Khandual
715bdac52fSAnshuman Khandual "3: ;"
725bdac52fSAnshuman Khandual : [tfhar] "=r" (tfhar), [res] "=r" (result),
735249497aSBreno Leitao [texasr] "=r" (texasr), [cptr1] "=b" (cptr1)
745bdac52fSAnshuman Khandual : [sprn_texasr] "i" (SPRN_TEXASR)
75f36dbfe1SSimon Guo : "memory", "r0", "r8", "r31"
765bdac52fSAnshuman Khandual );
775bdac52fSAnshuman Khandual
785bdac52fSAnshuman Khandual /* There are 2 32bit instructions before tbegin. */
795bdac52fSAnshuman Khandual tfhar += 12;
805bdac52fSAnshuman Khandual
815bdac52fSAnshuman Khandual if (result) {
825bdac52fSAnshuman Khandual if (!cptr->flag)
835bdac52fSAnshuman Khandual goto trans;
845bdac52fSAnshuman Khandual
855bdac52fSAnshuman Khandual ret = validate_tm_spr((struct tm_spr_regs *)&cptr->regs);
865bdac52fSAnshuman Khandual shmdt((void *)cptr);
875bdac52fSAnshuman Khandual shmdt((void *)cptr1);
885bdac52fSAnshuman Khandual if (ret)
895bdac52fSAnshuman Khandual exit(1);
905bdac52fSAnshuman Khandual exit(0);
915bdac52fSAnshuman Khandual }
925bdac52fSAnshuman Khandual shmdt((void *)cptr);
935bdac52fSAnshuman Khandual shmdt((void *)cptr1);
945bdac52fSAnshuman Khandual exit(1);
955bdac52fSAnshuman Khandual }
965bdac52fSAnshuman Khandual
trace_tm_spr(pid_t child)975bdac52fSAnshuman Khandual int trace_tm_spr(pid_t child)
985bdac52fSAnshuman Khandual {
995bdac52fSAnshuman Khandual FAIL_IF(start_trace(child));
1005bdac52fSAnshuman Khandual FAIL_IF(show_tm_spr(child, (struct tm_spr_regs *)&pptr->regs));
1015bdac52fSAnshuman Khandual
1025bdac52fSAnshuman Khandual printf("TFHAR: %lx TEXASR: %lx TFIAR: %lx\n", pptr->regs.tm_tfhar,
1035bdac52fSAnshuman Khandual pptr->regs.tm_texasr, pptr->regs.tm_tfiar);
1045bdac52fSAnshuman Khandual
1055bdac52fSAnshuman Khandual pptr->flag = 1;
1065bdac52fSAnshuman Khandual FAIL_IF(stop_trace(child));
1075bdac52fSAnshuman Khandual
1085bdac52fSAnshuman Khandual return TEST_PASS;
1095bdac52fSAnshuman Khandual }
1105bdac52fSAnshuman Khandual
ptrace_tm_spr(void)1115bdac52fSAnshuman Khandual int ptrace_tm_spr(void)
1125bdac52fSAnshuman Khandual {
1135bdac52fSAnshuman Khandual pid_t pid;
1145bdac52fSAnshuman Khandual int ret, status;
1155bdac52fSAnshuman Khandual
116*68877ff2SBenjamin Gray SKIP_IF_MSG(!have_htm(), "Don't have transactional memory");
117*68877ff2SBenjamin Gray SKIP_IF_MSG(htm_is_synthetic(), "Transactional memory is synthetic");
1185bdac52fSAnshuman Khandual shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT);
1195bdac52fSAnshuman Khandual shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
1205bdac52fSAnshuman Khandual pid = fork();
1215bdac52fSAnshuman Khandual if (pid < 0) {
1225bdac52fSAnshuman Khandual perror("fork() failed");
1235bdac52fSAnshuman Khandual return TEST_FAIL;
1245bdac52fSAnshuman Khandual }
1255bdac52fSAnshuman Khandual
1265bdac52fSAnshuman Khandual if (pid == 0)
1275bdac52fSAnshuman Khandual tm_spr();
1285bdac52fSAnshuman Khandual
1295bdac52fSAnshuman Khandual if (pid) {
1305bdac52fSAnshuman Khandual pptr = (struct shared *)shmat(shm_id, NULL, 0);
1315bdac52fSAnshuman Khandual pptr1 = (int *)shmat(shm_id1, NULL, 0);
1325bdac52fSAnshuman Khandual
1335bdac52fSAnshuman Khandual while (!pptr1[0])
1345bdac52fSAnshuman Khandual asm volatile("" : : : "memory");
1355bdac52fSAnshuman Khandual ret = trace_tm_spr(pid);
1365bdac52fSAnshuman Khandual if (ret) {
1375bdac52fSAnshuman Khandual kill(pid, SIGKILL);
1385bdac52fSAnshuman Khandual shmdt((void *)pptr);
1395bdac52fSAnshuman Khandual shmdt((void *)pptr1);
1405bdac52fSAnshuman Khandual shmctl(shm_id, IPC_RMID, NULL);
1415bdac52fSAnshuman Khandual shmctl(shm_id1, IPC_RMID, NULL);
1425bdac52fSAnshuman Khandual return TEST_FAIL;
1435bdac52fSAnshuman Khandual }
1445bdac52fSAnshuman Khandual
1455bdac52fSAnshuman Khandual shmdt((void *)pptr);
1465bdac52fSAnshuman Khandual shmdt((void *)pptr1);
1475bdac52fSAnshuman Khandual ret = wait(&status);
1485bdac52fSAnshuman Khandual shmctl(shm_id, IPC_RMID, NULL);
1495bdac52fSAnshuman Khandual shmctl(shm_id1, IPC_RMID, NULL);
1505bdac52fSAnshuman Khandual if (ret != pid) {
1515bdac52fSAnshuman Khandual printf("Child's exit status not captured\n");
1525bdac52fSAnshuman Khandual return TEST_FAIL;
1535bdac52fSAnshuman Khandual }
1545bdac52fSAnshuman Khandual
1555bdac52fSAnshuman Khandual return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
1565bdac52fSAnshuman Khandual TEST_PASS;
1575bdac52fSAnshuman Khandual }
1585bdac52fSAnshuman Khandual return TEST_PASS;
1595bdac52fSAnshuman Khandual }
1605bdac52fSAnshuman Khandual
main(int argc,char * argv[])1615bdac52fSAnshuman Khandual int main(int argc, char *argv[])
1625bdac52fSAnshuman Khandual {
1635bdac52fSAnshuman Khandual return test_harness(ptrace_tm_spr, "ptrace_tm_spr");
1645bdac52fSAnshuman Khandual }
165