18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Ptrace test for TAR, PPR, DSCR registers in the TM context 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#include "ptrace.h" 88c2ecf20Sopenharmony_ci#include "tm.h" 98c2ecf20Sopenharmony_ci#include "ptrace-tar.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ciint shm_id; 128c2ecf20Sopenharmony_ciunsigned long *cptr, *pptr; 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_civoid tm_tar(void) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci unsigned long result, texasr; 188c2ecf20Sopenharmony_ci unsigned long regs[3]; 198c2ecf20Sopenharmony_ci int ret; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci cptr = (unsigned long *)shmat(shm_id, NULL, 0); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_citrans: 248c2ecf20Sopenharmony_ci cptr[1] = 0; 258c2ecf20Sopenharmony_ci asm __volatile__( 268c2ecf20Sopenharmony_ci "li 4, %[tar_1];" 278c2ecf20Sopenharmony_ci "mtspr %[sprn_tar], 4;" /* TAR_1 */ 288c2ecf20Sopenharmony_ci "li 4, %[dscr_1];" 298c2ecf20Sopenharmony_ci "mtspr %[sprn_dscr], 4;" /* DSCR_1 */ 308c2ecf20Sopenharmony_ci "or 31,31,31;" /* PPR_1*/ 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci "1: ;" 338c2ecf20Sopenharmony_ci "tbegin.;" 348c2ecf20Sopenharmony_ci "beq 2f;" 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci "li 4, %[tar_2];" 378c2ecf20Sopenharmony_ci "mtspr %[sprn_tar], 4;" /* TAR_2 */ 388c2ecf20Sopenharmony_ci "li 4, %[dscr_2];" 398c2ecf20Sopenharmony_ci "mtspr %[sprn_dscr], 4;" /* DSCR_2 */ 408c2ecf20Sopenharmony_ci "or 1,1,1;" /* PPR_2 */ 418c2ecf20Sopenharmony_ci "tsuspend.;" 428c2ecf20Sopenharmony_ci "li 0, 1;" 438c2ecf20Sopenharmony_ci "stw 0, 0(%[cptr1]);" 448c2ecf20Sopenharmony_ci "tresume.;" 458c2ecf20Sopenharmony_ci "b .;" 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci "tend.;" 488c2ecf20Sopenharmony_ci "li 0, 0;" 498c2ecf20Sopenharmony_ci "ori %[res], 0, 0;" 508c2ecf20Sopenharmony_ci "b 3f;" 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* Transaction abort handler */ 538c2ecf20Sopenharmony_ci "2: ;" 548c2ecf20Sopenharmony_ci "li 0, 1;" 558c2ecf20Sopenharmony_ci "ori %[res], 0, 0;" 568c2ecf20Sopenharmony_ci "mfspr %[texasr], %[sprn_texasr];" 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci "3: ;" 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci : [res] "=r" (result), [texasr] "=r" (texasr) 618c2ecf20Sopenharmony_ci : [sprn_dscr]"i"(SPRN_DSCR), [sprn_tar]"i"(SPRN_TAR), 628c2ecf20Sopenharmony_ci [sprn_ppr]"i"(SPRN_PPR), [sprn_texasr]"i"(SPRN_TEXASR), 638c2ecf20Sopenharmony_ci [tar_1]"i"(TAR_1), [dscr_1]"i"(DSCR_1), [tar_2]"i"(TAR_2), 648c2ecf20Sopenharmony_ci [dscr_2]"i"(DSCR_2), [cptr1] "b" (&cptr[1]) 658c2ecf20Sopenharmony_ci : "memory", "r0", "r3", "r4", "r5", "r6" 668c2ecf20Sopenharmony_ci ); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci /* TM failed, analyse */ 698c2ecf20Sopenharmony_ci if (result) { 708c2ecf20Sopenharmony_ci if (!cptr[0]) 718c2ecf20Sopenharmony_ci goto trans; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci regs[0] = mfspr(SPRN_TAR); 748c2ecf20Sopenharmony_ci regs[1] = mfspr(SPRN_PPR); 758c2ecf20Sopenharmony_ci regs[2] = mfspr(SPRN_DSCR); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci shmdt(&cptr); 788c2ecf20Sopenharmony_ci printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", 798c2ecf20Sopenharmony_ci user_read, regs[0], regs[1], regs[2]); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci ret = validate_tar_registers(regs, TAR_4, PPR_4, DSCR_4); 828c2ecf20Sopenharmony_ci if (ret) 838c2ecf20Sopenharmony_ci exit(1); 848c2ecf20Sopenharmony_ci exit(0); 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci shmdt(&cptr); 878c2ecf20Sopenharmony_ci exit(1); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ciint trace_tm_tar(pid_t child) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci unsigned long regs[3]; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci FAIL_IF(start_trace(child)); 958c2ecf20Sopenharmony_ci FAIL_IF(show_tar_registers(child, regs)); 968c2ecf20Sopenharmony_ci printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", 978c2ecf20Sopenharmony_ci ptrace_read_running, regs[0], regs[1], regs[2]); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci FAIL_IF(validate_tar_registers(regs, TAR_2, PPR_2, DSCR_2)); 1008c2ecf20Sopenharmony_ci FAIL_IF(show_tm_checkpointed_state(child, regs)); 1018c2ecf20Sopenharmony_ci printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", 1028c2ecf20Sopenharmony_ci ptrace_read_ckpt, regs[0], regs[1], regs[2]); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci FAIL_IF(validate_tar_registers(regs, TAR_1, PPR_1, DSCR_1)); 1058c2ecf20Sopenharmony_ci FAIL_IF(write_ckpt_tar_registers(child, TAR_4, PPR_4, DSCR_4)); 1068c2ecf20Sopenharmony_ci printf("%-30s TAR: %u PPR: %lx DSCR: %u\n", 1078c2ecf20Sopenharmony_ci ptrace_write_ckpt, TAR_4, PPR_4, DSCR_4); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci pptr[0] = 1; 1108c2ecf20Sopenharmony_ci FAIL_IF(stop_trace(child)); 1118c2ecf20Sopenharmony_ci return TEST_PASS; 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ciint ptrace_tm_tar(void) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci pid_t pid; 1178c2ecf20Sopenharmony_ci int ret, status; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci SKIP_IF(!have_htm()); 1208c2ecf20Sopenharmony_ci shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); 1218c2ecf20Sopenharmony_ci pid = fork(); 1228c2ecf20Sopenharmony_ci if (pid == 0) 1238c2ecf20Sopenharmony_ci tm_tar(); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci pptr = (unsigned long *)shmat(shm_id, NULL, 0); 1268c2ecf20Sopenharmony_ci pptr[0] = 0; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (pid) { 1298c2ecf20Sopenharmony_ci while (!pptr[1]) 1308c2ecf20Sopenharmony_ci asm volatile("" : : : "memory"); 1318c2ecf20Sopenharmony_ci ret = trace_tm_tar(pid); 1328c2ecf20Sopenharmony_ci if (ret) { 1338c2ecf20Sopenharmony_ci kill(pid, SIGTERM); 1348c2ecf20Sopenharmony_ci shmdt(&pptr); 1358c2ecf20Sopenharmony_ci shmctl(shm_id, IPC_RMID, NULL); 1368c2ecf20Sopenharmony_ci return TEST_FAIL; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci shmdt(&pptr); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci ret = wait(&status); 1418c2ecf20Sopenharmony_ci shmctl(shm_id, IPC_RMID, NULL); 1428c2ecf20Sopenharmony_ci if (ret != pid) { 1438c2ecf20Sopenharmony_ci printf("Child's exit status not captured\n"); 1448c2ecf20Sopenharmony_ci return TEST_FAIL; 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : 1488c2ecf20Sopenharmony_ci TEST_PASS; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci return TEST_PASS; 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ciint main(int argc, char *argv[]) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci return test_harness(ptrace_tm_tar, "ptrace_tm_tar"); 1568c2ecf20Sopenharmony_ci} 157