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