12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
201f7fdc7SAnshuman Khandual /*
301f7fdc7SAnshuman Khandual * Ptrace test for TAR, PPR, DSCR registers in the TM Suspend context
401f7fdc7SAnshuman Khandual *
501f7fdc7SAnshuman Khandual * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
601f7fdc7SAnshuman Khandual */
701f7fdc7SAnshuman Khandual #include "ptrace.h"
801f7fdc7SAnshuman Khandual #include "tm.h"
901f7fdc7SAnshuman Khandual #include "ptrace-tar.h"
1001f7fdc7SAnshuman Khandual
1101f7fdc7SAnshuman Khandual int shm_id;
1201f7fdc7SAnshuman Khandual int *cptr, *pptr;
1301f7fdc7SAnshuman Khandual
wait_parent(void)1401f7fdc7SAnshuman Khandual __attribute__((used)) void wait_parent(void)
1501f7fdc7SAnshuman Khandual {
1601f7fdc7SAnshuman Khandual cptr[2] = 1;
1701f7fdc7SAnshuman Khandual while (!cptr[1])
1801f7fdc7SAnshuman Khandual asm volatile("" : : : "memory");
1901f7fdc7SAnshuman Khandual }
2001f7fdc7SAnshuman Khandual
tm_spd_tar(void)2101f7fdc7SAnshuman Khandual void tm_spd_tar(void)
2201f7fdc7SAnshuman Khandual {
2301f7fdc7SAnshuman Khandual unsigned long result, texasr;
2401f7fdc7SAnshuman Khandual unsigned long regs[3];
2501f7fdc7SAnshuman Khandual int ret;
2601f7fdc7SAnshuman Khandual
2701f7fdc7SAnshuman Khandual cptr = (int *)shmat(shm_id, NULL, 0);
2801f7fdc7SAnshuman Khandual
2901f7fdc7SAnshuman Khandual trans:
3001f7fdc7SAnshuman Khandual cptr[2] = 0;
3101f7fdc7SAnshuman Khandual asm __volatile__(
3201f7fdc7SAnshuman Khandual "li 4, %[tar_1];"
3301f7fdc7SAnshuman Khandual "mtspr %[sprn_tar], 4;" /* TAR_1 */
3401f7fdc7SAnshuman Khandual "li 4, %[dscr_1];"
3501f7fdc7SAnshuman Khandual "mtspr %[sprn_dscr], 4;" /* DSCR_1 */
3601f7fdc7SAnshuman Khandual "or 31,31,31;" /* PPR_1*/
3701f7fdc7SAnshuman Khandual
3801f7fdc7SAnshuman Khandual "1: ;"
3901f7fdc7SAnshuman Khandual "tbegin.;"
4001f7fdc7SAnshuman Khandual "beq 2f;"
4101f7fdc7SAnshuman Khandual
4201f7fdc7SAnshuman Khandual "li 4, %[tar_2];"
4301f7fdc7SAnshuman Khandual "mtspr %[sprn_tar], 4;" /* TAR_2 */
4401f7fdc7SAnshuman Khandual "li 4, %[dscr_2];"
4501f7fdc7SAnshuman Khandual "mtspr %[sprn_dscr], 4;" /* DSCR_2 */
4601f7fdc7SAnshuman Khandual "or 1,1,1;" /* PPR_2 */
4701f7fdc7SAnshuman Khandual
4801f7fdc7SAnshuman Khandual "tsuspend.;"
4901f7fdc7SAnshuman Khandual "li 4, %[tar_3];"
5001f7fdc7SAnshuman Khandual "mtspr %[sprn_tar], 4;" /* TAR_3 */
5101f7fdc7SAnshuman Khandual "li 4, %[dscr_3];"
5201f7fdc7SAnshuman Khandual "mtspr %[sprn_dscr], 4;" /* DSCR_3 */
5301f7fdc7SAnshuman Khandual "or 6,6,6;" /* PPR_3 */
5401f7fdc7SAnshuman Khandual "bl wait_parent;"
5501f7fdc7SAnshuman Khandual "tresume.;"
5601f7fdc7SAnshuman Khandual
5701f7fdc7SAnshuman Khandual "tend.;"
5801f7fdc7SAnshuman Khandual "li 0, 0;"
5901f7fdc7SAnshuman Khandual "ori %[res], 0, 0;"
6001f7fdc7SAnshuman Khandual "b 3f;"
6101f7fdc7SAnshuman Khandual
6201f7fdc7SAnshuman Khandual /* Transaction abort handler */
6301f7fdc7SAnshuman Khandual "2: ;"
6401f7fdc7SAnshuman Khandual "li 0, 1;"
6501f7fdc7SAnshuman Khandual "ori %[res], 0, 0;"
6601f7fdc7SAnshuman Khandual "mfspr %[texasr], %[sprn_texasr];"
6701f7fdc7SAnshuman Khandual
6801f7fdc7SAnshuman Khandual "3: ;"
6901f7fdc7SAnshuman Khandual
7001f7fdc7SAnshuman Khandual : [res] "=r" (result), [texasr] "=r" (texasr)
715249497aSBreno Leitao : [sprn_dscr]"i"(SPRN_DSCR),
7201f7fdc7SAnshuman Khandual [sprn_tar]"i"(SPRN_TAR), [sprn_ppr]"i"(SPRN_PPR),
7301f7fdc7SAnshuman Khandual [sprn_texasr]"i"(SPRN_TEXASR), [tar_1]"i"(TAR_1),
7401f7fdc7SAnshuman Khandual [dscr_1]"i"(DSCR_1), [tar_2]"i"(TAR_2), [dscr_2]"i"(DSCR_2),
7501f7fdc7SAnshuman Khandual [tar_3]"i"(TAR_3), [dscr_3]"i"(DSCR_3)
76a02cbc7fSMichael Ellerman : "memory", "r0", "r3", "r4", "r5", "r6", "lr"
7701f7fdc7SAnshuman Khandual );
7801f7fdc7SAnshuman Khandual
7901f7fdc7SAnshuman Khandual /* TM failed, analyse */
8001f7fdc7SAnshuman Khandual if (result) {
8101f7fdc7SAnshuman Khandual if (!cptr[0])
8201f7fdc7SAnshuman Khandual goto trans;
8301f7fdc7SAnshuman Khandual
8401f7fdc7SAnshuman Khandual regs[0] = mfspr(SPRN_TAR);
8501f7fdc7SAnshuman Khandual regs[1] = mfspr(SPRN_PPR);
8601f7fdc7SAnshuman Khandual regs[2] = mfspr(SPRN_DSCR);
8701f7fdc7SAnshuman Khandual
8801f7fdc7SAnshuman Khandual shmdt(&cptr);
8901f7fdc7SAnshuman Khandual printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
9001f7fdc7SAnshuman Khandual user_read, regs[0], regs[1], regs[2]);
9101f7fdc7SAnshuman Khandual
9201f7fdc7SAnshuman Khandual ret = validate_tar_registers(regs, TAR_4, PPR_4, DSCR_4);
9301f7fdc7SAnshuman Khandual if (ret)
9401f7fdc7SAnshuman Khandual exit(1);
9501f7fdc7SAnshuman Khandual exit(0);
9601f7fdc7SAnshuman Khandual }
9701f7fdc7SAnshuman Khandual shmdt(&cptr);
9801f7fdc7SAnshuman Khandual exit(1);
9901f7fdc7SAnshuman Khandual }
10001f7fdc7SAnshuman Khandual
trace_tm_spd_tar(pid_t child)10101f7fdc7SAnshuman Khandual int trace_tm_spd_tar(pid_t child)
10201f7fdc7SAnshuman Khandual {
10301f7fdc7SAnshuman Khandual unsigned long regs[3];
10401f7fdc7SAnshuman Khandual
10501f7fdc7SAnshuman Khandual FAIL_IF(start_trace(child));
10601f7fdc7SAnshuman Khandual FAIL_IF(show_tar_registers(child, regs));
10701f7fdc7SAnshuman Khandual printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
10801f7fdc7SAnshuman Khandual ptrace_read_running, regs[0], regs[1], regs[2]);
10901f7fdc7SAnshuman Khandual
11001f7fdc7SAnshuman Khandual FAIL_IF(validate_tar_registers(regs, TAR_3, PPR_3, DSCR_3));
11101f7fdc7SAnshuman Khandual FAIL_IF(show_tm_checkpointed_state(child, regs));
11201f7fdc7SAnshuman Khandual printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
11301f7fdc7SAnshuman Khandual ptrace_read_ckpt, regs[0], regs[1], regs[2]);
11401f7fdc7SAnshuman Khandual
11501f7fdc7SAnshuman Khandual FAIL_IF(validate_tar_registers(regs, TAR_1, PPR_1, DSCR_1));
11601f7fdc7SAnshuman Khandual FAIL_IF(write_ckpt_tar_registers(child, TAR_4, PPR_4, DSCR_4));
11701f7fdc7SAnshuman Khandual printf("%-30s TAR: %u PPR: %lx DSCR: %u\n",
11801f7fdc7SAnshuman Khandual ptrace_write_ckpt, TAR_4, PPR_4, DSCR_4);
11901f7fdc7SAnshuman Khandual
12001f7fdc7SAnshuman Khandual pptr[0] = 1;
12101f7fdc7SAnshuman Khandual pptr[1] = 1;
12201f7fdc7SAnshuman Khandual FAIL_IF(stop_trace(child));
12301f7fdc7SAnshuman Khandual return TEST_PASS;
12401f7fdc7SAnshuman Khandual }
12501f7fdc7SAnshuman Khandual
ptrace_tm_spd_tar(void)12601f7fdc7SAnshuman Khandual int ptrace_tm_spd_tar(void)
12701f7fdc7SAnshuman Khandual {
12801f7fdc7SAnshuman Khandual pid_t pid;
12901f7fdc7SAnshuman Khandual int ret, status;
13001f7fdc7SAnshuman Khandual
131*68877ff2SBenjamin Gray SKIP_IF_MSG(!have_htm(), "Don't have transactional memory");
132*68877ff2SBenjamin Gray SKIP_IF_MSG(htm_is_synthetic(), "Transactional memory is synthetic");
13301f7fdc7SAnshuman Khandual shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
13401f7fdc7SAnshuman Khandual pid = fork();
13501f7fdc7SAnshuman Khandual if (pid == 0)
13601f7fdc7SAnshuman Khandual tm_spd_tar();
13701f7fdc7SAnshuman Khandual
13801f7fdc7SAnshuman Khandual pptr = (int *)shmat(shm_id, NULL, 0);
13901f7fdc7SAnshuman Khandual pptr[0] = 0;
14001f7fdc7SAnshuman Khandual pptr[1] = 0;
14101f7fdc7SAnshuman Khandual
14201f7fdc7SAnshuman Khandual if (pid) {
14301f7fdc7SAnshuman Khandual while (!pptr[2])
14401f7fdc7SAnshuman Khandual asm volatile("" : : : "memory");
14501f7fdc7SAnshuman Khandual ret = trace_tm_spd_tar(pid);
14601f7fdc7SAnshuman Khandual if (ret) {
14701f7fdc7SAnshuman Khandual kill(pid, SIGTERM);
14801f7fdc7SAnshuman Khandual shmdt(&pptr);
14901f7fdc7SAnshuman Khandual shmctl(shm_id, IPC_RMID, NULL);
15001f7fdc7SAnshuman Khandual return TEST_FAIL;
15101f7fdc7SAnshuman Khandual }
15201f7fdc7SAnshuman Khandual
15301f7fdc7SAnshuman Khandual shmdt(&pptr);
15401f7fdc7SAnshuman Khandual
15501f7fdc7SAnshuman Khandual ret = wait(&status);
15601f7fdc7SAnshuman Khandual shmctl(shm_id, IPC_RMID, NULL);
15701f7fdc7SAnshuman Khandual if (ret != pid) {
15801f7fdc7SAnshuman Khandual printf("Child's exit status not captured\n");
15901f7fdc7SAnshuman Khandual return TEST_FAIL;
16001f7fdc7SAnshuman Khandual }
16101f7fdc7SAnshuman Khandual
16201f7fdc7SAnshuman Khandual return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
16301f7fdc7SAnshuman Khandual TEST_PASS;
16401f7fdc7SAnshuman Khandual }
16501f7fdc7SAnshuman Khandual return TEST_PASS;
16601f7fdc7SAnshuman Khandual }
16701f7fdc7SAnshuman Khandual
main(int argc,char * argv[])16801f7fdc7SAnshuman Khandual int main(int argc, char *argv[])
16901f7fdc7SAnshuman Khandual {
17001f7fdc7SAnshuman Khandual return test_harness(ptrace_tm_spd_tar, "ptrace_tm_spd_tar");
17101f7fdc7SAnshuman Khandual }
172