1 // SPDX-License-Identifier: GPL-2.0-only 2 /* ptrace.c: Sparc process tracing support. 3 * 4 * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net) 5 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 6 * 7 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson, 8 * and David Mosberger. 9 * 10 * Added Linux support -miguel (weird, eh?, the original code was meant 11 * to emulate SunOS). 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/sched.h> 16 #include <linux/sched/task_stack.h> 17 #include <linux/mm.h> 18 #include <linux/errno.h> 19 #include <linux/export.h> 20 #include <linux/ptrace.h> 21 #include <linux/user.h> 22 #include <linux/smp.h> 23 #include <linux/security.h> 24 #include <linux/seccomp.h> 25 #include <linux/audit.h> 26 #include <linux/signal.h> 27 #include <linux/regset.h> 28 #include <linux/tracehook.h> 29 #include <trace/syscall.h> 30 #include <linux/compat.h> 31 #include <linux/elf.h> 32 #include <linux/context_tracking.h> 33 34 #include <asm/asi.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 (put_user(reg, u++)) 580 return -EFAULT; 581 } 582 } 583 } 584 while (count > 0) { 585 switch (pos) { 586 case 32: /* PSR */ 587 reg = tstate_to_psr(regs->tstate); 588 break; 589 case 33: /* PC */ 590 reg = regs->tpc; 591 break; 592 case 34: /* NPC */ 593 reg = regs->tnpc; 594 break; 595 case 35: /* Y */ 596 reg = regs->y; 597 break; 598 case 36: /* WIM */ 599 case 37: /* TBR */ 600 reg = 0; 601 break; 602 default: 603 goto finish; 604 } 605 606 if (kbuf) 607 *k++ = reg; 608 else if (put_user(reg, u++)) 609 return -EFAULT; 610 pos++; 611 count--; 612 } 613 finish: 614 pos *= sizeof(reg); 615 count *= sizeof(reg); 616 617 return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 618 38 * sizeof(reg), -1); 619 } 620 621 static int genregs32_set(struct task_struct *target, 622 const struct user_regset *regset, 623 unsigned int pos, unsigned int count, 624 const void *kbuf, const void __user *ubuf) 625 { 626 struct pt_regs *regs = task_pt_regs(target); 627 compat_ulong_t __user *reg_window; 628 const compat_ulong_t *k = kbuf; 629 const compat_ulong_t __user *u = ubuf; 630 compat_ulong_t reg; 631 632 if (target == current) 633 flushw_user(); 634 635 pos /= sizeof(reg); 636 count /= sizeof(reg); 637 638 if (kbuf) { 639 for (; count > 0 && pos < 16; count--) 640 regs->u_regs[pos++] = *k++; 641 642 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 643 reg_window -= 16; 644 if (target == current) { 645 for (; count > 0 && pos < 32; count--) { 646 if (put_user(*k++, ®_window[pos++])) 647 return -EFAULT; 648 } 649 } else { 650 for (; count > 0 && pos < 32; count--) { 651 if (access_process_vm(target, 652 (unsigned long) 653 ®_window[pos], 654 (void *) k, 655 sizeof(*k), 656 FOLL_FORCE | FOLL_WRITE) 657 != sizeof(*k)) 658 return -EFAULT; 659 k++; 660 pos++; 661 } 662 } 663 } else { 664 for (; count > 0 && pos < 16; count--) { 665 if (get_user(reg, u++)) 666 return -EFAULT; 667 regs->u_regs[pos++] = reg; 668 } 669 670 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 671 reg_window -= 16; 672 if (target == current) { 673 for (; count > 0 && pos < 32; count--) { 674 if (get_user(reg, u++) || 675 put_user(reg, ®_window[pos++])) 676 return -EFAULT; 677 } 678 } else { 679 for (; count > 0 && pos < 32; count--) { 680 if (get_user(reg, u++)) 681 return -EFAULT; 682 if (access_process_vm(target, 683 (unsigned long) 684 ®_window[pos], 685 ®, sizeof(reg), 686 FOLL_FORCE | FOLL_WRITE) 687 != sizeof(reg)) 688 return -EFAULT; 689 pos++; 690 u++; 691 } 692 } 693 } 694 while (count > 0) { 695 unsigned long tstate; 696 697 if (kbuf) 698 reg = *k++; 699 else if (get_user(reg, u++)) 700 return -EFAULT; 701 702 switch (pos) { 703 case 32: /* PSR */ 704 tstate = regs->tstate; 705 tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); 706 tstate |= psr_to_tstate_icc(reg); 707 if (reg & PSR_SYSCALL) 708 tstate |= TSTATE_SYSCALL; 709 regs->tstate = tstate; 710 break; 711 case 33: /* PC */ 712 regs->tpc = reg; 713 break; 714 case 34: /* NPC */ 715 regs->tnpc = reg; 716 break; 717 case 35: /* Y */ 718 regs->y = reg; 719 break; 720 case 36: /* WIM */ 721 case 37: /* TBR */ 722 break; 723 default: 724 goto finish; 725 } 726 727 pos++; 728 count--; 729 } 730 finish: 731 pos *= sizeof(reg); 732 count *= sizeof(reg); 733 734 return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 735 38 * sizeof(reg), -1); 736 } 737 738 static int fpregs32_get(struct task_struct *target, 739 const struct user_regset *regset, 740 unsigned int pos, unsigned int count, 741 void *kbuf, void __user *ubuf) 742 { 743 const unsigned long *fpregs = task_thread_info(target)->fpregs; 744 compat_ulong_t enabled; 745 unsigned long fprs; 746 compat_ulong_t fsr; 747 int ret = 0; 748 749 if (target == current) 750 save_and_clear_fpu(); 751 752 fprs = task_thread_info(target)->fpsaved[0]; 753 if (fprs & FPRS_FEF) { 754 fsr = task_thread_info(target)->xfsr[0]; 755 enabled = 1; 756 } else { 757 fsr = 0; 758 enabled = 0; 759 } 760 761 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 762 fpregs, 763 0, 32 * sizeof(u32)); 764 765 if (!ret) 766 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 767 32 * sizeof(u32), 768 33 * sizeof(u32)); 769 if (!ret) 770 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 771 &fsr, 772 33 * sizeof(u32), 773 34 * sizeof(u32)); 774 775 if (!ret) { 776 compat_ulong_t val; 777 778 val = (enabled << 8) | (8 << 16); 779 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 780 &val, 781 34 * sizeof(u32), 782 35 * sizeof(u32)); 783 } 784 785 if (!ret) 786 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 787 35 * sizeof(u32), -1); 788 789 return ret; 790 } 791 792 static int fpregs32_set(struct task_struct *target, 793 const struct user_regset *regset, 794 unsigned int pos, unsigned int count, 795 const void *kbuf, const void __user *ubuf) 796 { 797 unsigned long *fpregs = task_thread_info(target)->fpregs; 798 unsigned long fprs; 799 int ret; 800 801 if (target == current) 802 save_and_clear_fpu(); 803 804 fprs = task_thread_info(target)->fpsaved[0]; 805 806 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 807 fpregs, 808 0, 32 * sizeof(u32)); 809 if (!ret) 810 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 811 32 * sizeof(u32), 812 33 * sizeof(u32)); 813 if (!ret && count > 0) { 814 compat_ulong_t fsr; 815 unsigned long val; 816 817 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 818 &fsr, 819 33 * sizeof(u32), 820 34 * sizeof(u32)); 821 if (!ret) { 822 val = task_thread_info(target)->xfsr[0]; 823 val &= 0xffffffff00000000UL; 824 val |= fsr; 825 task_thread_info(target)->xfsr[0] = val; 826 } 827 } 828 829 fprs |= (FPRS_FEF | FPRS_DL); 830 task_thread_info(target)->fpsaved[0] = fprs; 831 832 if (!ret) 833 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 834 34 * sizeof(u32), -1); 835 return ret; 836 } 837 838 static const struct user_regset sparc32_regsets[] = { 839 /* Format is: 840 * G0 --> G7 841 * O0 --> O7 842 * L0 --> L7 843 * I0 --> I7 844 * PSR, PC, nPC, Y, WIM, TBR 845 */ 846 [REGSET_GENERAL] = { 847 .core_note_type = NT_PRSTATUS, 848 .n = 38, 849 .size = sizeof(u32), .align = sizeof(u32), 850 .get = genregs32_get, .set = genregs32_set 851 }, 852 /* Format is: 853 * F0 --> F31 854 * empty 32-bit word 855 * FSR (32--bit word) 856 * FPU QUEUE COUNT (8-bit char) 857 * FPU QUEUE ENTRYSIZE (8-bit char) 858 * FPU ENABLED (8-bit char) 859 * empty 8-bit char 860 * FPU QUEUE (64 32-bit ints) 861 */ 862 [REGSET_FP] = { 863 .core_note_type = NT_PRFPREG, 864 .n = 99, 865 .size = sizeof(u32), .align = sizeof(u32), 866 .get = fpregs32_get, .set = fpregs32_set 867 }, 868 }; 869 870 static const struct user_regset_view user_sparc32_view = { 871 .name = "sparc", .e_machine = EM_SPARC, 872 .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets) 873 }; 874 #endif /* CONFIG_COMPAT */ 875 876 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 877 { 878 #ifdef CONFIG_COMPAT 879 if (test_tsk_thread_flag(task, TIF_32BIT)) 880 return &user_sparc32_view; 881 #endif 882 return &user_sparc64_view; 883 } 884 885 #ifdef CONFIG_COMPAT 886 struct compat_fps { 887 unsigned int regs[32]; 888 unsigned int fsr; 889 unsigned int flags; 890 unsigned int extra; 891 unsigned int fpqd; 892 struct compat_fq { 893 unsigned int insnaddr; 894 unsigned int insn; 895 } fpq[16]; 896 }; 897 898 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 899 compat_ulong_t caddr, compat_ulong_t cdata) 900 { 901 const struct user_regset_view *view = task_user_regset_view(current); 902 compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4]; 903 struct pt_regs32 __user *pregs; 904 struct compat_fps __user *fps; 905 unsigned long addr2 = caddr2; 906 unsigned long addr = caddr; 907 unsigned long data = cdata; 908 int ret; 909 910 pregs = (struct pt_regs32 __user *) addr; 911 fps = (struct compat_fps __user *) addr; 912 913 switch (request) { 914 case PTRACE_PEEKUSR: 915 ret = (addr != 0) ? -EIO : 0; 916 break; 917 918 case PTRACE_GETREGS: 919 ret = copy_regset_to_user(child, view, REGSET_GENERAL, 920 32 * sizeof(u32), 921 4 * sizeof(u32), 922 &pregs->psr); 923 if (!ret) 924 ret = copy_regset_to_user(child, view, REGSET_GENERAL, 925 1 * sizeof(u32), 926 15 * sizeof(u32), 927 &pregs->u_regs[0]); 928 break; 929 930 case PTRACE_SETREGS: 931 ret = copy_regset_from_user(child, view, REGSET_GENERAL, 932 32 * sizeof(u32), 933 4 * sizeof(u32), 934 &pregs->psr); 935 if (!ret) 936 ret = copy_regset_from_user(child, view, REGSET_GENERAL, 937 1 * sizeof(u32), 938 15 * sizeof(u32), 939 &pregs->u_regs[0]); 940 break; 941 942 case PTRACE_GETFPREGS: 943 ret = copy_regset_to_user(child, view, REGSET_FP, 944 0 * sizeof(u32), 945 32 * sizeof(u32), 946 &fps->regs[0]); 947 if (!ret) 948 ret = copy_regset_to_user(child, view, REGSET_FP, 949 33 * sizeof(u32), 950 1 * sizeof(u32), 951 &fps->fsr); 952 if (!ret) { 953 if (__put_user(0, &fps->flags) || 954 __put_user(0, &fps->extra) || 955 __put_user(0, &fps->fpqd) || 956 clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) 957 ret = -EFAULT; 958 } 959 break; 960 961 case PTRACE_SETFPREGS: 962 ret = copy_regset_from_user(child, view, REGSET_FP, 963 0 * sizeof(u32), 964 32 * sizeof(u32), 965 &fps->regs[0]); 966 if (!ret) 967 ret = copy_regset_from_user(child, view, REGSET_FP, 968 33 * sizeof(u32), 969 1 * sizeof(u32), 970 &fps->fsr); 971 break; 972 973 case PTRACE_READTEXT: 974 case PTRACE_READDATA: 975 ret = ptrace_readdata(child, addr, 976 (char __user *)addr2, data); 977 if (ret == data) 978 ret = 0; 979 else if (ret >= 0) 980 ret = -EIO; 981 break; 982 983 case PTRACE_WRITETEXT: 984 case PTRACE_WRITEDATA: 985 ret = ptrace_writedata(child, (char __user *) addr2, 986 addr, data); 987 if (ret == data) 988 ret = 0; 989 else if (ret >= 0) 990 ret = -EIO; 991 break; 992 993 default: 994 if (request == PTRACE_SPARC_DETACH) 995 request = PTRACE_DETACH; 996 ret = compat_ptrace_request(child, request, addr, data); 997 break; 998 } 999 1000 return ret; 1001 } 1002 #endif /* CONFIG_COMPAT */ 1003 1004 struct fps { 1005 unsigned int regs[64]; 1006 unsigned long fsr; 1007 }; 1008 1009 long arch_ptrace(struct task_struct *child, long request, 1010 unsigned long addr, unsigned long data) 1011 { 1012 const struct user_regset_view *view = task_user_regset_view(current); 1013 unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; 1014 struct pt_regs __user *pregs; 1015 struct fps __user *fps; 1016 void __user *addr2p; 1017 int ret; 1018 1019 pregs = (struct pt_regs __user *) addr; 1020 fps = (struct fps __user *) addr; 1021 addr2p = (void __user *) addr2; 1022 1023 switch (request) { 1024 case PTRACE_PEEKUSR: 1025 ret = (addr != 0) ? -EIO : 0; 1026 break; 1027 1028 case PTRACE_GETREGS64: 1029 ret = copy_regset_to_user(child, view, REGSET_GENERAL, 1030 1 * sizeof(u64), 1031 15 * sizeof(u64), 1032 &pregs->u_regs[0]); 1033 if (!ret) { 1034 /* XXX doesn't handle 'y' register correctly XXX */ 1035 ret = copy_regset_to_user(child, view, REGSET_GENERAL, 1036 32 * sizeof(u64), 1037 4 * sizeof(u64), 1038 &pregs->tstate); 1039 } 1040 break; 1041 1042 case PTRACE_SETREGS64: 1043 ret = copy_regset_from_user(child, view, REGSET_GENERAL, 1044 1 * sizeof(u64), 1045 15 * sizeof(u64), 1046 &pregs->u_regs[0]); 1047 if (!ret) { 1048 /* XXX doesn't handle 'y' register correctly XXX */ 1049 ret = copy_regset_from_user(child, view, REGSET_GENERAL, 1050 32 * sizeof(u64), 1051 4 * sizeof(u64), 1052 &pregs->tstate); 1053 } 1054 break; 1055 1056 case PTRACE_GETFPREGS64: 1057 ret = copy_regset_to_user(child, view, REGSET_FP, 1058 0 * sizeof(u64), 1059 33 * sizeof(u64), 1060 fps); 1061 break; 1062 1063 case PTRACE_SETFPREGS64: 1064 ret = copy_regset_from_user(child, view, REGSET_FP, 1065 0 * sizeof(u64), 1066 33 * sizeof(u64), 1067 fps); 1068 break; 1069 1070 case PTRACE_READTEXT: 1071 case PTRACE_READDATA: 1072 ret = ptrace_readdata(child, addr, addr2p, data); 1073 if (ret == data) 1074 ret = 0; 1075 else if (ret >= 0) 1076 ret = -EIO; 1077 break; 1078 1079 case PTRACE_WRITETEXT: 1080 case PTRACE_WRITEDATA: 1081 ret = ptrace_writedata(child, addr2p, addr, data); 1082 if (ret == data) 1083 ret = 0; 1084 else if (ret >= 0) 1085 ret = -EIO; 1086 break; 1087 1088 default: 1089 if (request == PTRACE_SPARC_DETACH) 1090 request = PTRACE_DETACH; 1091 ret = ptrace_request(child, request, addr, data); 1092 break; 1093 } 1094 1095 return ret; 1096 } 1097 1098 asmlinkage int syscall_trace_enter(struct pt_regs *regs) 1099 { 1100 int ret = 0; 1101 1102 /* do the secure computing check first */ 1103 secure_computing_strict(regs->u_regs[UREG_G1]); 1104 1105 if (test_thread_flag(TIF_NOHZ)) 1106 user_exit(); 1107 1108 if (test_thread_flag(TIF_SYSCALL_TRACE)) 1109 ret = tracehook_report_syscall_entry(regs); 1110 1111 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 1112 trace_sys_enter(regs, regs->u_regs[UREG_G1]); 1113 1114 audit_syscall_entry(regs->u_regs[UREG_G1], regs->u_regs[UREG_I0], 1115 regs->u_regs[UREG_I1], regs->u_regs[UREG_I2], 1116 regs->u_regs[UREG_I3]); 1117 1118 return ret; 1119 } 1120 1121 asmlinkage void syscall_trace_leave(struct pt_regs *regs) 1122 { 1123 if (test_thread_flag(TIF_NOHZ)) 1124 user_exit(); 1125 1126 audit_syscall_exit(regs); 1127 1128 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 1129 trace_sys_exit(regs, regs->u_regs[UREG_I0]); 1130 1131 if (test_thread_flag(TIF_SYSCALL_TRACE)) 1132 tracehook_report_syscall_exit(regs, 0); 1133 1134 if (test_thread_flag(TIF_NOHZ)) 1135 user_enter(); 1136 } 1137 1138 /** 1139 * regs_query_register_offset() - query register offset from its name 1140 * @name: the name of a register 1141 * 1142 * regs_query_register_offset() returns the offset of a register in struct 1143 * pt_regs from its name. If the name is invalid, this returns -EINVAL; 1144 */ 1145 int regs_query_register_offset(const char *name) 1146 { 1147 const struct pt_regs_offset *roff; 1148 1149 for (roff = regoffset_table; roff->name != NULL; roff++) 1150 if (!strcmp(roff->name, name)) 1151 return roff->offset; 1152 return -EINVAL; 1153 } 1154 1155 /** 1156 * regs_within_kernel_stack() - check the address in the stack 1157 * @regs: pt_regs which contains kernel stack pointer. 1158 * @addr: address which is checked. 1159 * 1160 * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). 1161 * If @addr is within the kernel stack, it returns true. If not, returns false. 1162 */ 1163 static inline int regs_within_kernel_stack(struct pt_regs *regs, 1164 unsigned long addr) 1165 { 1166 unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS; 1167 return ((addr & ~(THREAD_SIZE - 1)) == 1168 (ksp & ~(THREAD_SIZE - 1))); 1169 } 1170 1171 /** 1172 * regs_get_kernel_stack_nth() - get Nth entry of the stack 1173 * @regs: pt_regs which contains kernel stack pointer. 1174 * @n: stack entry number. 1175 * 1176 * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which 1177 * is specified by @regs. If the @n th entry is NOT in the kernel stack, 1178 * this returns 0. 1179 */ 1180 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) 1181 { 1182 unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS; 1183 unsigned long *addr = (unsigned long *)ksp; 1184 addr += n; 1185 if (regs_within_kernel_stack(regs, (unsigned long)addr)) 1186 return *addr; 1187 else 1188 return 0; 1189 } 1190