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