1 /* ptrace.c: Sparc process tracing support. 2 * 3 * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net) 4 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 5 * 6 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson, 7 * and David Mosberger. 8 * 9 * Added Linux support -miguel (weird, eh?, the original code was meant 10 * to emulate SunOS). 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/sched.h> 15 #include <linux/mm.h> 16 #include <linux/errno.h> 17 #include <linux/ptrace.h> 18 #include <linux/user.h> 19 #include <linux/smp.h> 20 #include <linux/security.h> 21 #include <linux/seccomp.h> 22 #include <linux/audit.h> 23 #include <linux/signal.h> 24 #include <linux/regset.h> 25 #include <linux/tracehook.h> 26 #include <trace/syscall.h> 27 #include <linux/compat.h> 28 #include <linux/elf.h> 29 30 #include <asm/asi.h> 31 #include <asm/pgtable.h> 32 #include <asm/uaccess.h> 33 #include <asm/psrcompat.h> 34 #include <asm/visasm.h> 35 #include <asm/spitfire.h> 36 #include <asm/page.h> 37 #include <asm/cpudata.h> 38 #include <asm/cacheflush.h> 39 40 #define CREATE_TRACE_POINTS 41 #include <trace/events/syscalls.h> 42 43 #include "entry.h" 44 45 /* #define ALLOW_INIT_TRACING */ 46 47 /* 48 * Called by kernel/ptrace.c when detaching.. 49 * 50 * Make sure single step bits etc are not set. 51 */ 52 void ptrace_disable(struct task_struct *child) 53 { 54 /* nothing to do */ 55 } 56 57 /* To get the necessary page struct, access_process_vm() first calls 58 * get_user_pages(). This has done a flush_dcache_page() on the 59 * accessed page. Then our caller (copy_{to,from}_user_page()) did 60 * to memcpy to read/write the data from that page. 61 * 62 * Now, the only thing we have to do is: 63 * 1) flush the D-cache if it's possible than an illegal alias 64 * has been created 65 * 2) flush the I-cache if this is pre-cheetah and we did a write 66 */ 67 void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, 68 unsigned long uaddr, void *kaddr, 69 unsigned long len, int write) 70 { 71 BUG_ON(len > PAGE_SIZE); 72 73 if (tlb_type == hypervisor) 74 return; 75 76 preempt_disable(); 77 78 #ifdef DCACHE_ALIASING_POSSIBLE 79 /* If bit 13 of the kernel address we used to access the 80 * user page is the same as the virtual address that page 81 * is mapped to in the user's address space, we can skip the 82 * D-cache flush. 83 */ 84 if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) { 85 unsigned long start = __pa(kaddr); 86 unsigned long end = start + len; 87 unsigned long dcache_line_size; 88 89 dcache_line_size = local_cpu_data().dcache_line_size; 90 91 if (tlb_type == spitfire) { 92 for (; start < end; start += dcache_line_size) 93 spitfire_put_dcache_tag(start & 0x3fe0, 0x0); 94 } else { 95 start &= ~(dcache_line_size - 1); 96 for (; start < end; start += dcache_line_size) 97 __asm__ __volatile__( 98 "stxa %%g0, [%0] %1\n\t" 99 "membar #Sync" 100 : /* no outputs */ 101 : "r" (start), 102 "i" (ASI_DCACHE_INVALIDATE)); 103 } 104 } 105 #endif 106 if (write && tlb_type == spitfire) { 107 unsigned long start = (unsigned long) kaddr; 108 unsigned long end = start + len; 109 unsigned long icache_line_size; 110 111 icache_line_size = local_cpu_data().icache_line_size; 112 113 for (; start < end; start += icache_line_size) 114 flushi(start); 115 } 116 117 preempt_enable(); 118 } 119 120 static int get_from_target(struct task_struct *target, unsigned long uaddr, 121 void *kbuf, int len) 122 { 123 if (target == current) { 124 if (copy_from_user(kbuf, (void __user *) uaddr, len)) 125 return -EFAULT; 126 } else { 127 int len2 = access_process_vm(target, uaddr, kbuf, len, 0); 128 if (len2 != len) 129 return -EFAULT; 130 } 131 return 0; 132 } 133 134 static int set_to_target(struct task_struct *target, unsigned long uaddr, 135 void *kbuf, int len) 136 { 137 if (target == current) { 138 if (copy_to_user((void __user *) uaddr, kbuf, len)) 139 return -EFAULT; 140 } else { 141 int len2 = access_process_vm(target, uaddr, kbuf, len, 1); 142 if (len2 != len) 143 return -EFAULT; 144 } 145 return 0; 146 } 147 148 static int regwindow64_get(struct task_struct *target, 149 const struct pt_regs *regs, 150 struct reg_window *wbuf) 151 { 152 unsigned long rw_addr = regs->u_regs[UREG_I6]; 153 154 if (!test_thread_64bit_stack(rw_addr)) { 155 struct reg_window32 win32; 156 int i; 157 158 if (get_from_target(target, rw_addr, &win32, sizeof(win32))) 159 return -EFAULT; 160 for (i = 0; i < 8; i++) 161 wbuf->locals[i] = win32.locals[i]; 162 for (i = 0; i < 8; i++) 163 wbuf->ins[i] = win32.ins[i]; 164 } else { 165 rw_addr += STACK_BIAS; 166 if (get_from_target(target, rw_addr, wbuf, sizeof(*wbuf))) 167 return -EFAULT; 168 } 169 170 return 0; 171 } 172 173 static int regwindow64_set(struct task_struct *target, 174 const struct pt_regs *regs, 175 struct reg_window *wbuf) 176 { 177 unsigned long rw_addr = regs->u_regs[UREG_I6]; 178 179 if (!test_thread_64bit_stack(rw_addr)) { 180 struct reg_window32 win32; 181 int i; 182 183 for (i = 0; i < 8; i++) 184 win32.locals[i] = wbuf->locals[i]; 185 for (i = 0; i < 8; i++) 186 win32.ins[i] = wbuf->ins[i]; 187 188 if (set_to_target(target, rw_addr, &win32, sizeof(win32))) 189 return -EFAULT; 190 } else { 191 rw_addr += STACK_BIAS; 192 if (set_to_target(target, rw_addr, wbuf, sizeof(*wbuf))) 193 return -EFAULT; 194 } 195 196 return 0; 197 } 198 199 enum sparc_regset { 200 REGSET_GENERAL, 201 REGSET_FP, 202 }; 203 204 static int genregs64_get(struct task_struct *target, 205 const struct user_regset *regset, 206 unsigned int pos, unsigned int count, 207 void *kbuf, void __user *ubuf) 208 { 209 const struct pt_regs *regs = task_pt_regs(target); 210 int ret; 211 212 if (target == current) 213 flushw_user(); 214 215 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 216 regs->u_regs, 217 0, 16 * sizeof(u64)); 218 if (!ret && count && pos < (32 * sizeof(u64))) { 219 struct reg_window window; 220 221 if (regwindow64_get(target, regs, &window)) 222 return -EFAULT; 223 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 224 &window, 225 16 * sizeof(u64), 226 32 * sizeof(u64)); 227 } 228 229 if (!ret) { 230 /* TSTATE, TPC, TNPC */ 231 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 232 ®s->tstate, 233 32 * sizeof(u64), 234 35 * sizeof(u64)); 235 } 236 237 if (!ret) { 238 unsigned long y = regs->y; 239 240 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 241 &y, 242 35 * sizeof(u64), 243 36 * sizeof(u64)); 244 } 245 246 if (!ret) { 247 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 248 36 * sizeof(u64), -1); 249 250 } 251 return ret; 252 } 253 254 static int genregs64_set(struct task_struct *target, 255 const struct user_regset *regset, 256 unsigned int pos, unsigned int count, 257 const void *kbuf, const void __user *ubuf) 258 { 259 struct pt_regs *regs = task_pt_regs(target); 260 int ret; 261 262 if (target == current) 263 flushw_user(); 264 265 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 266 regs->u_regs, 267 0, 16 * sizeof(u64)); 268 if (!ret && count && pos < (32 * sizeof(u64))) { 269 struct reg_window window; 270 271 if (regwindow64_get(target, regs, &window)) 272 return -EFAULT; 273 274 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 275 &window, 276 16 * sizeof(u64), 277 32 * sizeof(u64)); 278 279 if (!ret && 280 regwindow64_set(target, regs, &window)) 281 return -EFAULT; 282 } 283 284 if (!ret && count > 0) { 285 unsigned long tstate; 286 287 /* TSTATE */ 288 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 289 &tstate, 290 32 * sizeof(u64), 291 33 * sizeof(u64)); 292 if (!ret) { 293 /* Only the condition codes and the "in syscall" 294 * state can be modified in the %tstate register. 295 */ 296 tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); 297 regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); 298 regs->tstate |= tstate; 299 } 300 } 301 302 if (!ret) { 303 /* TPC, TNPC */ 304 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 305 ®s->tpc, 306 33 * sizeof(u64), 307 35 * sizeof(u64)); 308 } 309 310 if (!ret) { 311 unsigned long y; 312 313 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 314 &y, 315 35 * sizeof(u64), 316 36 * sizeof(u64)); 317 if (!ret) 318 regs->y = y; 319 } 320 321 if (!ret) 322 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 323 36 * sizeof(u64), -1); 324 325 return ret; 326 } 327 328 static int fpregs64_get(struct task_struct *target, 329 const struct user_regset *regset, 330 unsigned int pos, unsigned int count, 331 void *kbuf, void __user *ubuf) 332 { 333 const unsigned long *fpregs = task_thread_info(target)->fpregs; 334 unsigned long fprs, fsr, gsr; 335 int ret; 336 337 if (target == current) 338 save_and_clear_fpu(); 339 340 fprs = task_thread_info(target)->fpsaved[0]; 341 342 if (fprs & FPRS_DL) 343 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 344 fpregs, 345 0, 16 * sizeof(u64)); 346 else 347 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 348 0, 349 16 * sizeof(u64)); 350 351 if (!ret) { 352 if (fprs & FPRS_DU) 353 ret = user_regset_copyout(&pos, &count, 354 &kbuf, &ubuf, 355 fpregs + 16, 356 16 * sizeof(u64), 357 32 * sizeof(u64)); 358 else 359 ret = user_regset_copyout_zero(&pos, &count, 360 &kbuf, &ubuf, 361 16 * sizeof(u64), 362 32 * sizeof(u64)); 363 } 364 365 if (fprs & FPRS_FEF) { 366 fsr = task_thread_info(target)->xfsr[0]; 367 gsr = task_thread_info(target)->gsr[0]; 368 } else { 369 fsr = gsr = 0; 370 } 371 372 if (!ret) 373 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 374 &fsr, 375 32 * sizeof(u64), 376 33 * sizeof(u64)); 377 if (!ret) 378 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 379 &gsr, 380 33 * sizeof(u64), 381 34 * sizeof(u64)); 382 if (!ret) 383 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 384 &fprs, 385 34 * sizeof(u64), 386 35 * sizeof(u64)); 387 388 if (!ret) 389 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 390 35 * sizeof(u64), -1); 391 392 return ret; 393 } 394 395 static int fpregs64_set(struct task_struct *target, 396 const struct user_regset *regset, 397 unsigned int pos, unsigned int count, 398 const void *kbuf, const void __user *ubuf) 399 { 400 unsigned long *fpregs = task_thread_info(target)->fpregs; 401 unsigned long fprs; 402 int ret; 403 404 if (target == current) 405 save_and_clear_fpu(); 406 407 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 408 fpregs, 409 0, 32 * sizeof(u64)); 410 if (!ret) 411 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 412 task_thread_info(target)->xfsr, 413 32 * sizeof(u64), 414 33 * sizeof(u64)); 415 if (!ret) 416 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 417 task_thread_info(target)->gsr, 418 33 * sizeof(u64), 419 34 * sizeof(u64)); 420 421 fprs = task_thread_info(target)->fpsaved[0]; 422 if (!ret && count > 0) { 423 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 424 &fprs, 425 34 * sizeof(u64), 426 35 * sizeof(u64)); 427 } 428 429 fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU); 430 task_thread_info(target)->fpsaved[0] = fprs; 431 432 if (!ret) 433 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 434 35 * sizeof(u64), -1); 435 return ret; 436 } 437 438 static const struct user_regset sparc64_regsets[] = { 439 /* Format is: 440 * G0 --> G7 441 * O0 --> O7 442 * L0 --> L7 443 * I0 --> I7 444 * TSTATE, TPC, TNPC, Y 445 */ 446 [REGSET_GENERAL] = { 447 .core_note_type = NT_PRSTATUS, 448 .n = 36, 449 .size = sizeof(u64), .align = sizeof(u64), 450 .get = genregs64_get, .set = genregs64_set 451 }, 452 /* Format is: 453 * F0 --> F63 454 * FSR 455 * GSR 456 * FPRS 457 */ 458 [REGSET_FP] = { 459 .core_note_type = NT_PRFPREG, 460 .n = 35, 461 .size = sizeof(u64), .align = sizeof(u64), 462 .get = fpregs64_get, .set = fpregs64_set 463 }, 464 }; 465 466 static const struct user_regset_view user_sparc64_view = { 467 .name = "sparc64", .e_machine = EM_SPARCV9, 468 .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets) 469 }; 470 471 #ifdef CONFIG_COMPAT 472 static int genregs32_get(struct task_struct *target, 473 const struct user_regset *regset, 474 unsigned int pos, unsigned int count, 475 void *kbuf, void __user *ubuf) 476 { 477 const struct pt_regs *regs = task_pt_regs(target); 478 compat_ulong_t __user *reg_window; 479 compat_ulong_t *k = kbuf; 480 compat_ulong_t __user *u = ubuf; 481 compat_ulong_t reg; 482 483 if (target == current) 484 flushw_user(); 485 486 pos /= sizeof(reg); 487 count /= sizeof(reg); 488 489 if (kbuf) { 490 for (; count > 0 && pos < 16; count--) 491 *k++ = regs->u_regs[pos++]; 492 493 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 494 reg_window -= 16; 495 if (target == current) { 496 for (; count > 0 && pos < 32; count--) { 497 if (get_user(*k++, ®_window[pos++])) 498 return -EFAULT; 499 } 500 } else { 501 for (; count > 0 && pos < 32; count--) { 502 if (access_process_vm(target, 503 (unsigned long) 504 ®_window[pos], 505 k, sizeof(*k), 0) 506 != sizeof(*k)) 507 return -EFAULT; 508 k++; 509 pos++; 510 } 511 } 512 } else { 513 for (; count > 0 && pos < 16; count--) { 514 if (put_user((compat_ulong_t) regs->u_regs[pos++], u++)) 515 return -EFAULT; 516 } 517 518 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 519 reg_window -= 16; 520 if (target == current) { 521 for (; count > 0 && pos < 32; count--) { 522 if (get_user(reg, ®_window[pos++]) || 523 put_user(reg, u++)) 524 return -EFAULT; 525 } 526 } else { 527 for (; count > 0 && pos < 32; count--) { 528 if (access_process_vm(target, 529 (unsigned long) 530 ®_window[pos], 531 ®, sizeof(reg), 0) 532 != sizeof(reg)) 533 return -EFAULT; 534 if (access_process_vm(target, 535 (unsigned long) u, 536 ®, sizeof(reg), 1) 537 != sizeof(reg)) 538 return -EFAULT; 539 pos++; 540 u++; 541 } 542 } 543 } 544 while (count > 0) { 545 switch (pos) { 546 case 32: /* PSR */ 547 reg = tstate_to_psr(regs->tstate); 548 break; 549 case 33: /* PC */ 550 reg = regs->tpc; 551 break; 552 case 34: /* NPC */ 553 reg = regs->tnpc; 554 break; 555 case 35: /* Y */ 556 reg = regs->y; 557 break; 558 case 36: /* WIM */ 559 case 37: /* TBR */ 560 reg = 0; 561 break; 562 default: 563 goto finish; 564 } 565 566 if (kbuf) 567 *k++ = reg; 568 else if (put_user(reg, u++)) 569 return -EFAULT; 570 pos++; 571 count--; 572 } 573 finish: 574 pos *= sizeof(reg); 575 count *= sizeof(reg); 576 577 return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 578 38 * sizeof(reg), -1); 579 } 580 581 static int genregs32_set(struct task_struct *target, 582 const struct user_regset *regset, 583 unsigned int pos, unsigned int count, 584 const void *kbuf, const void __user *ubuf) 585 { 586 struct pt_regs *regs = task_pt_regs(target); 587 compat_ulong_t __user *reg_window; 588 const compat_ulong_t *k = kbuf; 589 const compat_ulong_t __user *u = ubuf; 590 compat_ulong_t reg; 591 592 if (target == current) 593 flushw_user(); 594 595 pos /= sizeof(reg); 596 count /= sizeof(reg); 597 598 if (kbuf) { 599 for (; count > 0 && pos < 16; count--) 600 regs->u_regs[pos++] = *k++; 601 602 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 603 reg_window -= 16; 604 if (target == current) { 605 for (; count > 0 && pos < 32; count--) { 606 if (put_user(*k++, ®_window[pos++])) 607 return -EFAULT; 608 } 609 } else { 610 for (; count > 0 && pos < 32; count--) { 611 if (access_process_vm(target, 612 (unsigned long) 613 ®_window[pos], 614 (void *) k, 615 sizeof(*k), 1) 616 != sizeof(*k)) 617 return -EFAULT; 618 k++; 619 pos++; 620 } 621 } 622 } else { 623 for (; count > 0 && pos < 16; count--) { 624 if (get_user(reg, u++)) 625 return -EFAULT; 626 regs->u_regs[pos++] = reg; 627 } 628 629 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 630 reg_window -= 16; 631 if (target == current) { 632 for (; count > 0 && pos < 32; count--) { 633 if (get_user(reg, u++) || 634 put_user(reg, ®_window[pos++])) 635 return -EFAULT; 636 } 637 } else { 638 for (; count > 0 && pos < 32; count--) { 639 if (access_process_vm(target, 640 (unsigned long) 641 u, 642 ®, sizeof(reg), 0) 643 != sizeof(reg)) 644 return -EFAULT; 645 if (access_process_vm(target, 646 (unsigned long) 647 ®_window[pos], 648 ®, sizeof(reg), 1) 649 != sizeof(reg)) 650 return -EFAULT; 651 pos++; 652 u++; 653 } 654 } 655 } 656 while (count > 0) { 657 unsigned long tstate; 658 659 if (kbuf) 660 reg = *k++; 661 else if (get_user(reg, u++)) 662 return -EFAULT; 663 664 switch (pos) { 665 case 32: /* PSR */ 666 tstate = regs->tstate; 667 tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); 668 tstate |= psr_to_tstate_icc(reg); 669 if (reg & PSR_SYSCALL) 670 tstate |= TSTATE_SYSCALL; 671 regs->tstate = tstate; 672 break; 673 case 33: /* PC */ 674 regs->tpc = reg; 675 break; 676 case 34: /* NPC */ 677 regs->tnpc = reg; 678 break; 679 case 35: /* Y */ 680 regs->y = reg; 681 break; 682 case 36: /* WIM */ 683 case 37: /* TBR */ 684 break; 685 default: 686 goto finish; 687 } 688 689 pos++; 690 count--; 691 } 692 finish: 693 pos *= sizeof(reg); 694 count *= sizeof(reg); 695 696 return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 697 38 * sizeof(reg), -1); 698 } 699 700 static int fpregs32_get(struct task_struct *target, 701 const struct user_regset *regset, 702 unsigned int pos, unsigned int count, 703 void *kbuf, void __user *ubuf) 704 { 705 const unsigned long *fpregs = task_thread_info(target)->fpregs; 706 compat_ulong_t enabled; 707 unsigned long fprs; 708 compat_ulong_t fsr; 709 int ret = 0; 710 711 if (target == current) 712 save_and_clear_fpu(); 713 714 fprs = task_thread_info(target)->fpsaved[0]; 715 if (fprs & FPRS_FEF) { 716 fsr = task_thread_info(target)->xfsr[0]; 717 enabled = 1; 718 } else { 719 fsr = 0; 720 enabled = 0; 721 } 722 723 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 724 fpregs, 725 0, 32 * sizeof(u32)); 726 727 if (!ret) 728 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 729 32 * sizeof(u32), 730 33 * sizeof(u32)); 731 if (!ret) 732 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 733 &fsr, 734 33 * sizeof(u32), 735 34 * sizeof(u32)); 736 737 if (!ret) { 738 compat_ulong_t val; 739 740 val = (enabled << 8) | (8 << 16); 741 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 742 &val, 743 34 * sizeof(u32), 744 35 * sizeof(u32)); 745 } 746 747 if (!ret) 748 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 749 35 * sizeof(u32), -1); 750 751 return ret; 752 } 753 754 static int fpregs32_set(struct task_struct *target, 755 const struct user_regset *regset, 756 unsigned int pos, unsigned int count, 757 const void *kbuf, const void __user *ubuf) 758 { 759 unsigned long *fpregs = task_thread_info(target)->fpregs; 760 unsigned long fprs; 761 int ret; 762 763 if (target == current) 764 save_and_clear_fpu(); 765 766 fprs = task_thread_info(target)->fpsaved[0]; 767 768 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 769 fpregs, 770 0, 32 * sizeof(u32)); 771 if (!ret) 772 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 773 32 * sizeof(u32), 774 33 * sizeof(u32)); 775 if (!ret && count > 0) { 776 compat_ulong_t fsr; 777 unsigned long val; 778 779 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 780 &fsr, 781 33 * sizeof(u32), 782 34 * sizeof(u32)); 783 if (!ret) { 784 val = task_thread_info(target)->xfsr[0]; 785 val &= 0xffffffff00000000UL; 786 val |= fsr; 787 task_thread_info(target)->xfsr[0] = val; 788 } 789 } 790 791 fprs |= (FPRS_FEF | FPRS_DL); 792 task_thread_info(target)->fpsaved[0] = fprs; 793 794 if (!ret) 795 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 796 34 * sizeof(u32), -1); 797 return ret; 798 } 799 800 static const struct user_regset sparc32_regsets[] = { 801 /* Format is: 802 * G0 --> G7 803 * O0 --> O7 804 * L0 --> L7 805 * I0 --> I7 806 * PSR, PC, nPC, Y, WIM, TBR 807 */ 808 [REGSET_GENERAL] = { 809 .core_note_type = NT_PRSTATUS, 810 .n = 38, 811 .size = sizeof(u32), .align = sizeof(u32), 812 .get = genregs32_get, .set = genregs32_set 813 }, 814 /* Format is: 815 * F0 --> F31 816 * empty 32-bit word 817 * FSR (32--bit word) 818 * FPU QUEUE COUNT (8-bit char) 819 * FPU QUEUE ENTRYSIZE (8-bit char) 820 * FPU ENABLED (8-bit char) 821 * empty 8-bit char 822 * FPU QUEUE (64 32-bit ints) 823 */ 824 [REGSET_FP] = { 825 .core_note_type = NT_PRFPREG, 826 .n = 99, 827 .size = sizeof(u32), .align = sizeof(u32), 828 .get = fpregs32_get, .set = fpregs32_set 829 }, 830 }; 831 832 static const struct user_regset_view user_sparc32_view = { 833 .name = "sparc", .e_machine = EM_SPARC, 834 .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets) 835 }; 836 #endif /* CONFIG_COMPAT */ 837 838 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 839 { 840 #ifdef CONFIG_COMPAT 841 if (test_tsk_thread_flag(task, TIF_32BIT)) 842 return &user_sparc32_view; 843 #endif 844 return &user_sparc64_view; 845 } 846 847 #ifdef CONFIG_COMPAT 848 struct compat_fps { 849 unsigned int regs[32]; 850 unsigned int fsr; 851 unsigned int flags; 852 unsigned int extra; 853 unsigned int fpqd; 854 struct compat_fq { 855 unsigned int insnaddr; 856 unsigned int insn; 857 } fpq[16]; 858 }; 859 860 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 861 compat_ulong_t caddr, compat_ulong_t cdata) 862 { 863 const struct user_regset_view *view = task_user_regset_view(current); 864 compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4]; 865 struct pt_regs32 __user *pregs; 866 struct compat_fps __user *fps; 867 unsigned long addr2 = caddr2; 868 unsigned long addr = caddr; 869 unsigned long data = cdata; 870 int ret; 871 872 pregs = (struct pt_regs32 __user *) addr; 873 fps = (struct compat_fps __user *) addr; 874 875 switch (request) { 876 case PTRACE_PEEKUSR: 877 ret = (addr != 0) ? -EIO : 0; 878 break; 879 880 case PTRACE_GETREGS: 881 ret = copy_regset_to_user(child, view, REGSET_GENERAL, 882 32 * sizeof(u32), 883 4 * sizeof(u32), 884 &pregs->psr); 885 if (!ret) 886 ret = copy_regset_to_user(child, view, REGSET_GENERAL, 887 1 * sizeof(u32), 888 15 * sizeof(u32), 889 &pregs->u_regs[0]); 890 break; 891 892 case PTRACE_SETREGS: 893 ret = copy_regset_from_user(child, view, REGSET_GENERAL, 894 32 * sizeof(u32), 895 4 * sizeof(u32), 896 &pregs->psr); 897 if (!ret) 898 ret = copy_regset_from_user(child, view, REGSET_GENERAL, 899 1 * sizeof(u32), 900 15 * sizeof(u32), 901 &pregs->u_regs[0]); 902 break; 903 904 case PTRACE_GETFPREGS: 905 ret = copy_regset_to_user(child, view, REGSET_FP, 906 0 * sizeof(u32), 907 32 * sizeof(u32), 908 &fps->regs[0]); 909 if (!ret) 910 ret = copy_regset_to_user(child, view, REGSET_FP, 911 33 * sizeof(u32), 912 1 * sizeof(u32), 913 &fps->fsr); 914 if (!ret) { 915 if (__put_user(0, &fps->flags) || 916 __put_user(0, &fps->extra) || 917 __put_user(0, &fps->fpqd) || 918 clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) 919 ret = -EFAULT; 920 } 921 break; 922 923 case PTRACE_SETFPREGS: 924 ret = copy_regset_from_user(child, view, REGSET_FP, 925 0 * sizeof(u32), 926 32 * sizeof(u32), 927 &fps->regs[0]); 928 if (!ret) 929 ret = copy_regset_from_user(child, view, REGSET_FP, 930 33 * sizeof(u32), 931 1 * sizeof(u32), 932 &fps->fsr); 933 break; 934 935 case PTRACE_READTEXT: 936 case PTRACE_READDATA: 937 ret = ptrace_readdata(child, addr, 938 (char __user *)addr2, data); 939 if (ret == data) 940 ret = 0; 941 else if (ret >= 0) 942 ret = -EIO; 943 break; 944 945 case PTRACE_WRITETEXT: 946 case PTRACE_WRITEDATA: 947 ret = ptrace_writedata(child, (char __user *) addr2, 948 addr, data); 949 if (ret == data) 950 ret = 0; 951 else if (ret >= 0) 952 ret = -EIO; 953 break; 954 955 default: 956 if (request == PTRACE_SPARC_DETACH) 957 request = PTRACE_DETACH; 958 ret = compat_ptrace_request(child, request, addr, data); 959 break; 960 } 961 962 return ret; 963 } 964 #endif /* CONFIG_COMPAT */ 965 966 struct fps { 967 unsigned int regs[64]; 968 unsigned long fsr; 969 }; 970 971 long arch_ptrace(struct task_struct *child, long request, 972 unsigned long addr, unsigned long data) 973 { 974 const struct user_regset_view *view = task_user_regset_view(current); 975 unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; 976 struct pt_regs __user *pregs; 977 struct fps __user *fps; 978 void __user *addr2p; 979 int ret; 980 981 pregs = (struct pt_regs __user *) addr; 982 fps = (struct fps __user *) addr; 983 addr2p = (void __user *) addr2; 984 985 switch (request) { 986 case PTRACE_PEEKUSR: 987 ret = (addr != 0) ? -EIO : 0; 988 break; 989 990 case PTRACE_GETREGS64: 991 ret = copy_regset_to_user(child, view, REGSET_GENERAL, 992 1 * sizeof(u64), 993 15 * sizeof(u64), 994 &pregs->u_regs[0]); 995 if (!ret) { 996 /* XXX doesn't handle 'y' register correctly XXX */ 997 ret = copy_regset_to_user(child, view, REGSET_GENERAL, 998 32 * sizeof(u64), 999 4 * sizeof(u64), 1000 &pregs->tstate); 1001 } 1002 break; 1003 1004 case PTRACE_SETREGS64: 1005 ret = copy_regset_from_user(child, view, REGSET_GENERAL, 1006 1 * sizeof(u64), 1007 15 * sizeof(u64), 1008 &pregs->u_regs[0]); 1009 if (!ret) { 1010 /* XXX doesn't handle 'y' register correctly XXX */ 1011 ret = copy_regset_from_user(child, view, REGSET_GENERAL, 1012 32 * sizeof(u64), 1013 4 * sizeof(u64), 1014 &pregs->tstate); 1015 } 1016 break; 1017 1018 case PTRACE_GETFPREGS64: 1019 ret = copy_regset_to_user(child, view, REGSET_FP, 1020 0 * sizeof(u64), 1021 33 * sizeof(u64), 1022 fps); 1023 break; 1024 1025 case PTRACE_SETFPREGS64: 1026 ret = copy_regset_from_user(child, view, REGSET_FP, 1027 0 * sizeof(u64), 1028 33 * sizeof(u64), 1029 fps); 1030 break; 1031 1032 case PTRACE_READTEXT: 1033 case PTRACE_READDATA: 1034 ret = ptrace_readdata(child, addr, addr2p, data); 1035 if (ret == data) 1036 ret = 0; 1037 else if (ret >= 0) 1038 ret = -EIO; 1039 break; 1040 1041 case PTRACE_WRITETEXT: 1042 case PTRACE_WRITEDATA: 1043 ret = ptrace_writedata(child, addr2p, addr, data); 1044 if (ret == data) 1045 ret = 0; 1046 else if (ret >= 0) 1047 ret = -EIO; 1048 break; 1049 1050 default: 1051 if (request == PTRACE_SPARC_DETACH) 1052 request = PTRACE_DETACH; 1053 ret = ptrace_request(child, request, addr, data); 1054 break; 1055 } 1056 1057 return ret; 1058 } 1059 1060 asmlinkage int syscall_trace_enter(struct pt_regs *regs) 1061 { 1062 int ret = 0; 1063 1064 /* do the secure computing check first */ 1065 secure_computing_strict(regs->u_regs[UREG_G1]); 1066 1067 if (test_thread_flag(TIF_SYSCALL_TRACE)) 1068 ret = tracehook_report_syscall_entry(regs); 1069 1070 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 1071 trace_sys_enter(regs, regs->u_regs[UREG_G1]); 1072 1073 audit_syscall_entry((test_thread_flag(TIF_32BIT) ? 1074 AUDIT_ARCH_SPARC : 1075 AUDIT_ARCH_SPARC64), 1076 regs->u_regs[UREG_G1], 1077 regs->u_regs[UREG_I0], 1078 regs->u_regs[UREG_I1], 1079 regs->u_regs[UREG_I2], 1080 regs->u_regs[UREG_I3]); 1081 1082 return ret; 1083 } 1084 1085 asmlinkage void syscall_trace_leave(struct pt_regs *regs) 1086 { 1087 audit_syscall_exit(regs); 1088 1089 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 1090 trace_sys_exit(regs, regs->u_regs[UREG_G1]); 1091 1092 if (test_thread_flag(TIF_SYSCALL_TRACE)) 1093 tracehook_report_syscall_exit(regs, 0); 1094 } 1095