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 /* TAR, PPR, DSCR */ 106 int 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; 146 fail: 147 free(reg); 148 return TEST_FAIL; 149 } 150 151 int 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; 190 fail: 191 free(reg); 192 return TEST_FAIL; 193 } 194 195 int 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 237 fail: 238 free(reg); 239 return TEST_FAIL; 240 } 241 242 int 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; 281 fail: 282 free(reg); 283 return TEST_FAIL; 284 } 285 286 /* FPR */ 287 int 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 306 int 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 329 int 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 353 int 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 */ 381 int 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 406 int 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 434 int 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 463 int 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 */ 495 int 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 507 int 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 525 int 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 537 int 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 */ 555 int 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 567 int 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 584 int 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 596 int 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 */ 614 int 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 */ 644 inline 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 652 void 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 710 void store_gpr(unsigned long *addr); 711 void store_fpr(float *addr); 712