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