1 /* 2 * Based on arch/arm/kernel/ptrace.c 3 * 4 * By Ross Biro 1/23/92 5 * edited by Linus Torvalds 6 * ARM modifications Copyright (C) 2000 Russell King 7 * Copyright (C) 2012 ARM Ltd. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include <linux/kernel.h> 23 #include <linux/sched.h> 24 #include <linux/mm.h> 25 #include <linux/smp.h> 26 #include <linux/ptrace.h> 27 #include <linux/user.h> 28 #include <linux/security.h> 29 #include <linux/init.h> 30 #include <linux/signal.h> 31 #include <linux/uaccess.h> 32 #include <linux/perf_event.h> 33 #include <linux/hw_breakpoint.h> 34 #include <linux/regset.h> 35 #include <linux/tracehook.h> 36 #include <linux/elf.h> 37 38 #include <asm/compat.h> 39 #include <asm/debug-monitors.h> 40 #include <asm/pgtable.h> 41 #include <asm/traps.h> 42 #include <asm/system_misc.h> 43 44 /* 45 * TODO: does not yet catch signals sent when the child dies. 46 * in exit.c or in signal.c. 47 */ 48 49 /* 50 * Called by kernel/ptrace.c when detaching.. 51 */ 52 void ptrace_disable(struct task_struct *child) 53 { 54 } 55 56 #ifdef CONFIG_HAVE_HW_BREAKPOINT 57 /* 58 * Handle hitting a HW-breakpoint. 59 */ 60 static void ptrace_hbptriggered(struct perf_event *bp, 61 struct perf_sample_data *data, 62 struct pt_regs *regs) 63 { 64 struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp); 65 siginfo_t info = { 66 .si_signo = SIGTRAP, 67 .si_errno = 0, 68 .si_code = TRAP_HWBKPT, 69 .si_addr = (void __user *)(bkpt->trigger), 70 }; 71 72 #ifdef CONFIG_COMPAT 73 int i; 74 75 if (!is_compat_task()) 76 goto send_sig; 77 78 for (i = 0; i < ARM_MAX_BRP; ++i) { 79 if (current->thread.debug.hbp_break[i] == bp) { 80 info.si_errno = (i << 1) + 1; 81 break; 82 } 83 } 84 for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) { 85 if (current->thread.debug.hbp_watch[i] == bp) { 86 info.si_errno = -((i << 1) + 1); 87 break; 88 } 89 } 90 91 send_sig: 92 #endif 93 force_sig_info(SIGTRAP, &info, current); 94 } 95 96 /* 97 * Unregister breakpoints from this task and reset the pointers in 98 * the thread_struct. 99 */ 100 void flush_ptrace_hw_breakpoint(struct task_struct *tsk) 101 { 102 int i; 103 struct thread_struct *t = &tsk->thread; 104 105 for (i = 0; i < ARM_MAX_BRP; i++) { 106 if (t->debug.hbp_break[i]) { 107 unregister_hw_breakpoint(t->debug.hbp_break[i]); 108 t->debug.hbp_break[i] = NULL; 109 } 110 } 111 112 for (i = 0; i < ARM_MAX_WRP; i++) { 113 if (t->debug.hbp_watch[i]) { 114 unregister_hw_breakpoint(t->debug.hbp_watch[i]); 115 t->debug.hbp_watch[i] = NULL; 116 } 117 } 118 } 119 120 void ptrace_hw_copy_thread(struct task_struct *tsk) 121 { 122 memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); 123 } 124 125 static struct perf_event *ptrace_hbp_get_event(unsigned int note_type, 126 struct task_struct *tsk, 127 unsigned long idx) 128 { 129 struct perf_event *bp = ERR_PTR(-EINVAL); 130 131 switch (note_type) { 132 case NT_ARM_HW_BREAK: 133 if (idx < ARM_MAX_BRP) 134 bp = tsk->thread.debug.hbp_break[idx]; 135 break; 136 case NT_ARM_HW_WATCH: 137 if (idx < ARM_MAX_WRP) 138 bp = tsk->thread.debug.hbp_watch[idx]; 139 break; 140 } 141 142 return bp; 143 } 144 145 static int ptrace_hbp_set_event(unsigned int note_type, 146 struct task_struct *tsk, 147 unsigned long idx, 148 struct perf_event *bp) 149 { 150 int err = -EINVAL; 151 152 switch (note_type) { 153 case NT_ARM_HW_BREAK: 154 if (idx < ARM_MAX_BRP) { 155 tsk->thread.debug.hbp_break[idx] = bp; 156 err = 0; 157 } 158 break; 159 case NT_ARM_HW_WATCH: 160 if (idx < ARM_MAX_WRP) { 161 tsk->thread.debug.hbp_watch[idx] = bp; 162 err = 0; 163 } 164 break; 165 } 166 167 return err; 168 } 169 170 static struct perf_event *ptrace_hbp_create(unsigned int note_type, 171 struct task_struct *tsk, 172 unsigned long idx) 173 { 174 struct perf_event *bp; 175 struct perf_event_attr attr; 176 int err, type; 177 178 switch (note_type) { 179 case NT_ARM_HW_BREAK: 180 type = HW_BREAKPOINT_X; 181 break; 182 case NT_ARM_HW_WATCH: 183 type = HW_BREAKPOINT_RW; 184 break; 185 default: 186 return ERR_PTR(-EINVAL); 187 } 188 189 ptrace_breakpoint_init(&attr); 190 191 /* 192 * Initialise fields to sane defaults 193 * (i.e. values that will pass validation). 194 */ 195 attr.bp_addr = 0; 196 attr.bp_len = HW_BREAKPOINT_LEN_4; 197 attr.bp_type = type; 198 attr.disabled = 1; 199 200 bp = register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL, tsk); 201 if (IS_ERR(bp)) 202 return bp; 203 204 err = ptrace_hbp_set_event(note_type, tsk, idx, bp); 205 if (err) 206 return ERR_PTR(err); 207 208 return bp; 209 } 210 211 static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type, 212 struct arch_hw_breakpoint_ctrl ctrl, 213 struct perf_event_attr *attr) 214 { 215 int err, len, type, disabled = !ctrl.enabled; 216 217 if (disabled) { 218 len = 0; 219 type = HW_BREAKPOINT_EMPTY; 220 } else { 221 err = arch_bp_generic_fields(ctrl, &len, &type); 222 if (err) 223 return err; 224 225 switch (note_type) { 226 case NT_ARM_HW_BREAK: 227 if ((type & HW_BREAKPOINT_X) != type) 228 return -EINVAL; 229 break; 230 case NT_ARM_HW_WATCH: 231 if ((type & HW_BREAKPOINT_RW) != type) 232 return -EINVAL; 233 break; 234 default: 235 return -EINVAL; 236 } 237 } 238 239 attr->bp_len = len; 240 attr->bp_type = type; 241 attr->disabled = disabled; 242 243 return 0; 244 } 245 246 static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info) 247 { 248 u8 num; 249 u32 reg = 0; 250 251 switch (note_type) { 252 case NT_ARM_HW_BREAK: 253 num = hw_breakpoint_slots(TYPE_INST); 254 break; 255 case NT_ARM_HW_WATCH: 256 num = hw_breakpoint_slots(TYPE_DATA); 257 break; 258 default: 259 return -EINVAL; 260 } 261 262 reg |= debug_monitors_arch(); 263 reg <<= 8; 264 reg |= num; 265 266 *info = reg; 267 return 0; 268 } 269 270 static int ptrace_hbp_get_ctrl(unsigned int note_type, 271 struct task_struct *tsk, 272 unsigned long idx, 273 u32 *ctrl) 274 { 275 struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); 276 277 if (IS_ERR(bp)) 278 return PTR_ERR(bp); 279 280 *ctrl = bp ? encode_ctrl_reg(counter_arch_bp(bp)->ctrl) : 0; 281 return 0; 282 } 283 284 static int ptrace_hbp_get_addr(unsigned int note_type, 285 struct task_struct *tsk, 286 unsigned long idx, 287 u64 *addr) 288 { 289 struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); 290 291 if (IS_ERR(bp)) 292 return PTR_ERR(bp); 293 294 *addr = bp ? bp->attr.bp_addr : 0; 295 return 0; 296 } 297 298 static struct perf_event *ptrace_hbp_get_initialised_bp(unsigned int note_type, 299 struct task_struct *tsk, 300 unsigned long idx) 301 { 302 struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); 303 304 if (!bp) 305 bp = ptrace_hbp_create(note_type, tsk, idx); 306 307 return bp; 308 } 309 310 static int ptrace_hbp_set_ctrl(unsigned int note_type, 311 struct task_struct *tsk, 312 unsigned long idx, 313 u32 uctrl) 314 { 315 int err; 316 struct perf_event *bp; 317 struct perf_event_attr attr; 318 struct arch_hw_breakpoint_ctrl ctrl; 319 320 bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); 321 if (IS_ERR(bp)) { 322 err = PTR_ERR(bp); 323 return err; 324 } 325 326 attr = bp->attr; 327 decode_ctrl_reg(uctrl, &ctrl); 328 err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr); 329 if (err) 330 return err; 331 332 return modify_user_hw_breakpoint(bp, &attr); 333 } 334 335 static int ptrace_hbp_set_addr(unsigned int note_type, 336 struct task_struct *tsk, 337 unsigned long idx, 338 u64 addr) 339 { 340 int err; 341 struct perf_event *bp; 342 struct perf_event_attr attr; 343 344 bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); 345 if (IS_ERR(bp)) { 346 err = PTR_ERR(bp); 347 return err; 348 } 349 350 attr = bp->attr; 351 attr.bp_addr = addr; 352 err = modify_user_hw_breakpoint(bp, &attr); 353 return err; 354 } 355 356 #define PTRACE_HBP_ADDR_SZ sizeof(u64) 357 #define PTRACE_HBP_CTRL_SZ sizeof(u32) 358 #define PTRACE_HBP_PAD_SZ sizeof(u32) 359 360 static int hw_break_get(struct task_struct *target, 361 const struct user_regset *regset, 362 unsigned int pos, unsigned int count, 363 void *kbuf, void __user *ubuf) 364 { 365 unsigned int note_type = regset->core_note_type; 366 int ret, idx = 0, offset, limit; 367 u32 info, ctrl; 368 u64 addr; 369 370 /* Resource info */ 371 ret = ptrace_hbp_get_resource_info(note_type, &info); 372 if (ret) 373 return ret; 374 375 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0, 376 sizeof(info)); 377 if (ret) 378 return ret; 379 380 /* Pad */ 381 offset = offsetof(struct user_hwdebug_state, pad); 382 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, offset, 383 offset + PTRACE_HBP_PAD_SZ); 384 if (ret) 385 return ret; 386 387 /* (address, ctrl) registers */ 388 offset = offsetof(struct user_hwdebug_state, dbg_regs); 389 limit = regset->n * regset->size; 390 while (count && offset < limit) { 391 ret = ptrace_hbp_get_addr(note_type, target, idx, &addr); 392 if (ret) 393 return ret; 394 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &addr, 395 offset, offset + PTRACE_HBP_ADDR_SZ); 396 if (ret) 397 return ret; 398 offset += PTRACE_HBP_ADDR_SZ; 399 400 ret = ptrace_hbp_get_ctrl(note_type, target, idx, &ctrl); 401 if (ret) 402 return ret; 403 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &ctrl, 404 offset, offset + PTRACE_HBP_CTRL_SZ); 405 if (ret) 406 return ret; 407 offset += PTRACE_HBP_CTRL_SZ; 408 409 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 410 offset, 411 offset + PTRACE_HBP_PAD_SZ); 412 if (ret) 413 return ret; 414 offset += PTRACE_HBP_PAD_SZ; 415 idx++; 416 } 417 418 return 0; 419 } 420 421 static int hw_break_set(struct task_struct *target, 422 const struct user_regset *regset, 423 unsigned int pos, unsigned int count, 424 const void *kbuf, const void __user *ubuf) 425 { 426 unsigned int note_type = regset->core_note_type; 427 int ret, idx = 0, offset, limit; 428 u32 ctrl; 429 u64 addr; 430 431 /* Resource info and pad */ 432 offset = offsetof(struct user_hwdebug_state, dbg_regs); 433 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset); 434 if (ret) 435 return ret; 436 437 /* (address, ctrl) registers */ 438 limit = regset->n * regset->size; 439 while (count && offset < limit) { 440 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr, 441 offset, offset + PTRACE_HBP_ADDR_SZ); 442 if (ret) 443 return ret; 444 ret = ptrace_hbp_set_addr(note_type, target, idx, addr); 445 if (ret) 446 return ret; 447 offset += PTRACE_HBP_ADDR_SZ; 448 449 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, 450 offset, offset + PTRACE_HBP_CTRL_SZ); 451 if (ret) 452 return ret; 453 ret = ptrace_hbp_set_ctrl(note_type, target, idx, ctrl); 454 if (ret) 455 return ret; 456 offset += PTRACE_HBP_CTRL_SZ; 457 458 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 459 offset, 460 offset + PTRACE_HBP_PAD_SZ); 461 if (ret) 462 return ret; 463 offset += PTRACE_HBP_PAD_SZ; 464 idx++; 465 } 466 467 return 0; 468 } 469 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 470 471 static int gpr_get(struct task_struct *target, 472 const struct user_regset *regset, 473 unsigned int pos, unsigned int count, 474 void *kbuf, void __user *ubuf) 475 { 476 struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs; 477 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); 478 } 479 480 static int gpr_set(struct task_struct *target, const struct user_regset *regset, 481 unsigned int pos, unsigned int count, 482 const void *kbuf, const void __user *ubuf) 483 { 484 int ret; 485 struct user_pt_regs newregs; 486 487 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1); 488 if (ret) 489 return ret; 490 491 if (!valid_user_regs(&newregs)) 492 return -EINVAL; 493 494 task_pt_regs(target)->user_regs = newregs; 495 return 0; 496 } 497 498 /* 499 * TODO: update fp accessors for lazy context switching (sync/flush hwstate) 500 */ 501 static int fpr_get(struct task_struct *target, const struct user_regset *regset, 502 unsigned int pos, unsigned int count, 503 void *kbuf, void __user *ubuf) 504 { 505 struct user_fpsimd_state *uregs; 506 uregs = &target->thread.fpsimd_state.user_fpsimd; 507 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); 508 } 509 510 static int fpr_set(struct task_struct *target, const struct user_regset *regset, 511 unsigned int pos, unsigned int count, 512 const void *kbuf, const void __user *ubuf) 513 { 514 int ret; 515 struct user_fpsimd_state newstate; 516 517 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1); 518 if (ret) 519 return ret; 520 521 target->thread.fpsimd_state.user_fpsimd = newstate; 522 return ret; 523 } 524 525 static int tls_get(struct task_struct *target, const struct user_regset *regset, 526 unsigned int pos, unsigned int count, 527 void *kbuf, void __user *ubuf) 528 { 529 unsigned long *tls = &target->thread.tp_value; 530 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, tls, 0, -1); 531 } 532 533 static int tls_set(struct task_struct *target, const struct user_regset *regset, 534 unsigned int pos, unsigned int count, 535 const void *kbuf, const void __user *ubuf) 536 { 537 int ret; 538 unsigned long tls; 539 540 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); 541 if (ret) 542 return ret; 543 544 target->thread.tp_value = tls; 545 return ret; 546 } 547 548 enum aarch64_regset { 549 REGSET_GPR, 550 REGSET_FPR, 551 REGSET_TLS, 552 #ifdef CONFIG_HAVE_HW_BREAKPOINT 553 REGSET_HW_BREAK, 554 REGSET_HW_WATCH, 555 #endif 556 }; 557 558 static const struct user_regset aarch64_regsets[] = { 559 [REGSET_GPR] = { 560 .core_note_type = NT_PRSTATUS, 561 .n = sizeof(struct user_pt_regs) / sizeof(u64), 562 .size = sizeof(u64), 563 .align = sizeof(u64), 564 .get = gpr_get, 565 .set = gpr_set 566 }, 567 [REGSET_FPR] = { 568 .core_note_type = NT_PRFPREG, 569 .n = sizeof(struct user_fpsimd_state) / sizeof(u32), 570 /* 571 * We pretend we have 32-bit registers because the fpsr and 572 * fpcr are 32-bits wide. 573 */ 574 .size = sizeof(u32), 575 .align = sizeof(u32), 576 .get = fpr_get, 577 .set = fpr_set 578 }, 579 [REGSET_TLS] = { 580 .core_note_type = NT_ARM_TLS, 581 .n = 1, 582 .size = sizeof(void *), 583 .align = sizeof(void *), 584 .get = tls_get, 585 .set = tls_set, 586 }, 587 #ifdef CONFIG_HAVE_HW_BREAKPOINT 588 [REGSET_HW_BREAK] = { 589 .core_note_type = NT_ARM_HW_BREAK, 590 .n = sizeof(struct user_hwdebug_state) / sizeof(u32), 591 .size = sizeof(u32), 592 .align = sizeof(u32), 593 .get = hw_break_get, 594 .set = hw_break_set, 595 }, 596 [REGSET_HW_WATCH] = { 597 .core_note_type = NT_ARM_HW_WATCH, 598 .n = sizeof(struct user_hwdebug_state) / sizeof(u32), 599 .size = sizeof(u32), 600 .align = sizeof(u32), 601 .get = hw_break_get, 602 .set = hw_break_set, 603 }, 604 #endif 605 }; 606 607 static const struct user_regset_view user_aarch64_view = { 608 .name = "aarch64", .e_machine = EM_AARCH64, 609 .regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets) 610 }; 611 612 #ifdef CONFIG_COMPAT 613 #include <linux/compat.h> 614 615 enum compat_regset { 616 REGSET_COMPAT_GPR, 617 REGSET_COMPAT_VFP, 618 }; 619 620 static int compat_gpr_get(struct task_struct *target, 621 const struct user_regset *regset, 622 unsigned int pos, unsigned int count, 623 void *kbuf, void __user *ubuf) 624 { 625 int ret = 0; 626 unsigned int i, start, num_regs; 627 628 /* Calculate the number of AArch32 registers contained in count */ 629 num_regs = count / regset->size; 630 631 /* Convert pos into an register number */ 632 start = pos / regset->size; 633 634 if (start + num_regs > regset->n) 635 return -EIO; 636 637 for (i = 0; i < num_regs; ++i) { 638 unsigned int idx = start + i; 639 compat_ulong_t reg; 640 641 switch (idx) { 642 case 15: 643 reg = task_pt_regs(target)->pc; 644 break; 645 case 16: 646 reg = task_pt_regs(target)->pstate; 647 break; 648 case 17: 649 reg = task_pt_regs(target)->orig_x0; 650 break; 651 default: 652 reg = task_pt_regs(target)->regs[idx]; 653 } 654 655 ret = copy_to_user(ubuf, ®, sizeof(reg)); 656 if (ret) 657 break; 658 659 ubuf += sizeof(reg); 660 } 661 662 return ret; 663 } 664 665 static int compat_gpr_set(struct task_struct *target, 666 const struct user_regset *regset, 667 unsigned int pos, unsigned int count, 668 const void *kbuf, const void __user *ubuf) 669 { 670 struct pt_regs newregs; 671 int ret = 0; 672 unsigned int i, start, num_regs; 673 674 /* Calculate the number of AArch32 registers contained in count */ 675 num_regs = count / regset->size; 676 677 /* Convert pos into an register number */ 678 start = pos / regset->size; 679 680 if (start + num_regs > regset->n) 681 return -EIO; 682 683 newregs = *task_pt_regs(target); 684 685 for (i = 0; i < num_regs; ++i) { 686 unsigned int idx = start + i; 687 compat_ulong_t reg; 688 689 ret = copy_from_user(®, ubuf, sizeof(reg)); 690 if (ret) 691 return ret; 692 693 ubuf += sizeof(reg); 694 695 switch (idx) { 696 case 15: 697 newregs.pc = reg; 698 break; 699 case 16: 700 newregs.pstate = reg; 701 break; 702 case 17: 703 newregs.orig_x0 = reg; 704 break; 705 default: 706 newregs.regs[idx] = reg; 707 } 708 709 } 710 711 if (valid_user_regs(&newregs.user_regs)) 712 *task_pt_regs(target) = newregs; 713 else 714 ret = -EINVAL; 715 716 return ret; 717 } 718 719 static int compat_vfp_get(struct task_struct *target, 720 const struct user_regset *regset, 721 unsigned int pos, unsigned int count, 722 void *kbuf, void __user *ubuf) 723 { 724 struct user_fpsimd_state *uregs; 725 compat_ulong_t fpscr; 726 int ret; 727 728 uregs = &target->thread.fpsimd_state.user_fpsimd; 729 730 /* 731 * The VFP registers are packed into the fpsimd_state, so they all sit 732 * nicely together for us. We just need to create the fpscr separately. 733 */ 734 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, 735 VFP_STATE_SIZE - sizeof(compat_ulong_t)); 736 737 if (count && !ret) { 738 fpscr = (uregs->fpsr & VFP_FPSCR_STAT_MASK) | 739 (uregs->fpcr & VFP_FPSCR_CTRL_MASK); 740 ret = put_user(fpscr, (compat_ulong_t *)ubuf); 741 } 742 743 return ret; 744 } 745 746 static int compat_vfp_set(struct task_struct *target, 747 const struct user_regset *regset, 748 unsigned int pos, unsigned int count, 749 const void *kbuf, const void __user *ubuf) 750 { 751 struct user_fpsimd_state *uregs; 752 compat_ulong_t fpscr; 753 int ret; 754 755 if (pos + count > VFP_STATE_SIZE) 756 return -EIO; 757 758 uregs = &target->thread.fpsimd_state.user_fpsimd; 759 760 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, 761 VFP_STATE_SIZE - sizeof(compat_ulong_t)); 762 763 if (count && !ret) { 764 ret = get_user(fpscr, (compat_ulong_t *)ubuf); 765 uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK; 766 uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK; 767 } 768 769 return ret; 770 } 771 772 static const struct user_regset aarch32_regsets[] = { 773 [REGSET_COMPAT_GPR] = { 774 .core_note_type = NT_PRSTATUS, 775 .n = COMPAT_ELF_NGREG, 776 .size = sizeof(compat_elf_greg_t), 777 .align = sizeof(compat_elf_greg_t), 778 .get = compat_gpr_get, 779 .set = compat_gpr_set 780 }, 781 [REGSET_COMPAT_VFP] = { 782 .core_note_type = NT_ARM_VFP, 783 .n = VFP_STATE_SIZE / sizeof(compat_ulong_t), 784 .size = sizeof(compat_ulong_t), 785 .align = sizeof(compat_ulong_t), 786 .get = compat_vfp_get, 787 .set = compat_vfp_set 788 }, 789 }; 790 791 static const struct user_regset_view user_aarch32_view = { 792 .name = "aarch32", .e_machine = EM_ARM, 793 .regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets) 794 }; 795 796 static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off, 797 compat_ulong_t __user *ret) 798 { 799 compat_ulong_t tmp; 800 801 if (off & 3) 802 return -EIO; 803 804 if (off == COMPAT_PT_TEXT_ADDR) 805 tmp = tsk->mm->start_code; 806 else if (off == COMPAT_PT_DATA_ADDR) 807 tmp = tsk->mm->start_data; 808 else if (off == COMPAT_PT_TEXT_END_ADDR) 809 tmp = tsk->mm->end_code; 810 else if (off < sizeof(compat_elf_gregset_t)) 811 return copy_regset_to_user(tsk, &user_aarch32_view, 812 REGSET_COMPAT_GPR, off, 813 sizeof(compat_ulong_t), ret); 814 else if (off >= COMPAT_USER_SZ) 815 return -EIO; 816 else 817 tmp = 0; 818 819 return put_user(tmp, ret); 820 } 821 822 static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off, 823 compat_ulong_t val) 824 { 825 int ret; 826 827 if (off & 3 || off >= COMPAT_USER_SZ) 828 return -EIO; 829 830 if (off >= sizeof(compat_elf_gregset_t)) 831 return 0; 832 833 ret = copy_regset_from_user(tsk, &user_aarch32_view, 834 REGSET_COMPAT_GPR, off, 835 sizeof(compat_ulong_t), 836 &val); 837 return ret; 838 } 839 840 #ifdef CONFIG_HAVE_HW_BREAKPOINT 841 842 /* 843 * Convert a virtual register number into an index for a thread_info 844 * breakpoint array. Breakpoints are identified using positive numbers 845 * whilst watchpoints are negative. The registers are laid out as pairs 846 * of (address, control), each pair mapping to a unique hw_breakpoint struct. 847 * Register 0 is reserved for describing resource information. 848 */ 849 static int compat_ptrace_hbp_num_to_idx(compat_long_t num) 850 { 851 return (abs(num) - 1) >> 1; 852 } 853 854 static int compat_ptrace_hbp_get_resource_info(u32 *kdata) 855 { 856 u8 num_brps, num_wrps, debug_arch, wp_len; 857 u32 reg = 0; 858 859 num_brps = hw_breakpoint_slots(TYPE_INST); 860 num_wrps = hw_breakpoint_slots(TYPE_DATA); 861 862 debug_arch = debug_monitors_arch(); 863 wp_len = 8; 864 reg |= debug_arch; 865 reg <<= 8; 866 reg |= wp_len; 867 reg <<= 8; 868 reg |= num_wrps; 869 reg <<= 8; 870 reg |= num_brps; 871 872 *kdata = reg; 873 return 0; 874 } 875 876 static int compat_ptrace_hbp_get(unsigned int note_type, 877 struct task_struct *tsk, 878 compat_long_t num, 879 u32 *kdata) 880 { 881 u64 addr = 0; 882 u32 ctrl = 0; 883 884 int err, idx = compat_ptrace_hbp_num_to_idx(num);; 885 886 if (num & 1) { 887 err = ptrace_hbp_get_addr(note_type, tsk, idx, &addr); 888 *kdata = (u32)addr; 889 } else { 890 err = ptrace_hbp_get_ctrl(note_type, tsk, idx, &ctrl); 891 *kdata = ctrl; 892 } 893 894 return err; 895 } 896 897 static int compat_ptrace_hbp_set(unsigned int note_type, 898 struct task_struct *tsk, 899 compat_long_t num, 900 u32 *kdata) 901 { 902 u64 addr; 903 u32 ctrl; 904 905 int err, idx = compat_ptrace_hbp_num_to_idx(num); 906 907 if (num & 1) { 908 addr = *kdata; 909 err = ptrace_hbp_set_addr(note_type, tsk, idx, addr); 910 } else { 911 ctrl = *kdata; 912 err = ptrace_hbp_set_ctrl(note_type, tsk, idx, ctrl); 913 } 914 915 return err; 916 } 917 918 static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num, 919 compat_ulong_t __user *data) 920 { 921 int ret; 922 u32 kdata; 923 mm_segment_t old_fs = get_fs(); 924 925 set_fs(KERNEL_DS); 926 /* Watchpoint */ 927 if (num < 0) { 928 ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata); 929 /* Resource info */ 930 } else if (num == 0) { 931 ret = compat_ptrace_hbp_get_resource_info(&kdata); 932 /* Breakpoint */ 933 } else { 934 ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata); 935 } 936 set_fs(old_fs); 937 938 if (!ret) 939 ret = put_user(kdata, data); 940 941 return ret; 942 } 943 944 static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num, 945 compat_ulong_t __user *data) 946 { 947 int ret; 948 u32 kdata = 0; 949 mm_segment_t old_fs = get_fs(); 950 951 if (num == 0) 952 return 0; 953 954 ret = get_user(kdata, data); 955 if (ret) 956 return ret; 957 958 set_fs(KERNEL_DS); 959 if (num < 0) 960 ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata); 961 else 962 ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata); 963 set_fs(old_fs); 964 965 return ret; 966 } 967 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 968 969 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 970 compat_ulong_t caddr, compat_ulong_t cdata) 971 { 972 unsigned long addr = caddr; 973 unsigned long data = cdata; 974 void __user *datap = compat_ptr(data); 975 int ret; 976 977 switch (request) { 978 case PTRACE_PEEKUSR: 979 ret = compat_ptrace_read_user(child, addr, datap); 980 break; 981 982 case PTRACE_POKEUSR: 983 ret = compat_ptrace_write_user(child, addr, data); 984 break; 985 986 case COMPAT_PTRACE_GETREGS: 987 ret = copy_regset_to_user(child, 988 &user_aarch32_view, 989 REGSET_COMPAT_GPR, 990 0, sizeof(compat_elf_gregset_t), 991 datap); 992 break; 993 994 case COMPAT_PTRACE_SETREGS: 995 ret = copy_regset_from_user(child, 996 &user_aarch32_view, 997 REGSET_COMPAT_GPR, 998 0, sizeof(compat_elf_gregset_t), 999 datap); 1000 break; 1001 1002 case COMPAT_PTRACE_GET_THREAD_AREA: 1003 ret = put_user((compat_ulong_t)child->thread.tp_value, 1004 (compat_ulong_t __user *)datap); 1005 break; 1006 1007 case COMPAT_PTRACE_SET_SYSCALL: 1008 task_pt_regs(child)->syscallno = data; 1009 ret = 0; 1010 break; 1011 1012 case COMPAT_PTRACE_GETVFPREGS: 1013 ret = copy_regset_to_user(child, 1014 &user_aarch32_view, 1015 REGSET_COMPAT_VFP, 1016 0, VFP_STATE_SIZE, 1017 datap); 1018 break; 1019 1020 case COMPAT_PTRACE_SETVFPREGS: 1021 ret = copy_regset_from_user(child, 1022 &user_aarch32_view, 1023 REGSET_COMPAT_VFP, 1024 0, VFP_STATE_SIZE, 1025 datap); 1026 break; 1027 1028 #ifdef CONFIG_HAVE_HW_BREAKPOINT 1029 case COMPAT_PTRACE_GETHBPREGS: 1030 ret = compat_ptrace_gethbpregs(child, addr, datap); 1031 break; 1032 1033 case COMPAT_PTRACE_SETHBPREGS: 1034 ret = compat_ptrace_sethbpregs(child, addr, datap); 1035 break; 1036 #endif 1037 1038 default: 1039 ret = compat_ptrace_request(child, request, addr, 1040 data); 1041 break; 1042 } 1043 1044 return ret; 1045 } 1046 #endif /* CONFIG_COMPAT */ 1047 1048 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 1049 { 1050 #ifdef CONFIG_COMPAT 1051 if (is_compat_thread(task_thread_info(task))) 1052 return &user_aarch32_view; 1053 #endif 1054 return &user_aarch64_view; 1055 } 1056 1057 long arch_ptrace(struct task_struct *child, long request, 1058 unsigned long addr, unsigned long data) 1059 { 1060 return ptrace_request(child, request, addr, data); 1061 } 1062 1063 asmlinkage int syscall_trace(int dir, struct pt_regs *regs) 1064 { 1065 unsigned long saved_reg; 1066 1067 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 1068 return regs->syscallno; 1069 1070 if (is_compat_task()) { 1071 /* AArch32 uses ip (r12) for scratch */ 1072 saved_reg = regs->regs[12]; 1073 regs->regs[12] = dir; 1074 } else { 1075 /* 1076 * Save X7. X7 is used to denote syscall entry/exit: 1077 * X7 = 0 -> entry, = 1 -> exit 1078 */ 1079 saved_reg = regs->regs[7]; 1080 regs->regs[7] = dir; 1081 } 1082 1083 if (dir) 1084 tracehook_report_syscall_exit(regs, 0); 1085 else if (tracehook_report_syscall_entry(regs)) 1086 regs->syscallno = ~0UL; 1087 1088 if (is_compat_task()) 1089 regs->regs[12] = saved_reg; 1090 else 1091 regs->regs[7] = saved_reg; 1092 1093 return regs->syscallno; 1094 } 1095