linux/tools/testing/selftests/powerpc/ptrace/ptrace.h
<<
>>
Prefs
   1/*
   2 * Ptrace interface test helper functions
   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 <inttypes.h>
  12#include <unistd.h>
  13#include <stdlib.h>
  14#include <string.h>
  15#include <malloc.h>
  16#include <errno.h>
  17#include <time.h>
  18#include <sys/ptrace.h>
  19#include <sys/ioctl.h>
  20#include <sys/uio.h>
  21#include <sys/types.h>
  22#include <sys/wait.h>
  23#include <sys/signal.h>
  24#include <sys/ipc.h>
  25#include <sys/shm.h>
  26#include <sys/user.h>
  27#include <linux/elf.h>
  28#include <linux/types.h>
  29#include <linux/auxvec.h>
  30#include "reg.h"
  31#include "utils.h"
  32
  33#define TEST_PASS 0
  34#define TEST_FAIL 1
  35
  36struct fpr_regs {
  37        unsigned long fpr[32];
  38        unsigned long fpscr;
  39};
  40
  41struct tm_spr_regs {
  42        unsigned long tm_tfhar;
  43        unsigned long tm_texasr;
  44        unsigned long tm_tfiar;
  45};
  46
  47#ifndef NT_PPC_TAR
  48#define NT_PPC_TAR      0x103
  49#define NT_PPC_PPR      0x104
  50#define NT_PPC_DSCR     0x105
  51#define NT_PPC_EBB      0x106
  52#define NT_PPC_PMU      0x107
  53#define NT_PPC_TM_CGPR  0x108
  54#define NT_PPC_TM_CFPR  0x109
  55#define NT_PPC_TM_CVMX  0x10a
  56#define NT_PPC_TM_CVSX  0x10b
  57#define NT_PPC_TM_SPR   0x10c
  58#define NT_PPC_TM_CTAR  0x10d
  59#define NT_PPC_TM_CPPR  0x10e
  60#define NT_PPC_TM_CDSCR 0x10f
  61#endif
  62
  63/* Basic ptrace operations */
  64int start_trace(pid_t child)
  65{
  66        int ret;
  67
  68        ret = ptrace(PTRACE_ATTACH, child, NULL, NULL);
  69        if (ret) {
  70                perror("ptrace(PTRACE_ATTACH) failed");
  71                return TEST_FAIL;
  72        }
  73        ret = waitpid(child, NULL, 0);
  74        if (ret != child) {
  75                perror("waitpid() failed");
  76                return TEST_FAIL;
  77        }
  78        return TEST_PASS;
  79}
  80
  81int stop_trace(pid_t child)
  82{
  83        int ret;
  84
  85        ret = ptrace(PTRACE_DETACH, child, NULL, NULL);
  86        if (ret) {
  87                perror("ptrace(PTRACE_DETACH) failed");
  88                return TEST_FAIL;
  89        }
  90        return TEST_PASS;
  91}
  92
  93int cont_trace(pid_t child)
  94{
  95        int ret;
  96
  97        ret = ptrace(PTRACE_CONT, child, NULL, NULL);
  98        if (ret) {
  99                perror("ptrace(PTRACE_CONT) failed");
 100                return TEST_FAIL;
 101        }
 102        return TEST_PASS;
 103}
 104
 105/* TAR, PPR, DSCR */
 106int show_tar_registers(pid_t child, unsigned long *out)
 107{
 108        struct iovec iov;
 109        unsigned long *reg;
 110        int ret;
 111
 112        reg = malloc(sizeof(unsigned long));
 113        if (!reg) {
 114                perror("malloc() failed");
 115                return TEST_FAIL;
 116        }
 117        iov.iov_base = (u64 *) reg;
 118        iov.iov_len = sizeof(unsigned long);
 119
 120        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TAR, &iov);
 121        if (ret) {
 122                perror("ptrace(PTRACE_GETREGSET) failed");
 123                goto fail;
 124        }
 125        if (out)
 126                out[0] = *reg;
 127
 128        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_PPR, &iov);
 129        if (ret) {
 130                perror("ptrace(PTRACE_GETREGSET) failed");
 131                goto fail;
 132        }
 133        if (out)
 134                out[1] = *reg;
 135
 136        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_DSCR, &iov);
 137        if (ret) {
 138                perror("ptrace(PTRACE_GETREGSET) failed");
 139                goto fail;
 140        }
 141        if (out)
 142                out[2] = *reg;
 143
 144        free(reg);
 145        return TEST_PASS;
 146fail:
 147        free(reg);
 148        return TEST_FAIL;
 149}
 150
 151int write_tar_registers(pid_t child, unsigned long tar,
 152                unsigned long ppr, unsigned long dscr)
 153{
 154        struct iovec iov;
 155        unsigned long *reg;
 156        int ret;
 157
 158        reg = malloc(sizeof(unsigned long));
 159        if (!reg) {
 160                perror("malloc() failed");
 161                return TEST_FAIL;
 162        }
 163
 164        iov.iov_base = (u64 *) reg;
 165        iov.iov_len = sizeof(unsigned long);
 166
 167        *reg = tar;
 168        ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TAR, &iov);
 169        if (ret) {
 170                perror("ptrace(PTRACE_SETREGSET) failed");
 171                goto fail;
 172        }
 173
 174        *reg = ppr;
 175        ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_PPR, &iov);
 176        if (ret) {
 177                perror("ptrace(PTRACE_SETREGSET) failed");
 178                goto fail;
 179        }
 180
 181        *reg = dscr;
 182        ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_DSCR, &iov);
 183        if (ret) {
 184                perror("ptrace(PTRACE_SETREGSET) failed");
 185                goto fail;
 186        }
 187
 188        free(reg);
 189        return TEST_PASS;
 190fail:
 191        free(reg);
 192        return TEST_FAIL;
 193}
 194
 195int show_tm_checkpointed_state(pid_t child, unsigned long *out)
 196{
 197        struct iovec iov;
 198        unsigned long *reg;
 199        int ret;
 200
 201        reg = malloc(sizeof(unsigned long));
 202        if (!reg) {
 203                perror("malloc() failed");
 204                return TEST_FAIL;
 205        }
 206
 207        iov.iov_base = (u64 *) reg;
 208        iov.iov_len = sizeof(unsigned long);
 209
 210        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CTAR, &iov);
 211        if (ret) {
 212                perror("ptrace(PTRACE_GETREGSET) failed");
 213                goto fail;
 214        }
 215        if (out)
 216                out[0] = *reg;
 217
 218        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CPPR, &iov);
 219        if (ret) {
 220                perror("ptrace(PTRACE_GETREGSET) failed");
 221                goto fail;
 222        }
 223        if (out)
 224                out[1] = *reg;
 225
 226        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CDSCR, &iov);
 227        if (ret) {
 228                perror("ptrace(PTRACE_GETREGSET) failed");
 229                goto fail;
 230        }
 231        if (out)
 232                out[2] = *reg;
 233
 234        free(reg);
 235        return TEST_PASS;
 236
 237fail:
 238        free(reg);
 239        return TEST_FAIL;
 240}
 241
 242int write_ckpt_tar_registers(pid_t child, unsigned long tar,
 243                unsigned long ppr, unsigned long dscr)
 244{
 245        struct iovec iov;
 246        unsigned long *reg;
 247        int ret;
 248
 249        reg = malloc(sizeof(unsigned long));
 250        if (!reg) {
 251                perror("malloc() failed");
 252                return TEST_FAIL;
 253        }
 254
 255        iov.iov_base = (u64 *) reg;
 256        iov.iov_len = sizeof(unsigned long);
 257
 258        *reg = tar;
 259        ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CTAR, &iov);
 260        if (ret) {
 261                perror("ptrace(PTRACE_GETREGSET) failed");
 262                goto fail;
 263        }
 264
 265        *reg = ppr;
 266        ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CPPR, &iov);
 267        if (ret) {
 268                perror("ptrace(PTRACE_GETREGSET) failed");
 269                goto fail;
 270        }
 271
 272        *reg = dscr;
 273        ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CDSCR, &iov);
 274        if (ret) {
 275                perror("ptrace(PTRACE_GETREGSET) failed");
 276                goto fail;
 277        }
 278
 279        free(reg);
 280        return TEST_PASS;
 281fail:
 282        free(reg);
 283        return TEST_FAIL;
 284}
 285
 286/* FPR */
 287int show_fpr(pid_t child, unsigned long *fpr)
 288{
 289        struct fpr_regs *regs;
 290        int ret, i;
 291
 292        regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
 293        ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);
 294        if (ret) {
 295                perror("ptrace(PTRACE_GETREGSET) failed");
 296                return TEST_FAIL;
 297        }
 298
 299        if (fpr) {
 300                for (i = 0; i < 32; i++)
 301                        fpr[i] = regs->fpr[i];
 302        }
 303        return TEST_PASS;
 304}
 305
 306int write_fpr(pid_t child, unsigned long val)
 307{
 308        struct fpr_regs *regs;
 309        int ret, i;
 310
 311        regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
 312        ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);
 313        if (ret) {
 314                perror("ptrace(PTRACE_GETREGSET) failed");
 315                return TEST_FAIL;
 316        }
 317
 318        for (i = 0; i < 32; i++)
 319                regs->fpr[i] = val;
 320
 321        ret = ptrace(PTRACE_SETFPREGS, child, NULL, regs);
 322        if (ret) {
 323                perror("ptrace(PTRACE_GETREGSET) failed");
 324                return TEST_FAIL;
 325        }
 326        return TEST_PASS;
 327}
 328
 329int show_ckpt_fpr(pid_t child, unsigned long *fpr)
 330{
 331        struct fpr_regs *regs;
 332        struct iovec iov;
 333        int ret, i;
 334
 335        regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
 336        iov.iov_base = regs;
 337        iov.iov_len = sizeof(struct fpr_regs);
 338
 339        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
 340        if (ret) {
 341                perror("ptrace(PTRACE_GETREGSET) failed");
 342                return TEST_FAIL;
 343        }
 344
 345        if (fpr) {
 346                for (i = 0; i < 32; i++)
 347                        fpr[i] = regs->fpr[i];
 348        }
 349
 350        return TEST_PASS;
 351}
 352
 353int write_ckpt_fpr(pid_t child, unsigned long val)
 354{
 355        struct fpr_regs *regs;
 356        struct iovec iov;
 357        int ret, i;
 358
 359        regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
 360        iov.iov_base = regs;
 361        iov.iov_len = sizeof(struct fpr_regs);
 362
 363        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
 364        if (ret) {
 365                perror("ptrace(PTRACE_GETREGSET) failed");
 366                return TEST_FAIL;
 367        }
 368
 369        for (i = 0; i < 32; i++)
 370                regs->fpr[i] = val;
 371
 372        ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CFPR, &iov);
 373        if (ret) {
 374                perror("ptrace(PTRACE_GETREGSET) failed");
 375                return TEST_FAIL;
 376        }
 377        return TEST_PASS;
 378}
 379
 380/* GPR */
 381int show_gpr(pid_t child, unsigned long *gpr)
 382{
 383        struct pt_regs *regs;
 384        int ret, i;
 385
 386        regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
 387        if (!regs) {
 388                perror("malloc() failed");
 389                return TEST_FAIL;
 390        }
 391
 392        ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
 393        if (ret) {
 394                perror("ptrace(PTRACE_GETREGSET) failed");
 395                return TEST_FAIL;
 396        }
 397
 398        if (gpr) {
 399                for (i = 14; i < 32; i++)
 400                        gpr[i-14] = regs->gpr[i];
 401        }
 402
 403        return TEST_PASS;
 404}
 405
 406int write_gpr(pid_t child, unsigned long val)
 407{
 408        struct pt_regs *regs;
 409        int i, ret;
 410
 411        regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
 412        if (!regs) {
 413                perror("malloc() failed");
 414                return TEST_FAIL;
 415        }
 416
 417        ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
 418        if (ret) {
 419                perror("ptrace(PTRACE_GETREGSET) failed");
 420                return TEST_FAIL;
 421        }
 422
 423        for (i = 14; i < 32; i++)
 424                regs->gpr[i] = val;
 425
 426        ret = ptrace(PTRACE_SETREGS, child, NULL, regs);
 427        if (ret) {
 428                perror("ptrace(PTRACE_GETREGSET) failed");
 429                return TEST_FAIL;
 430        }
 431        return TEST_PASS;
 432}
 433
 434int show_ckpt_gpr(pid_t child, unsigned long *gpr)
 435{
 436        struct pt_regs *regs;
 437        struct iovec iov;
 438        int ret, i;
 439
 440        regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
 441        if (!regs) {
 442                perror("malloc() failed");
 443                return TEST_FAIL;
 444        }
 445
 446        iov.iov_base = (u64 *) regs;
 447        iov.iov_len = sizeof(struct pt_regs);
 448
 449        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
 450        if (ret) {
 451                perror("ptrace(PTRACE_GETREGSET) failed");
 452                return TEST_FAIL;
 453        }
 454
 455        if (gpr) {
 456                for (i = 14; i < 32; i++)
 457                        gpr[i-14] = regs->gpr[i];
 458        }
 459
 460        return TEST_PASS;
 461}
 462
 463int write_ckpt_gpr(pid_t child, unsigned long val)
 464{
 465        struct pt_regs *regs;
 466        struct iovec iov;
 467        int ret, i;
 468
 469        regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
 470        if (!regs) {
 471                perror("malloc() failed\n");
 472                return TEST_FAIL;
 473        }
 474        iov.iov_base = (u64 *) regs;
 475        iov.iov_len = sizeof(struct pt_regs);
 476
 477        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
 478        if (ret) {
 479                perror("ptrace(PTRACE_GETREGSET) failed");
 480                return TEST_FAIL;
 481        }
 482
 483        for (i = 14; i < 32; i++)
 484                regs->gpr[i] = val;
 485
 486        ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CGPR, &iov);
 487        if (ret) {
 488                perror("ptrace(PTRACE_GETREGSET) failed");
 489                return TEST_FAIL;
 490        }
 491        return TEST_PASS;
 492}
 493
 494/* VMX */
 495int show_vmx(pid_t child, unsigned long vmx[][2])
 496{
 497        int ret;
 498
 499        ret = ptrace(PTRACE_GETVRREGS, child, 0, vmx);
 500        if (ret) {
 501                perror("ptrace(PTRACE_GETVRREGS) failed");
 502                return TEST_FAIL;
 503        }
 504        return TEST_PASS;
 505}
 506
 507int show_vmx_ckpt(pid_t child, unsigned long vmx[][2])
 508{
 509        unsigned long regs[34][2];
 510        struct iovec iov;
 511        int ret;
 512
 513        iov.iov_base = (u64 *) regs;
 514        iov.iov_len = sizeof(regs);
 515        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVMX, &iov);
 516        if (ret) {
 517                perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVMX) failed");
 518                return TEST_FAIL;
 519        }
 520        memcpy(vmx, regs, sizeof(regs));
 521        return TEST_PASS;
 522}
 523
 524
 525int write_vmx(pid_t child, unsigned long vmx[][2])
 526{
 527        int ret;
 528
 529        ret = ptrace(PTRACE_SETVRREGS, child, 0, vmx);
 530        if (ret) {
 531                perror("ptrace(PTRACE_SETVRREGS) failed");
 532                return TEST_FAIL;
 533        }
 534        return TEST_PASS;
 535}
 536
 537int write_vmx_ckpt(pid_t child, unsigned long vmx[][2])
 538{
 539        unsigned long regs[34][2];
 540        struct iovec iov;
 541        int ret;
 542
 543        memcpy(regs, vmx, sizeof(regs));
 544        iov.iov_base = (u64 *) regs;
 545        iov.iov_len = sizeof(regs);
 546        ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVMX, &iov);
 547        if (ret) {
 548                perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVMX) failed");
 549                return TEST_FAIL;
 550        }
 551        return TEST_PASS;
 552}
 553
 554/* VSX */
 555int show_vsx(pid_t child, unsigned long *vsx)
 556{
 557        int ret;
 558
 559        ret = ptrace(PTRACE_GETVSRREGS, child, 0, vsx);
 560        if (ret) {
 561                perror("ptrace(PTRACE_GETVSRREGS) failed");
 562                return TEST_FAIL;
 563        }
 564        return TEST_PASS;
 565}
 566
 567int show_vsx_ckpt(pid_t child, unsigned long *vsx)
 568{
 569        unsigned long regs[32];
 570        struct iovec iov;
 571        int ret;
 572
 573        iov.iov_base = (u64 *) regs;
 574        iov.iov_len = sizeof(regs);
 575        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVSX, &iov);
 576        if (ret) {
 577                perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVSX) failed");
 578                return TEST_FAIL;
 579        }
 580        memcpy(vsx, regs, sizeof(regs));
 581        return TEST_PASS;
 582}
 583
 584int write_vsx(pid_t child, unsigned long *vsx)
 585{
 586        int ret;
 587
 588        ret = ptrace(PTRACE_SETVSRREGS, child, 0, vsx);
 589        if (ret) {
 590                perror("ptrace(PTRACE_SETVSRREGS) failed");
 591                return TEST_FAIL;
 592        }
 593        return TEST_PASS;
 594}
 595
 596int write_vsx_ckpt(pid_t child, unsigned long *vsx)
 597{
 598        unsigned long regs[32];
 599        struct iovec iov;
 600        int ret;
 601
 602        memcpy(regs, vsx, sizeof(regs));
 603        iov.iov_base = (u64 *) regs;
 604        iov.iov_len = sizeof(regs);
 605        ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVSX, &iov);
 606        if (ret) {
 607                perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVSX) failed");
 608                return TEST_FAIL;
 609        }
 610        return TEST_PASS;
 611}
 612
 613/* TM SPR */
 614int show_tm_spr(pid_t child, struct tm_spr_regs *out)
 615{
 616        struct tm_spr_regs *regs;
 617        struct iovec iov;
 618        int ret;
 619
 620        regs = (struct tm_spr_regs *) malloc(sizeof(struct tm_spr_regs));
 621        if (!regs) {
 622                perror("malloc() failed");
 623                return TEST_FAIL;
 624        }
 625
 626        iov.iov_base = (u64 *) regs;
 627        iov.iov_len = sizeof(struct tm_spr_regs);
 628
 629        ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_SPR, &iov);
 630        if (ret) {
 631                perror("ptrace(PTRACE_GETREGSET) failed");
 632                return TEST_FAIL;
 633        }
 634
 635        if (out)
 636                memcpy(out, regs, sizeof(struct tm_spr_regs));
 637
 638        return TEST_PASS;
 639}
 640
 641
 642
 643/* Analyse TEXASR after TM failure */
 644inline unsigned long get_tfiar(void)
 645{
 646        unsigned long ret;
 647
 648        asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_TFIAR));
 649        return ret;
 650}
 651
 652void analyse_texasr(unsigned long texasr)
 653{
 654        printf("TEXASR: %16lx\t", texasr);
 655
 656        if (texasr & TEXASR_FP)
 657                printf("TEXASR_FP  ");
 658
 659        if (texasr & TEXASR_DA)
 660                printf("TEXASR_DA  ");
 661
 662        if (texasr & TEXASR_NO)
 663                printf("TEXASR_NO  ");
 664
 665        if (texasr & TEXASR_FO)
 666                printf("TEXASR_FO  ");
 667
 668        if (texasr & TEXASR_SIC)
 669                printf("TEXASR_SIC  ");
 670
 671        if (texasr & TEXASR_NTC)
 672                printf("TEXASR_NTC  ");
 673
 674        if (texasr & TEXASR_TC)
 675                printf("TEXASR_TC  ");
 676
 677        if (texasr & TEXASR_TIC)
 678                printf("TEXASR_TIC  ");
 679
 680        if (texasr & TEXASR_IC)
 681                printf("TEXASR_IC  ");
 682
 683        if (texasr & TEXASR_IFC)
 684                printf("TEXASR_IFC  ");
 685
 686        if (texasr & TEXASR_ABT)
 687                printf("TEXASR_ABT  ");
 688
 689        if (texasr & TEXASR_SPD)
 690                printf("TEXASR_SPD  ");
 691
 692        if (texasr & TEXASR_HV)
 693                printf("TEXASR_HV  ");
 694
 695        if (texasr & TEXASR_PR)
 696                printf("TEXASR_PR  ");
 697
 698        if (texasr & TEXASR_FS)
 699                printf("TEXASR_FS  ");
 700
 701        if (texasr & TEXASR_TE)
 702                printf("TEXASR_TE  ");
 703
 704        if (texasr & TEXASR_ROT)
 705                printf("TEXASR_ROT  ");
 706
 707        printf("TFIAR :%lx\n", get_tfiar());
 708}
 709
 710void store_gpr(unsigned long *addr);
 711void store_fpr(float *addr);
 712