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