linux/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c
<<
>>
Prefs
   1/*
   2 * Ptrace test TM SPR registers
   3 *
   4 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11#include "ptrace.h"
  12#include "tm.h"
  13
  14/* Tracee and tracer shared data */
  15struct shared {
  16        int flag;
  17        struct tm_spr_regs regs;
  18};
  19unsigned long tfhar;
  20
  21int shm_id;
  22struct shared *cptr, *pptr;
  23
  24int shm_id1;
  25int *cptr1, *pptr1;
  26
  27#define TM_KVM_SCHED   0xe0000001ac000001
  28int validate_tm_spr(struct tm_spr_regs *regs)
  29{
  30        FAIL_IF(regs->tm_tfhar != tfhar);
  31        FAIL_IF((regs->tm_texasr == TM_KVM_SCHED) && (regs->tm_tfiar != 0));
  32
  33        return TEST_PASS;
  34}
  35
  36void tm_spr(void)
  37{
  38        unsigned long result, texasr;
  39        int ret;
  40
  41        cptr = (struct shared *)shmat(shm_id, NULL, 0);
  42        cptr1 = (int *)shmat(shm_id1, NULL, 0);
  43
  44trans:
  45        cptr1[0] = 0;
  46        asm __volatile__(
  47                "1: ;"
  48                /* TM failover handler should follow "tbegin.;" */
  49                "mflr 31;"
  50                "bl 4f;"        /* $ = TFHAR - 12 */
  51                "4: ;"
  52                "mflr %[tfhar];"
  53                "mtlr 31;"
  54
  55                "tbegin.;"
  56                "beq 2f;"
  57
  58                "tsuspend.;"
  59                "li 8, 1;"
  60                "sth 8, 0(%[cptr1]);"
  61                "tresume.;"
  62                "b .;"
  63
  64                "tend.;"
  65                "li 0, 0;"
  66                "ori %[res], 0, 0;"
  67                "b 3f;"
  68
  69                "2: ;"
  70
  71                "li 0, 1;"
  72                "ori %[res], 0, 0;"
  73                "mfspr %[texasr], %[sprn_texasr];"
  74
  75                "3: ;"
  76                : [tfhar] "=r" (tfhar), [res] "=r" (result),
  77                [texasr] "=r" (texasr), [cptr1] "=r" (cptr1)
  78                : [sprn_texasr] "i"  (SPRN_TEXASR)
  79                : "memory", "r0", "r8", "r31"
  80                );
  81
  82        /* There are 2 32bit instructions before tbegin. */
  83        tfhar += 12;
  84
  85        if (result) {
  86                if (!cptr->flag)
  87                        goto trans;
  88
  89                ret = validate_tm_spr((struct tm_spr_regs *)&cptr->regs);
  90                shmdt((void *)cptr);
  91                shmdt((void *)cptr1);
  92                if (ret)
  93                        exit(1);
  94                exit(0);
  95        }
  96        shmdt((void *)cptr);
  97        shmdt((void *)cptr1);
  98        exit(1);
  99}
 100
 101int trace_tm_spr(pid_t child)
 102{
 103        FAIL_IF(start_trace(child));
 104        FAIL_IF(show_tm_spr(child, (struct tm_spr_regs *)&pptr->regs));
 105
 106        printf("TFHAR: %lx TEXASR: %lx TFIAR: %lx\n", pptr->regs.tm_tfhar,
 107                                pptr->regs.tm_texasr, pptr->regs.tm_tfiar);
 108
 109        pptr->flag = 1;
 110        FAIL_IF(stop_trace(child));
 111
 112        return TEST_PASS;
 113}
 114
 115int ptrace_tm_spr(void)
 116{
 117        pid_t pid;
 118        int ret, status;
 119
 120        SKIP_IF(!have_htm());
 121        shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT);
 122        shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
 123        pid = fork();
 124        if (pid < 0) {
 125                perror("fork() failed");
 126                return TEST_FAIL;
 127        }
 128
 129        if (pid == 0)
 130                tm_spr();
 131
 132        if (pid) {
 133                pptr = (struct shared *)shmat(shm_id, NULL, 0);
 134                pptr1 = (int *)shmat(shm_id1, NULL, 0);
 135
 136                while (!pptr1[0])
 137                        asm volatile("" : : : "memory");
 138                ret = trace_tm_spr(pid);
 139                if (ret) {
 140                        kill(pid, SIGKILL);
 141                        shmdt((void *)pptr);
 142                        shmdt((void *)pptr1);
 143                        shmctl(shm_id, IPC_RMID, NULL);
 144                        shmctl(shm_id1, IPC_RMID, NULL);
 145                        return TEST_FAIL;
 146                }
 147
 148                shmdt((void *)pptr);
 149                shmdt((void *)pptr1);
 150                ret = wait(&status);
 151                shmctl(shm_id, IPC_RMID, NULL);
 152                shmctl(shm_id1, IPC_RMID, NULL);
 153                if (ret != pid) {
 154                        printf("Child's exit status not captured\n");
 155                        return TEST_FAIL;
 156                }
 157
 158                return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
 159                        TEST_PASS;
 160        }
 161        return TEST_PASS;
 162}
 163
 164int main(int argc, char *argv[])
 165{
 166        return test_harness(ptrace_tm_spr, "ptrace_tm_spr");
 167}
 168