linux/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Ptrace test for TAR, PPR, DSCR registers in the TM Suspend context
   4 *
   5 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
   6 */
   7#include "ptrace.h"
   8#include "tm.h"
   9#include "ptrace-tar.h"
  10
  11int shm_id;
  12int *cptr, *pptr;
  13
  14__attribute__((used)) void wait_parent(void)
  15{
  16        cptr[2] = 1;
  17        while (!cptr[1])
  18                asm volatile("" : : : "memory");
  19}
  20
  21void tm_spd_tar(void)
  22{
  23        unsigned long result, texasr;
  24        unsigned long regs[3];
  25        int ret;
  26
  27        cptr = (int *)shmat(shm_id, NULL, 0);
  28
  29trans:
  30        cptr[2] = 0;
  31        asm __volatile__(
  32                "li     4, %[tar_1];"
  33                "mtspr %[sprn_tar],  4;"        /* TAR_1 */
  34                "li     4, %[dscr_1];"
  35                "mtspr %[sprn_dscr], 4;"        /* DSCR_1 */
  36                "or     31,31,31;"              /* PPR_1*/
  37
  38                "1: ;"
  39                "tbegin.;"
  40                "beq 2f;"
  41
  42                "li     4, %[tar_2];"
  43                "mtspr %[sprn_tar],  4;"        /* TAR_2 */
  44                "li     4, %[dscr_2];"
  45                "mtspr %[sprn_dscr], 4;"        /* DSCR_2 */
  46                "or     1,1,1;"                 /* PPR_2 */
  47
  48                "tsuspend.;"
  49                "li     4, %[tar_3];"
  50                "mtspr %[sprn_tar],  4;"        /* TAR_3 */
  51                "li     4, %[dscr_3];"
  52                "mtspr %[sprn_dscr], 4;"        /* DSCR_3 */
  53                "or     6,6,6;"                 /* PPR_3 */
  54                "bl wait_parent;"
  55                "tresume.;"
  56
  57                "tend.;"
  58                "li 0, 0;"
  59                "ori %[res], 0, 0;"
  60                "b 3f;"
  61
  62                /* Transaction abort handler */
  63                "2: ;"
  64                "li 0, 1;"
  65                "ori %[res], 0, 0;"
  66                "mfspr %[texasr], %[sprn_texasr];"
  67
  68                "3: ;"
  69
  70                : [res] "=r" (result), [texasr] "=r" (texasr)
  71                : [sprn_dscr]"i"(SPRN_DSCR),
  72                [sprn_tar]"i"(SPRN_TAR), [sprn_ppr]"i"(SPRN_PPR),
  73                [sprn_texasr]"i"(SPRN_TEXASR), [tar_1]"i"(TAR_1),
  74                [dscr_1]"i"(DSCR_1), [tar_2]"i"(TAR_2), [dscr_2]"i"(DSCR_2),
  75                [tar_3]"i"(TAR_3), [dscr_3]"i"(DSCR_3)
  76                : "memory", "r0", "r3", "r4", "r5", "r6", "lr"
  77                );
  78
  79        /* TM failed, analyse */
  80        if (result) {
  81                if (!cptr[0])
  82                        goto trans;
  83
  84                regs[0] = mfspr(SPRN_TAR);
  85                regs[1] = mfspr(SPRN_PPR);
  86                regs[2] = mfspr(SPRN_DSCR);
  87
  88                shmdt(&cptr);
  89                printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
  90                                user_read, regs[0], regs[1], regs[2]);
  91
  92                ret = validate_tar_registers(regs, TAR_4, PPR_4, DSCR_4);
  93                if (ret)
  94                        exit(1);
  95                exit(0);
  96        }
  97        shmdt(&cptr);
  98        exit(1);
  99}
 100
 101int trace_tm_spd_tar(pid_t child)
 102{
 103        unsigned long regs[3];
 104
 105        FAIL_IF(start_trace(child));
 106        FAIL_IF(show_tar_registers(child, regs));
 107        printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
 108                        ptrace_read_running, regs[0], regs[1], regs[2]);
 109
 110        FAIL_IF(validate_tar_registers(regs, TAR_3, PPR_3, DSCR_3));
 111        FAIL_IF(show_tm_checkpointed_state(child, regs));
 112        printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
 113                        ptrace_read_ckpt, regs[0], regs[1], regs[2]);
 114
 115        FAIL_IF(validate_tar_registers(regs, TAR_1, PPR_1, DSCR_1));
 116        FAIL_IF(write_ckpt_tar_registers(child, TAR_4, PPR_4, DSCR_4));
 117        printf("%-30s TAR: %u PPR: %lx DSCR: %u\n",
 118                        ptrace_write_ckpt, TAR_4, PPR_4, DSCR_4);
 119
 120        pptr[0] = 1;
 121        pptr[1] = 1;
 122        FAIL_IF(stop_trace(child));
 123        return TEST_PASS;
 124}
 125
 126int ptrace_tm_spd_tar(void)
 127{
 128        pid_t pid;
 129        int ret, status;
 130
 131        SKIP_IF(!have_htm());
 132        SKIP_IF(htm_is_synthetic());
 133        shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
 134        pid = fork();
 135        if (pid == 0)
 136                tm_spd_tar();
 137
 138        pptr = (int *)shmat(shm_id, NULL, 0);
 139        pptr[0] = 0;
 140        pptr[1] = 0;
 141
 142        if (pid) {
 143                while (!pptr[2])
 144                        asm volatile("" : : : "memory");
 145                ret = trace_tm_spd_tar(pid);
 146                if (ret) {
 147                        kill(pid, SIGTERM);
 148                        shmdt(&pptr);
 149                        shmctl(shm_id, IPC_RMID, NULL);
 150                        return TEST_FAIL;
 151                }
 152
 153                shmdt(&pptr);
 154
 155                ret = wait(&status);
 156                shmctl(shm_id, IPC_RMID, NULL);
 157                if (ret != pid) {
 158                        printf("Child's exit status not captured\n");
 159                        return TEST_FAIL;
 160                }
 161
 162                return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
 163                        TEST_PASS;
 164        }
 165        return TEST_PASS;
 166}
 167
 168int main(int argc, char *argv[])
 169{
 170        return test_harness(ptrace_tm_spd_tar, "ptrace_tm_spd_tar");
 171}
 172