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