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 <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 <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 struct membuf to) 249 { 250 const struct pt_regs *regs = task_pt_regs(target); 251 struct reg_window window; 252 253 if (target == current) 254 flushw_user(); 255 256 membuf_write(&to, regs->u_regs, 16 * sizeof(u64)); 257 if (!to.left) 258 return 0; 259 if (regwindow64_get(target, regs, &window)) 260 return -EFAULT; 261 membuf_write(&to, &window, 16 * sizeof(u64)); 262 /* TSTATE, TPC, TNPC */ 263 membuf_write(&to, ®s->tstate, 3 * sizeof(u64)); 264 return membuf_store(&to, (u64)regs->y); 265 } 266 267 static int genregs64_set(struct task_struct *target, 268 const struct user_regset *regset, 269 unsigned int pos, unsigned int count, 270 const void *kbuf, const void __user *ubuf) 271 { 272 struct pt_regs *regs = task_pt_regs(target); 273 int ret; 274 275 if (target == current) 276 flushw_user(); 277 278 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 279 regs->u_regs, 280 0, 16 * sizeof(u64)); 281 if (!ret && count && pos < (32 * sizeof(u64))) { 282 struct reg_window window; 283 284 if (regwindow64_get(target, regs, &window)) 285 return -EFAULT; 286 287 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 288 &window, 289 16 * sizeof(u64), 290 32 * sizeof(u64)); 291 292 if (!ret && 293 regwindow64_set(target, regs, &window)) 294 return -EFAULT; 295 } 296 297 if (!ret && count > 0) { 298 unsigned long tstate; 299 300 /* TSTATE */ 301 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 302 &tstate, 303 32 * sizeof(u64), 304 33 * sizeof(u64)); 305 if (!ret) { 306 /* Only the condition codes and the "in syscall" 307 * state can be modified in the %tstate register. 308 */ 309 tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); 310 regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); 311 regs->tstate |= tstate; 312 } 313 } 314 315 if (!ret) { 316 /* TPC, TNPC */ 317 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 318 ®s->tpc, 319 33 * sizeof(u64), 320 35 * sizeof(u64)); 321 } 322 323 if (!ret) { 324 unsigned long y = regs->y; 325 326 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 327 &y, 328 35 * sizeof(u64), 329 36 * sizeof(u64)); 330 if (!ret) 331 regs->y = y; 332 } 333 334 if (!ret) 335 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 336 36 * sizeof(u64), -1); 337 338 return ret; 339 } 340 341 static int fpregs64_get(struct task_struct *target, 342 const struct user_regset *regset, 343 struct membuf to) 344 { 345 struct thread_info *t = task_thread_info(target); 346 unsigned long fprs; 347 348 if (target == current) 349 save_and_clear_fpu(); 350 351 fprs = t->fpsaved[0]; 352 353 if (fprs & FPRS_DL) 354 membuf_write(&to, t->fpregs, 16 * sizeof(u64)); 355 else 356 membuf_zero(&to, 16 * sizeof(u64)); 357 358 if (fprs & FPRS_DU) 359 membuf_write(&to, t->fpregs + 16, 16 * sizeof(u64)); 360 else 361 membuf_zero(&to, 16 * sizeof(u64)); 362 if (fprs & FPRS_FEF) { 363 membuf_store(&to, t->xfsr[0]); 364 membuf_store(&to, t->gsr[0]); 365 } else { 366 membuf_zero(&to, 2 * sizeof(u64)); 367 } 368 return membuf_store(&to, fprs); 369 } 370 371 static int fpregs64_set(struct task_struct *target, 372 const struct user_regset *regset, 373 unsigned int pos, unsigned int count, 374 const void *kbuf, const void __user *ubuf) 375 { 376 unsigned long *fpregs = task_thread_info(target)->fpregs; 377 unsigned long fprs; 378 int ret; 379 380 if (target == current) 381 save_and_clear_fpu(); 382 383 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 384 fpregs, 385 0, 32 * sizeof(u64)); 386 if (!ret) 387 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 388 task_thread_info(target)->xfsr, 389 32 * sizeof(u64), 390 33 * sizeof(u64)); 391 if (!ret) 392 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 393 task_thread_info(target)->gsr, 394 33 * sizeof(u64), 395 34 * sizeof(u64)); 396 397 fprs = task_thread_info(target)->fpsaved[0]; 398 if (!ret && count > 0) { 399 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 400 &fprs, 401 34 * sizeof(u64), 402 35 * sizeof(u64)); 403 } 404 405 fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU); 406 task_thread_info(target)->fpsaved[0] = fprs; 407 408 if (!ret) 409 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 410 35 * sizeof(u64), -1); 411 return ret; 412 } 413 414 static const struct user_regset sparc64_regsets[] = { 415 /* Format is: 416 * G0 --> G7 417 * O0 --> O7 418 * L0 --> L7 419 * I0 --> I7 420 * TSTATE, TPC, TNPC, Y 421 */ 422 [REGSET_GENERAL] = { 423 .core_note_type = NT_PRSTATUS, 424 .n = 36, 425 .size = sizeof(u64), .align = sizeof(u64), 426 .regset_get = genregs64_get, .set = genregs64_set 427 }, 428 /* Format is: 429 * F0 --> F63 430 * FSR 431 * GSR 432 * FPRS 433 */ 434 [REGSET_FP] = { 435 .core_note_type = NT_PRFPREG, 436 .n = 35, 437 .size = sizeof(u64), .align = sizeof(u64), 438 .regset_get = fpregs64_get, .set = fpregs64_set 439 }, 440 }; 441 442 static int getregs64_get(struct task_struct *target, 443 const struct user_regset *regset, 444 struct membuf to) 445 { 446 const struct pt_regs *regs = task_pt_regs(target); 447 448 if (target == current) 449 flushw_user(); 450 451 membuf_write(&to, regs->u_regs + 1, 15 * sizeof(u64)); 452 membuf_store(&to, (u64)0); 453 membuf_write(&to, ®s->tstate, 3 * sizeof(u64)); 454 return membuf_store(&to, (u64)regs->y); 455 } 456 457 static int setregs64_set(struct task_struct *target, 458 const struct user_regset *regset, 459 unsigned int pos, unsigned int count, 460 const void *kbuf, const void __user *ubuf) 461 { 462 struct pt_regs *regs = task_pt_regs(target); 463 unsigned long y = regs->y; 464 unsigned long tstate; 465 int ret; 466 467 if (target == current) 468 flushw_user(); 469 470 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 471 regs->u_regs + 1, 472 0 * sizeof(u64), 473 15 * sizeof(u64)); 474 if (ret) 475 return ret; 476 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 477 15 * sizeof(u64), 16 * sizeof(u64)); 478 /* TSTATE */ 479 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 480 &tstate, 481 16 * sizeof(u64), 482 17 * sizeof(u64)); 483 if (ret) 484 return ret; 485 /* Only the condition codes and the "in syscall" 486 * state can be modified in the %tstate register. 487 */ 488 tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); 489 regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); 490 regs->tstate |= tstate; 491 492 /* TPC, TNPC */ 493 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 494 ®s->tpc, 495 17 * sizeof(u64), 496 19 * sizeof(u64)); 497 if (ret) 498 return ret; 499 /* Y */ 500 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 501 &y, 502 19 * sizeof(u64), 503 20 * sizeof(u64)); 504 if (!ret) 505 regs->y = y; 506 return ret; 507 } 508 509 static const struct user_regset ptrace64_regsets[] = { 510 /* Format is: 511 * G1 --> G7 512 * O0 --> O7 513 * 0 514 * TSTATE, TPC, TNPC, Y 515 */ 516 [REGSET_GENERAL] = { 517 .n = 20, .size = sizeof(u64), 518 .regset_get = getregs64_get, .set = setregs64_set, 519 }, 520 }; 521 522 static const struct user_regset_view ptrace64_view = { 523 .regsets = ptrace64_regsets, .n = ARRAY_SIZE(ptrace64_regsets) 524 }; 525 526 static const struct user_regset_view user_sparc64_view = { 527 .name = "sparc64", .e_machine = EM_SPARCV9, 528 .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets) 529 }; 530 531 #ifdef CONFIG_COMPAT 532 static int genregs32_get(struct task_struct *target, 533 const struct user_regset *regset, 534 struct membuf to) 535 { 536 const struct pt_regs *regs = task_pt_regs(target); 537 u32 uregs[16]; 538 int i; 539 540 if (target == current) 541 flushw_user(); 542 543 for (i = 0; i < 16; i++) 544 membuf_store(&to, (u32)regs->u_regs[i]); 545 if (!to.left) 546 return 0; 547 if (get_from_target(target, regs->u_regs[UREG_I6], 548 uregs, sizeof(uregs))) 549 return -EFAULT; 550 membuf_write(&to, uregs, 16 * sizeof(u32)); 551 membuf_store(&to, (u32)tstate_to_psr(regs->tstate)); 552 membuf_store(&to, (u32)(regs->tpc)); 553 membuf_store(&to, (u32)(regs->tnpc)); 554 membuf_store(&to, (u32)(regs->y)); 555 return membuf_zero(&to, 2 * sizeof(u32)); 556 } 557 558 static int genregs32_set(struct task_struct *target, 559 const struct user_regset *regset, 560 unsigned int pos, unsigned int count, 561 const void *kbuf, const void __user *ubuf) 562 { 563 struct pt_regs *regs = task_pt_regs(target); 564 compat_ulong_t __user *reg_window; 565 const compat_ulong_t *k = kbuf; 566 const compat_ulong_t __user *u = ubuf; 567 compat_ulong_t reg; 568 569 if (target == current) 570 flushw_user(); 571 572 pos /= sizeof(reg); 573 count /= sizeof(reg); 574 575 if (kbuf) { 576 for (; count > 0 && pos < 16; count--) 577 regs->u_regs[pos++] = *k++; 578 579 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 580 reg_window -= 16; 581 if (target == current) { 582 for (; count > 0 && pos < 32; count--) { 583 if (put_user(*k++, ®_window[pos++])) 584 return -EFAULT; 585 } 586 } else { 587 for (; count > 0 && pos < 32; count--) { 588 if (access_process_vm(target, 589 (unsigned long) 590 ®_window[pos], 591 (void *) k, 592 sizeof(*k), 593 FOLL_FORCE | FOLL_WRITE) 594 != sizeof(*k)) 595 return -EFAULT; 596 k++; 597 pos++; 598 } 599 } 600 } else { 601 for (; count > 0 && pos < 16; count--) { 602 if (get_user(reg, u++)) 603 return -EFAULT; 604 regs->u_regs[pos++] = reg; 605 } 606 607 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 608 reg_window -= 16; 609 if (target == current) { 610 for (; count > 0 && pos < 32; count--) { 611 if (get_user(reg, u++) || 612 put_user(reg, ®_window[pos++])) 613 return -EFAULT; 614 } 615 } else { 616 for (; count > 0 && pos < 32; count--) { 617 if (get_user(reg, u++)) 618 return -EFAULT; 619 if (access_process_vm(target, 620 (unsigned long) 621 ®_window[pos], 622 ®, sizeof(reg), 623 FOLL_FORCE | FOLL_WRITE) 624 != sizeof(reg)) 625 return -EFAULT; 626 pos++; 627 u++; 628 } 629 } 630 } 631 while (count > 0) { 632 unsigned long tstate; 633 634 if (kbuf) 635 reg = *k++; 636 else if (get_user(reg, u++)) 637 return -EFAULT; 638 639 switch (pos) { 640 case 32: /* PSR */ 641 tstate = regs->tstate; 642 tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); 643 tstate |= psr_to_tstate_icc(reg); 644 if (reg & PSR_SYSCALL) 645 tstate |= TSTATE_SYSCALL; 646 regs->tstate = tstate; 647 break; 648 case 33: /* PC */ 649 regs->tpc = reg; 650 break; 651 case 34: /* NPC */ 652 regs->tnpc = reg; 653 break; 654 case 35: /* Y */ 655 regs->y = reg; 656 break; 657 case 36: /* WIM */ 658 case 37: /* TBR */ 659 break; 660 default: 661 goto finish; 662 } 663 664 pos++; 665 count--; 666 } 667 finish: 668 pos *= sizeof(reg); 669 count *= sizeof(reg); 670 671 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 672 38 * sizeof(reg), -1); 673 return 0; 674 } 675 676 static int fpregs32_get(struct task_struct *target, 677 const struct user_regset *regset, 678 struct membuf to) 679 { 680 struct thread_info *t = task_thread_info(target); 681 bool enabled; 682 683 if (target == current) 684 save_and_clear_fpu(); 685 686 enabled = t->fpsaved[0] & FPRS_FEF; 687 688 membuf_write(&to, t->fpregs, 32 * sizeof(u32)); 689 membuf_zero(&to, sizeof(u32)); 690 if (enabled) 691 membuf_store(&to, (u32)t->xfsr[0]); 692 else 693 membuf_zero(&to, sizeof(u32)); 694 membuf_store(&to, (u32)((enabled << 8) | (8 << 16))); 695 return membuf_zero(&to, 64 * sizeof(u32)); 696 } 697 698 static int fpregs32_set(struct task_struct *target, 699 const struct user_regset *regset, 700 unsigned int pos, unsigned int count, 701 const void *kbuf, const void __user *ubuf) 702 { 703 unsigned long *fpregs = task_thread_info(target)->fpregs; 704 unsigned long fprs; 705 int ret; 706 707 if (target == current) 708 save_and_clear_fpu(); 709 710 fprs = task_thread_info(target)->fpsaved[0]; 711 712 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 713 fpregs, 714 0, 32 * sizeof(u32)); 715 if (!ret) 716 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 717 32 * sizeof(u32), 718 33 * sizeof(u32)); 719 if (!ret && count > 0) { 720 compat_ulong_t fsr; 721 unsigned long val; 722 723 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 724 &fsr, 725 33 * sizeof(u32), 726 34 * sizeof(u32)); 727 if (!ret) { 728 val = task_thread_info(target)->xfsr[0]; 729 val &= 0xffffffff00000000UL; 730 val |= fsr; 731 task_thread_info(target)->xfsr[0] = val; 732 } 733 } 734 735 fprs |= (FPRS_FEF | FPRS_DL); 736 task_thread_info(target)->fpsaved[0] = fprs; 737 738 if (!ret) 739 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 740 34 * sizeof(u32), -1); 741 return ret; 742 } 743 744 static const struct user_regset sparc32_regsets[] = { 745 /* Format is: 746 * G0 --> G7 747 * O0 --> O7 748 * L0 --> L7 749 * I0 --> I7 750 * PSR, PC, nPC, Y, WIM, TBR 751 */ 752 [REGSET_GENERAL] = { 753 .core_note_type = NT_PRSTATUS, 754 .n = 38, 755 .size = sizeof(u32), .align = sizeof(u32), 756 .regset_get = genregs32_get, .set = genregs32_set 757 }, 758 /* Format is: 759 * F0 --> F31 760 * empty 32-bit word 761 * FSR (32--bit word) 762 * FPU QUEUE COUNT (8-bit char) 763 * FPU QUEUE ENTRYSIZE (8-bit char) 764 * FPU ENABLED (8-bit char) 765 * empty 8-bit char 766 * FPU QUEUE (64 32-bit ints) 767 */ 768 [REGSET_FP] = { 769 .core_note_type = NT_PRFPREG, 770 .n = 99, 771 .size = sizeof(u32), .align = sizeof(u32), 772 .regset_get = fpregs32_get, .set = fpregs32_set 773 }, 774 }; 775 776 static int getregs_get(struct task_struct *target, 777 const struct user_regset *regset, 778 struct membuf to) 779 { 780 const struct pt_regs *regs = task_pt_regs(target); 781 int i; 782 783 if (target == current) 784 flushw_user(); 785 786 membuf_store(&to, (u32)tstate_to_psr(regs->tstate)); 787 membuf_store(&to, (u32)(regs->tpc)); 788 membuf_store(&to, (u32)(regs->tnpc)); 789 membuf_store(&to, (u32)(regs->y)); 790 for (i = 1; i < 16; i++) 791 membuf_store(&to, (u32)regs->u_regs[i]); 792 return to.left; 793 } 794 795 static int setregs_set(struct task_struct *target, 796 const struct user_regset *regset, 797 unsigned int pos, unsigned int count, 798 const void *kbuf, const void __user *ubuf) 799 { 800 struct pt_regs *regs = task_pt_regs(target); 801 unsigned long tstate; 802 u32 uregs[19]; 803 int i, ret; 804 805 if (target == current) 806 flushw_user(); 807 808 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 809 uregs, 810 0, 19 * sizeof(u32)); 811 if (ret) 812 return ret; 813 814 tstate = regs->tstate; 815 tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); 816 tstate |= psr_to_tstate_icc(uregs[0]); 817 if (uregs[0] & PSR_SYSCALL) 818 tstate |= TSTATE_SYSCALL; 819 regs->tstate = tstate; 820 regs->tpc = uregs[1]; 821 regs->tnpc = uregs[2]; 822 regs->y = uregs[3]; 823 824 for (i = 1; i < 15; i++) 825 regs->u_regs[i] = uregs[3 + i]; 826 return 0; 827 } 828 829 static int getfpregs_get(struct task_struct *target, 830 const struct user_regset *regset, 831 struct membuf to) 832 { 833 struct thread_info *t = task_thread_info(target); 834 835 if (target == current) 836 save_and_clear_fpu(); 837 838 membuf_write(&to, t->fpregs, 32 * sizeof(u32)); 839 if (t->fpsaved[0] & FPRS_FEF) 840 membuf_store(&to, (u32)t->xfsr[0]); 841 else 842 membuf_zero(&to, sizeof(u32)); 843 return membuf_zero(&to, 35 * sizeof(u32)); 844 } 845 846 static int setfpregs_set(struct task_struct *target, 847 const struct user_regset *regset, 848 unsigned int pos, unsigned int count, 849 const void *kbuf, const void __user *ubuf) 850 { 851 unsigned long *fpregs = task_thread_info(target)->fpregs; 852 unsigned long fprs; 853 int ret; 854 855 if (target == current) 856 save_and_clear_fpu(); 857 858 fprs = task_thread_info(target)->fpsaved[0]; 859 860 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 861 fpregs, 862 0, 32 * sizeof(u32)); 863 if (!ret) { 864 compat_ulong_t fsr; 865 unsigned long val; 866 867 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 868 &fsr, 869 32 * sizeof(u32), 870 33 * sizeof(u32)); 871 if (!ret) { 872 val = task_thread_info(target)->xfsr[0]; 873 val &= 0xffffffff00000000UL; 874 val |= fsr; 875 task_thread_info(target)->xfsr[0] = val; 876 } 877 } 878 879 fprs |= (FPRS_FEF | FPRS_DL); 880 task_thread_info(target)->fpsaved[0] = fprs; 881 return ret; 882 } 883 884 static const struct user_regset ptrace32_regsets[] = { 885 [REGSET_GENERAL] = { 886 .n = 19, .size = sizeof(u32), 887 .regset_get = getregs_get, .set = setregs_set, 888 }, 889 [REGSET_FP] = { 890 .n = 68, .size = sizeof(u32), 891 .regset_get = getfpregs_get, .set = setfpregs_set, 892 }, 893 }; 894 895 static const struct user_regset_view ptrace32_view = { 896 .regsets = ptrace32_regsets, .n = ARRAY_SIZE(ptrace32_regsets) 897 }; 898 899 static const struct user_regset_view user_sparc32_view = { 900 .name = "sparc", .e_machine = EM_SPARC, 901 .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets) 902 }; 903 #endif /* CONFIG_COMPAT */ 904 905 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 906 { 907 #ifdef CONFIG_COMPAT 908 if (test_tsk_thread_flag(task, TIF_32BIT)) 909 return &user_sparc32_view; 910 #endif 911 return &user_sparc64_view; 912 } 913 914 #ifdef CONFIG_COMPAT 915 struct compat_fps { 916 unsigned int regs[32]; 917 unsigned int fsr; 918 unsigned int flags; 919 unsigned int extra; 920 unsigned int fpqd; 921 struct compat_fq { 922 unsigned int insnaddr; 923 unsigned int insn; 924 } fpq[16]; 925 }; 926 927 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 928 compat_ulong_t caddr, compat_ulong_t cdata) 929 { 930 compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4]; 931 struct pt_regs32 __user *pregs; 932 struct compat_fps __user *fps; 933 unsigned long addr2 = caddr2; 934 unsigned long addr = caddr; 935 unsigned long data = cdata; 936 int ret; 937 938 pregs = (struct pt_regs32 __user *) addr; 939 fps = (struct compat_fps __user *) addr; 940 941 switch (request) { 942 case PTRACE_PEEKUSR: 943 ret = (addr != 0) ? -EIO : 0; 944 break; 945 946 case PTRACE_GETREGS: 947 ret = copy_regset_to_user(child, &ptrace32_view, 948 REGSET_GENERAL, 0, 949 19 * sizeof(u32), 950 pregs); 951 break; 952 953 case PTRACE_SETREGS: 954 ret = copy_regset_from_user(child, &ptrace32_view, 955 REGSET_GENERAL, 0, 956 19 * sizeof(u32), 957 pregs); 958 break; 959 960 case PTRACE_GETFPREGS: 961 ret = copy_regset_to_user(child, &ptrace32_view, 962 REGSET_FP, 0, 963 68 * sizeof(u32), 964 fps); 965 break; 966 967 case PTRACE_SETFPREGS: 968 ret = copy_regset_from_user(child, &ptrace32_view, 969 REGSET_FP, 0, 970 33 * sizeof(u32), 971 fps); 972 break; 973 974 case PTRACE_READTEXT: 975 case PTRACE_READDATA: 976 ret = ptrace_readdata(child, addr, 977 (char __user *)addr2, data); 978 if (ret == data) 979 ret = 0; 980 else if (ret >= 0) 981 ret = -EIO; 982 break; 983 984 case PTRACE_WRITETEXT: 985 case PTRACE_WRITEDATA: 986 ret = ptrace_writedata(child, (char __user *) addr2, 987 addr, data); 988 if (ret == data) 989 ret = 0; 990 else if (ret >= 0) 991 ret = -EIO; 992 break; 993 994 default: 995 if (request == PTRACE_SPARC_DETACH) 996 request = PTRACE_DETACH; 997 ret = compat_ptrace_request(child, request, addr, data); 998 break; 999 } 1000 1001 return ret; 1002 } 1003 #endif /* CONFIG_COMPAT */ 1004 1005 struct fps { 1006 unsigned int regs[64]; 1007 unsigned long fsr; 1008 }; 1009 1010 long arch_ptrace(struct task_struct *child, long request, 1011 unsigned long addr, unsigned long data) 1012 { 1013 const struct user_regset_view *view = task_user_regset_view(current); 1014 unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; 1015 struct pt_regs __user *pregs; 1016 struct fps __user *fps; 1017 void __user *addr2p; 1018 int ret; 1019 1020 pregs = (struct pt_regs __user *) addr; 1021 fps = (struct fps __user *) addr; 1022 addr2p = (void __user *) addr2; 1023 1024 switch (request) { 1025 case PTRACE_PEEKUSR: 1026 ret = (addr != 0) ? -EIO : 0; 1027 break; 1028 1029 case PTRACE_GETREGS64: 1030 ret = copy_regset_to_user(child, &ptrace64_view, 1031 REGSET_GENERAL, 0, 1032 19 * sizeof(u64), 1033 pregs); 1034 break; 1035 1036 case PTRACE_SETREGS64: 1037 ret = copy_regset_from_user(child, &ptrace64_view, 1038 REGSET_GENERAL, 0, 1039 19 * sizeof(u64), 1040 pregs); 1041 break; 1042 1043 case PTRACE_GETFPREGS64: 1044 ret = copy_regset_to_user(child, view, REGSET_FP, 1045 0 * sizeof(u64), 1046 33 * sizeof(u64), 1047 fps); 1048 break; 1049 1050 case PTRACE_SETFPREGS64: 1051 ret = copy_regset_from_user(child, view, REGSET_FP, 1052 0 * sizeof(u64), 1053 33 * sizeof(u64), 1054 fps); 1055 break; 1056 1057 case PTRACE_READTEXT: 1058 case PTRACE_READDATA: 1059 ret = ptrace_readdata(child, addr, addr2p, data); 1060 if (ret == data) 1061 ret = 0; 1062 else if (ret >= 0) 1063 ret = -EIO; 1064 break; 1065 1066 case PTRACE_WRITETEXT: 1067 case PTRACE_WRITEDATA: 1068 ret = ptrace_writedata(child, addr2p, addr, data); 1069 if (ret == data) 1070 ret = 0; 1071 else if (ret >= 0) 1072 ret = -EIO; 1073 break; 1074 1075 default: 1076 if (request == PTRACE_SPARC_DETACH) 1077 request = PTRACE_DETACH; 1078 ret = ptrace_request(child, request, addr, data); 1079 break; 1080 } 1081 1082 return ret; 1083 } 1084 1085 asmlinkage int syscall_trace_enter(struct pt_regs *regs) 1086 { 1087 int ret = 0; 1088 1089 /* do the secure computing check first */ 1090 secure_computing_strict(regs->u_regs[UREG_G1]); 1091 1092 if (test_thread_flag(TIF_NOHZ)) 1093 user_exit(); 1094 1095 if (test_thread_flag(TIF_SYSCALL_TRACE)) 1096 ret = ptrace_report_syscall_entry(regs); 1097 1098 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 1099 trace_sys_enter(regs, regs->u_regs[UREG_G1]); 1100 1101 audit_syscall_entry(regs->u_regs[UREG_G1], regs->u_regs[UREG_I0], 1102 regs->u_regs[UREG_I1], regs->u_regs[UREG_I2], 1103 regs->u_regs[UREG_I3]); 1104 1105 return ret; 1106 } 1107 1108 asmlinkage void syscall_trace_leave(struct pt_regs *regs) 1109 { 1110 if (test_thread_flag(TIF_NOHZ)) 1111 user_exit(); 1112 1113 audit_syscall_exit(regs); 1114 1115 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 1116 trace_sys_exit(regs, regs->u_regs[UREG_I0]); 1117 1118 if (test_thread_flag(TIF_SYSCALL_TRACE)) 1119 ptrace_report_syscall_exit(regs, 0); 1120 1121 if (test_thread_flag(TIF_NOHZ)) 1122 user_enter(); 1123 } 1124 1125 /** 1126 * regs_query_register_offset() - query register offset from its name 1127 * @name: the name of a register 1128 * 1129 * regs_query_register_offset() returns the offset of a register in struct 1130 * pt_regs from its name. If the name is invalid, this returns -EINVAL; 1131 */ 1132 int regs_query_register_offset(const char *name) 1133 { 1134 const struct pt_regs_offset *roff; 1135 1136 for (roff = regoffset_table; roff->name != NULL; roff++) 1137 if (!strcmp(roff->name, name)) 1138 return roff->offset; 1139 return -EINVAL; 1140 } 1141 1142 /** 1143 * regs_within_kernel_stack() - check the address in the stack 1144 * @regs: pt_regs which contains kernel stack pointer. 1145 * @addr: address which is checked. 1146 * 1147 * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). 1148 * If @addr is within the kernel stack, it returns true. If not, returns false. 1149 */ 1150 static inline int regs_within_kernel_stack(struct pt_regs *regs, 1151 unsigned long addr) 1152 { 1153 unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS; 1154 return ((addr & ~(THREAD_SIZE - 1)) == 1155 (ksp & ~(THREAD_SIZE - 1))); 1156 } 1157 1158 /** 1159 * regs_get_kernel_stack_nth() - get Nth entry of the stack 1160 * @regs: pt_regs which contains kernel stack pointer. 1161 * @n: stack entry number. 1162 * 1163 * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which 1164 * is specified by @regs. If the @n th entry is NOT in the kernel stack, 1165 * this returns 0. 1166 */ 1167 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) 1168 { 1169 unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS; 1170 unsigned long *addr = (unsigned long *)ksp; 1171 addr += n; 1172 if (regs_within_kernel_stack(regs, (unsigned long)addr)) 1173 return *addr; 1174 else 1175 return 0; 1176 } 1177
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.