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 attr->disabled = disabled; 218 if (disabled) 219 return 0; 220 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 attr->bp_len = len; 239 attr->bp_type = type; 240 241 return 0; 242 } 243 244 static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info) 245 { 246 u8 num; 247 u32 reg = 0; 248 249 switch (note_type) { 250 case NT_ARM_HW_BREAK: 251 num = hw_breakpoint_slots(TYPE_INST); 252 break; 253 case NT_ARM_HW_WATCH: 254 num = hw_breakpoint_slots(TYPE_DATA); 255 break; 256 default: 257 return -EINVAL; 258 } 259 260 reg |= debug_monitors_arch(); 261 reg <<= 8; 262 reg |= num; 263 264 *info = reg; 265 return 0; 266 } 267 268 static int ptrace_hbp_get_ctrl(unsigned int note_type, 269 struct task_struct *tsk, 270 unsigned long idx, 271 u32 *ctrl) 272 { 273 struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); 274 275 if (IS_ERR(bp)) 276 return PTR_ERR(bp); 277 278 *ctrl = bp ? encode_ctrl_reg(counter_arch_bp(bp)->ctrl) : 0; 279 return 0; 280 } 281 282 static int ptrace_hbp_get_addr(unsigned int note_type, 283 struct task_struct *tsk, 284 unsigned long idx, 285 u64 *addr) 286 { 287 struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); 288 289 if (IS_ERR(bp)) 290 return PTR_ERR(bp); 291 292 *addr = bp ? bp->attr.bp_addr : 0; 293 return 0; 294 } 295 296 static struct perf_event *ptrace_hbp_get_initialised_bp(unsigned int note_type, 297 struct task_struct *tsk, 298 unsigned long idx) 299 { 300 struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); 301 302 if (!bp) 303 bp = ptrace_hbp_create(note_type, tsk, idx); 304 305 return bp; 306 } 307 308 static int ptrace_hbp_set_ctrl(unsigned int note_type, 309 struct task_struct *tsk, 310 unsigned long idx, 311 u32 uctrl) 312 { 313 int err; 314 struct perf_event *bp; 315 struct perf_event_attr attr; 316 struct arch_hw_breakpoint_ctrl ctrl; 317 318 bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); 319 if (IS_ERR(bp)) { 320 err = PTR_ERR(bp); 321 return err; 322 } 323 324 attr = bp->attr; 325 decode_ctrl_reg(uctrl, &ctrl); 326 err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr); 327 if (err) 328 return err; 329 330 return modify_user_hw_breakpoint(bp, &attr); 331 } 332 333 static int ptrace_hbp_set_addr(unsigned int note_type, 334 struct task_struct *tsk, 335 unsigned long idx, 336 u64 addr) 337 { 338 int err; 339 struct perf_event *bp; 340 struct perf_event_attr attr; 341 342 bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); 343 if (IS_ERR(bp)) { 344 err = PTR_ERR(bp); 345 return err; 346 } 347 348 attr = bp->attr; 349 attr.bp_addr = addr; 350 err = modify_user_hw_breakpoint(bp, &attr); 351 return err; 352 } 353 354 #define PTRACE_HBP_ADDR_SZ sizeof(u64) 355 #define PTRACE_HBP_CTRL_SZ sizeof(u32) 356 #define PTRACE_HBP_PAD_SZ sizeof(u32) 357 358 static int hw_break_get(struct task_struct *target, 359 const struct user_regset *regset, 360 unsigned int pos, unsigned int count, 361 void *kbuf, void __user *ubuf) 362 { 363 unsigned int note_type = regset->core_note_type; 364 int ret, idx = 0, offset, limit; 365 u32 info, ctrl; 366 u64 addr; 367 368 /* Resource info */ 369 ret = ptrace_hbp_get_resource_info(note_type, &info); 370 if (ret) 371 return ret; 372 373 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0, 374 sizeof(info)); 375 if (ret) 376 return ret; 377 378 /* Pad */ 379 offset = offsetof(struct user_hwdebug_state, pad); 380 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, offset, 381 offset + PTRACE_HBP_PAD_SZ); 382 if (ret) 383 return ret; 384 385 /* (address, ctrl) registers */ 386 offset = offsetof(struct user_hwdebug_state, dbg_regs); 387 limit = regset->n * regset->size; 388 while (count && offset < limit) { 389 ret = ptrace_hbp_get_addr(note_type, target, idx, &addr); 390 if (ret) 391 return ret; 392 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &addr, 393 offset, offset + PTRACE_HBP_ADDR_SZ); 394 if (ret) 395 return ret; 396 offset += PTRACE_HBP_ADDR_SZ; 397 398 ret = ptrace_hbp_get_ctrl(note_type, target, idx, &ctrl); 399 if (ret) 400 return ret; 401 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &ctrl, 402 offset, offset + PTRACE_HBP_CTRL_SZ); 403 if (ret) 404 return ret; 405 offset += PTRACE_HBP_CTRL_SZ; 406 407 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 408 offset, 409 offset + PTRACE_HBP_PAD_SZ); 410 if (ret) 411 return ret; 412 offset += PTRACE_HBP_PAD_SZ; 413 idx++; 414 } 415 416 return 0; 417 } 418 419 static int hw_break_set(struct task_struct *target, 420 const struct user_regset *regset, 421 unsigned int pos, unsigned int count, 422 const void *kbuf, const void __user *ubuf) 423 { 424 unsigned int note_type = regset->core_note_type; 425 int ret, idx = 0, offset, limit; 426 u32 ctrl; 427 u64 addr; 428 429 /* Resource info and pad */ 430 offset = offsetof(struct user_hwdebug_state, dbg_regs); 431 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset); 432 if (ret) 433 return ret; 434 435 /* (address, ctrl) registers */ 436 limit = regset->n * regset->size; 437 while (count && offset < limit) { 438 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr, 439 offset, offset + PTRACE_HBP_ADDR_SZ); 440 if (ret) 441 return ret; 442 ret = ptrace_hbp_set_addr(note_type, target, idx, addr); 443 if (ret) 444 return ret; 445 offset += PTRACE_HBP_ADDR_SZ; 446 447 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, 448 offset, offset + PTRACE_HBP_CTRL_SZ); 449 if (ret) 450 return ret; 451 ret = ptrace_hbp_set_ctrl(note_type, target, idx, ctrl); 452 if (ret) 453 return ret; 454 offset += PTRACE_HBP_CTRL_SZ; 455 456 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 457 offset, 458 offset + PTRACE_HBP_PAD_SZ); 459 if (ret) 460 return ret; 461 offset += PTRACE_HBP_PAD_SZ; 462 idx++; 463 } 464 465 return 0; 466 } 467 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 468 469 static int gpr_get(struct task_struct *target, 470 const struct user_regset *regset, 471 unsigned int pos, unsigned int count, 472 void *kbuf, void __user *ubuf) 473 { 474 struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs; 475 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); 476 } 477 478 static int gpr_set(struct task_struct *target, const struct user_regset *regset, 479 unsigned int pos, unsigned int count, 480 const void *kbuf, const void __user *ubuf) 481 { 482 int ret; 483 struct user_pt_regs newregs; 484 485 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1); 486 if (ret) 487 return ret; 488 489 if (!valid_user_regs(&newregs)) 490 return -EINVAL; 491 492 task_pt_regs(target)->user_regs = newregs; 493 return 0; 494 } 495 496 /* 497 * TODO: update fp accessors for lazy context switching (sync/flush hwstate) 498 */ 499 static int fpr_get(struct task_struct *target, const struct user_regset *regset, 500 unsigned int pos, unsigned int count, 501 void *kbuf, void __user *ubuf) 502 { 503 struct user_fpsimd_state *uregs; 504 uregs = &target->thread.fpsimd_state.user_fpsimd; 505 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); 506 } 507 508 static int fpr_set(struct task_struct *target, const struct user_regset *regset, 509 unsigned int pos, unsigned int count, 510 const void *kbuf, const void __user *ubuf) 511 { 512 int ret; 513 struct user_fpsimd_state newstate; 514 515 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1); 516 if (ret) 517 return ret; 518 519 target->thread.fpsimd_state.user_fpsimd = newstate; 520 return ret; 521 } 522 523 static int tls_get(struct task_struct *target, const struct user_regset *regset, 524 unsigned int pos, unsigned int count, 525 void *kbuf, void __user *ubuf) 526 { 527 unsigned long *tls = &target->thread.tp_value; 528 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, tls, 0, -1); 529 } 530 531 static int tls_set(struct task_struct *target, const struct user_regset *regset, 532 unsigned int pos, unsigned int count, 533 const void *kbuf, const void __user *ubuf) 534 { 535 int ret; 536 unsigned long tls; 537 538 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); 539 if (ret) 540 return ret; 541 542 target->thread.tp_value = tls; 543 return ret; 544 } 545 546 enum aarch64_regset { 547 REGSET_GPR, 548 REGSET_FPR, 549 REGSET_TLS, 550 #ifdef CONFIG_HAVE_HW_BREAKPOINT 551 REGSET_HW_BREAK, 552 REGSET_HW_WATCH, 553 #endif 554 }; 555 556 static const struct user_regset aarch64_regsets[] = { 557 [REGSET_GPR] = { 558 .core_note_type = NT_PRSTATUS, 559 .n = sizeof(struct user_pt_regs) / sizeof(u64), 560 .size = sizeof(u64), 561 .align = sizeof(u64), 562 .get = gpr_get, 563 .set = gpr_set 564 }, 565 [REGSET_FPR] = { 566 .core_note_type = NT_PRFPREG, 567 .n = sizeof(struct user_fpsimd_state) / sizeof(u32), 568 /* 569 * We pretend we have 32-bit registers because the fpsr and 570 * fpcr are 32-bits wide. 571 */ 572 .size = sizeof(u32), 573 .align = sizeof(u32), 574 .get = fpr_get, 575 .set = fpr_set 576 }, 577 [REGSET_TLS] = { 578 .core_note_type = NT_ARM_TLS, 579 .n = 1, 580 .size = sizeof(void *), 581 .align = sizeof(void *), 582 .get = tls_get, 583 .set = tls_set, 584 }, 585 #ifdef CONFIG_HAVE_HW_BREAKPOINT 586 [REGSET_HW_BREAK] = { 587 .core_note_type = NT_ARM_HW_BREAK, 588 .n = sizeof(struct user_hwdebug_state) / sizeof(u32), 589 .size = sizeof(u32), 590 .align = sizeof(u32), 591 .get = hw_break_get, 592 .set = hw_break_set, 593 }, 594 [REGSET_HW_WATCH] = { 595 .core_note_type = NT_ARM_HW_WATCH, 596 .n = sizeof(struct user_hwdebug_state) / sizeof(u32), 597 .size = sizeof(u32), 598 .align = sizeof(u32), 599 .get = hw_break_get, 600 .set = hw_break_set, 601 }, 602 #endif 603 }; 604 605 static const struct user_regset_view user_aarch64_view = { 606 .name = "aarch64", .e_machine = EM_AARCH64, 607 .regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets) 608 }; 609 610 #ifdef CONFIG_COMPAT 611 #include <linux/compat.h> 612 613 enum compat_regset { 614 REGSET_COMPAT_GPR, 615 REGSET_COMPAT_VFP, 616 }; 617 618 static int compat_gpr_get(struct task_struct *target, 619 const struct user_regset *regset, 620 unsigned int pos, unsigned int count, 621 void *kbuf, void __user *ubuf) 622 { 623 int ret = 0; 624 unsigned int i, start, num_regs; 625 626 /* Calculate the number of AArch32 registers contained in count */ 627 num_regs = count / regset->size; 628 629 /* Convert pos into an register number */ 630 start = pos / regset->size; 631 632 if (start + num_regs > regset->n) 633 return -EIO; 634 635 for (i = 0; i < num_regs; ++i) { 636 unsigned int idx = start + i; 637 compat_ulong_t reg; 638 639 switch (idx) { 640 case 15: 641 reg = task_pt_regs(target)->pc; 642 break; 643 case 16: 644 reg = task_pt_regs(target)->pstate; 645 break; 646 case 17: 647 reg = task_pt_regs(target)->orig_x0; 648 break; 649 default: 650 reg = task_pt_regs(target)->regs[idx]; 651 } 652 653 ret = copy_to_user(ubuf, ®, sizeof(reg)); 654 if (ret) 655 break; 656 657 ubuf += sizeof(reg); 658 } 659 660 return ret; 661 } 662 663 static int compat_gpr_set(struct task_struct *target, 664 const struct user_regset *regset, 665 unsigned int pos, unsigned int count, 666 const void *kbuf, const void __user *ubuf) 667 { 668 struct pt_regs newregs; 669 int ret = 0; 670 unsigned int i, start, num_regs; 671 672 /* Calculate the number of AArch32 registers contained in count */ 673 num_regs = count / regset->size; 674 675 /* Convert pos into an register number */ 676 start = pos / regset->size; 677 678 if (start + num_regs > regset->n) 679 return -EIO; 680 681 newregs = *task_pt_regs(target); 682 683 for (i = 0; i < num_regs; ++i) { 684 unsigned int idx = start + i; 685 compat_ulong_t reg; 686 687 ret = copy_from_user(®, ubuf, sizeof(reg)); 688 if (ret) 689 return ret; 690 691 ubuf += sizeof(reg); 692 693 switch (idx) { 694 case 15: 695 newregs.pc = reg; 696 break; 697 case 16: 698 newregs.pstate = reg; 699 break; 700 case 17: 701 newregs.orig_x0 = reg; 702 break; 703 default: 704 newregs.regs[idx] = reg; 705 } 706 707 } 708 709 if (valid_user_regs(&newregs.user_regs)) 710 *task_pt_regs(target) = newregs; 711 else 712 ret = -EINVAL; 713 714 return ret; 715 } 716 717 static int compat_vfp_get(struct task_struct *target, 718 const struct user_regset *regset, 719 unsigned int pos, unsigned int count, 720 void *kbuf, void __user *ubuf) 721 { 722 struct user_fpsimd_state *uregs; 723 compat_ulong_t fpscr; 724 int ret; 725 726 uregs = &target->thread.fpsimd_state.user_fpsimd; 727 728 /* 729 * The VFP registers are packed into the fpsimd_state, so they all sit 730 * nicely together for us. We just need to create the fpscr separately. 731 */ 732 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, 733 VFP_STATE_SIZE - sizeof(compat_ulong_t)); 734 735 if (count && !ret) { 736 fpscr = (uregs->fpsr & VFP_FPSCR_STAT_MASK) | 737 (uregs->fpcr & VFP_FPSCR_CTRL_MASK); 738 ret = put_user(fpscr, (compat_ulong_t *)ubuf); 739 } 740 741 return ret; 742 } 743 744 static int compat_vfp_set(struct task_struct *target, 745 const struct user_regset *regset, 746 unsigned int pos, unsigned int count, 747 const void *kbuf, const void __user *ubuf) 748 { 749 struct user_fpsimd_state *uregs; 750 compat_ulong_t fpscr; 751 int ret; 752 753 if (pos + count > VFP_STATE_SIZE) 754 return -EIO; 755 756 uregs = &target->thread.fpsimd_state.user_fpsimd; 757 758 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, 759 VFP_STATE_SIZE - sizeof(compat_ulong_t)); 760 761 if (count && !ret) { 762 ret = get_user(fpscr, (compat_ulong_t *)ubuf); 763 uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK; 764 uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK; 765 } 766 767 return ret; 768 } 769 770 static const struct user_regset aarch32_regsets[] = { 771 [REGSET_COMPAT_GPR] = { 772 .core_note_type = NT_PRSTATUS, 773 .n = COMPAT_ELF_NGREG, 774 .size = sizeof(compat_elf_greg_t), 775 .align = sizeof(compat_elf_greg_t), 776 .get = compat_gpr_get, 777 .set = compat_gpr_set 778 }, 779 [REGSET_COMPAT_VFP] = { 780 .core_note_type = NT_ARM_VFP, 781 .n = VFP_STATE_SIZE / sizeof(compat_ulong_t), 782 .size = sizeof(compat_ulong_t), 783 .align = sizeof(compat_ulong_t), 784 .get = compat_vfp_get, 785 .set = compat_vfp_set 786 }, 787 }; 788 789 static const struct user_regset_view user_aarch32_view = { 790 .name = "aarch32", .e_machine = EM_ARM, 791 .regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets) 792 }; 793 794 static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off, 795 compat_ulong_t __user *ret) 796 { 797 compat_ulong_t tmp; 798 799 if (off & 3) 800 return -EIO; 801 802 if (off == COMPAT_PT_TEXT_ADDR) 803 tmp = tsk->mm->start_code; 804 else if (off == COMPAT_PT_DATA_ADDR) 805 tmp = tsk->mm->start_data; 806 else if (off == COMPAT_PT_TEXT_END_ADDR) 807 tmp = tsk->mm->end_code; 808 else if (off < sizeof(compat_elf_gregset_t)) 809 return copy_regset_to_user(tsk, &user_aarch32_view, 810 REGSET_COMPAT_GPR, off, 811 sizeof(compat_ulong_t), ret); 812 else if (off >= COMPAT_USER_SZ) 813 return -EIO; 814 else 815 tmp = 0; 816 817 return put_user(tmp, ret); 818 } 819 820 static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off, 821 compat_ulong_t val) 822 { 823 int ret; 824 825 if (off & 3 || off >= COMPAT_USER_SZ) 826 return -EIO; 827 828 if (off >= sizeof(compat_elf_gregset_t)) 829 return 0; 830 831 ret = copy_regset_from_user(tsk, &user_aarch32_view, 832 REGSET_COMPAT_GPR, off, 833 sizeof(compat_ulong_t), 834 &val); 835 return ret; 836 } 837 838 #ifdef CONFIG_HAVE_HW_BREAKPOINT 839 840 /* 841 * Convert a virtual register number into an index for a thread_info 842 * breakpoint array. Breakpoints are identified using positive numbers 843 * whilst watchpoints are negative. The registers are laid out as pairs 844 * of (address, control), each pair mapping to a unique hw_breakpoint struct. 845 * Register 0 is reserved for describing resource information. 846 */ 847 static int compat_ptrace_hbp_num_to_idx(compat_long_t num) 848 { 849 return (abs(num) - 1) >> 1; 850 } 851 852 static int compat_ptrace_hbp_get_resource_info(u32 *kdata) 853 { 854 u8 num_brps, num_wrps, debug_arch, wp_len; 855 u32 reg = 0; 856 857 num_brps = hw_breakpoint_slots(TYPE_INST); 858 num_wrps = hw_breakpoint_slots(TYPE_DATA); 859 860 debug_arch = debug_monitors_arch(); 861 wp_len = 8; 862 reg |= debug_arch; 863 reg <<= 8; 864 reg |= wp_len; 865 reg <<= 8; 866 reg |= num_wrps; 867 reg <<= 8; 868 reg |= num_brps; 869 870 *kdata = reg; 871 return 0; 872 } 873 874 static int compat_ptrace_hbp_get(unsigned int note_type, 875 struct task_struct *tsk, 876 compat_long_t num, 877 u32 *kdata) 878 { 879 u64 addr = 0; 880 u32 ctrl = 0; 881 882 int err, idx = compat_ptrace_hbp_num_to_idx(num);; 883 884 if (num & 1) { 885 err = ptrace_hbp_get_addr(note_type, tsk, idx, &addr); 886 *kdata = (u32)addr; 887 } else { 888 err = ptrace_hbp_get_ctrl(note_type, tsk, idx, &ctrl); 889 *kdata = ctrl; 890 } 891 892 return err; 893 } 894 895 static int compat_ptrace_hbp_set(unsigned int note_type, 896 struct task_struct *tsk, 897 compat_long_t num, 898 u32 *kdata) 899 { 900 u64 addr; 901 u32 ctrl; 902 903 int err, idx = compat_ptrace_hbp_num_to_idx(num); 904 905 if (num & 1) { 906 addr = *kdata; 907 err = ptrace_hbp_set_addr(note_type, tsk, idx, addr); 908 } else { 909 ctrl = *kdata; 910 err = ptrace_hbp_set_ctrl(note_type, tsk, idx, ctrl); 911 } 912 913 return err; 914 } 915 916 static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num, 917 compat_ulong_t __user *data) 918 { 919 int ret; 920 u32 kdata; 921 mm_segment_t old_fs = get_fs(); 922 923 set_fs(KERNEL_DS); 924 /* Watchpoint */ 925 if (num < 0) { 926 ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata); 927 /* Resource info */ 928 } else if (num == 0) { 929 ret = compat_ptrace_hbp_get_resource_info(&kdata); 930 /* Breakpoint */ 931 } else { 932 ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata); 933 } 934 set_fs(old_fs); 935 936 if (!ret) 937 ret = put_user(kdata, data); 938 939 return ret; 940 } 941 942 static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num, 943 compat_ulong_t __user *data) 944 { 945 int ret; 946 u32 kdata = 0; 947 mm_segment_t old_fs = get_fs(); 948 949 if (num == 0) 950 return 0; 951 952 ret = get_user(kdata, data); 953 if (ret) 954 return ret; 955 956 set_fs(KERNEL_DS); 957 if (num < 0) 958 ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata); 959 else 960 ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata); 961 set_fs(old_fs); 962 963 return ret; 964 } 965 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 966 967 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 968 compat_ulong_t caddr, compat_ulong_t cdata) 969 { 970 unsigned long addr = caddr; 971 unsigned long data = cdata; 972 void __user *datap = compat_ptr(data); 973 int ret; 974 975 switch (request) { 976 case PTRACE_PEEKUSR: 977 ret = compat_ptrace_read_user(child, addr, datap); 978 break; 979 980 case PTRACE_POKEUSR: 981 ret = compat_ptrace_write_user(child, addr, data); 982 break; 983 984 case COMPAT_PTRACE_GETREGS: 985 ret = copy_regset_to_user(child, 986 &user_aarch32_view, 987 REGSET_COMPAT_GPR, 988 0, sizeof(compat_elf_gregset_t), 989 datap); 990 break; 991 992 case COMPAT_PTRACE_SETREGS: 993 ret = copy_regset_from_user(child, 994 &user_aarch32_view, 995 REGSET_COMPAT_GPR, 996 0, sizeof(compat_elf_gregset_t), 997 datap); 998 break; 999 1000 case COMPAT_PTRACE_GET_THREAD_AREA: 1001 ret = put_user((compat_ulong_t)child->thread.tp_value, 1002 (compat_ulong_t __user *)datap); 1003 break; 1004 1005 case COMPAT_PTRACE_SET_SYSCALL: 1006 task_pt_regs(child)->syscallno = data; 1007 ret = 0; 1008 break; 1009 1010 case COMPAT_PTRACE_GETVFPREGS: 1011 ret = copy_regset_to_user(child, 1012 &user_aarch32_view, 1013 REGSET_COMPAT_VFP, 1014 0, VFP_STATE_SIZE, 1015 datap); 1016 break; 1017 1018 case COMPAT_PTRACE_SETVFPREGS: 1019 ret = copy_regset_from_user(child, 1020 &user_aarch32_view, 1021 REGSET_COMPAT_VFP, 1022 0, VFP_STATE_SIZE, 1023 datap); 1024 break; 1025 1026 #ifdef CONFIG_HAVE_HW_BREAKPOINT 1027 case COMPAT_PTRACE_GETHBPREGS: 1028 ret = compat_ptrace_gethbpregs(child, addr, datap); 1029 break; 1030 1031 case COMPAT_PTRACE_SETHBPREGS: 1032 ret = compat_ptrace_sethbpregs(child, addr, datap); 1033 break; 1034 #endif 1035 1036 default: 1037 ret = compat_ptrace_request(child, request, addr, 1038 data); 1039 break; 1040 } 1041 1042 return ret; 1043 } 1044 #endif /* CONFIG_COMPAT */ 1045 1046 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 1047 { 1048 #ifdef CONFIG_COMPAT 1049 if (is_compat_thread(task_thread_info(task))) 1050 return &user_aarch32_view; 1051 #endif 1052 return &user_aarch64_view; 1053 } 1054 1055 long arch_ptrace(struct task_struct *child, long request, 1056 unsigned long addr, unsigned long data) 1057 { 1058 return ptrace_request(child, request, addr, data); 1059 } 1060 1061 asmlinkage int syscall_trace(int dir, struct pt_regs *regs) 1062 { 1063 unsigned long saved_reg; 1064 1065 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 1066 return regs->syscallno; 1067 1068 if (is_compat_task()) { 1069 /* AArch32 uses ip (r12) for scratch */ 1070 saved_reg = regs->regs[12]; 1071 regs->regs[12] = dir; 1072 } else { 1073 /* 1074 * Save X7. X7 is used to denote syscall entry/exit: 1075 * X7 = 0 -> entry, = 1 -> exit 1076 */ 1077 saved_reg = regs->regs[7]; 1078 regs->regs[7] = dir; 1079 } 1080 1081 if (dir) 1082 tracehook_report_syscall_exit(regs, 0); 1083 else if (tracehook_report_syscall_entry(regs)) 1084 regs->syscallno = ~0UL; 1085 1086 if (is_compat_task()) 1087 regs->regs[12] = saved_reg; 1088 else 1089 regs->regs[7] = saved_reg; 1090 1091 return regs->syscallno; 1092 } 1093