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