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