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