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