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 void *reg; 640 641 switch (idx) { 642 case 15: 643 reg = (void *)&task_pt_regs(target)->pc; 644 break; 645 case 16: 646 reg = (void *)&task_pt_regs(target)->pstate; 647 break; 648 case 17: 649 reg = (void *)&task_pt_regs(target)->orig_x0; 650 break; 651 default: 652 reg = (void *)&task_pt_regs(target)->regs[idx]; 653 } 654 655 ret = copy_to_user(ubuf, reg, sizeof(compat_ulong_t)); 656 657 if (ret) 658 break; 659 else 660 ubuf += sizeof(compat_ulong_t); 661 } 662 663 return ret; 664 } 665 666 static int compat_gpr_set(struct task_struct *target, 667 const struct user_regset *regset, 668 unsigned int pos, unsigned int count, 669 const void *kbuf, const void __user *ubuf) 670 { 671 struct pt_regs newregs; 672 int ret = 0; 673 unsigned int i, start, num_regs; 674 675 /* Calculate the number of AArch32 registers contained in count */ 676 num_regs = count / regset->size; 677 678 /* Convert pos into an register number */ 679 start = pos / regset->size; 680 681 if (start + num_regs > regset->n) 682 return -EIO; 683 684 newregs = *task_pt_regs(target); 685 686 for (i = 0; i < num_regs; ++i) { 687 unsigned int idx = start + i; 688 void *reg; 689 690 switch (idx) { 691 case 15: 692 reg = (void *)&newregs.pc; 693 break; 694 case 16: 695 reg = (void *)&newregs.pstate; 696 break; 697 case 17: 698 reg = (void *)&newregs.orig_x0; 699 break; 700 default: 701 reg = (void *)&newregs.regs[idx]; 702 } 703 704 ret = copy_from_user(reg, ubuf, sizeof(compat_ulong_t)); 705 706 if (ret) 707 goto out; 708 else 709 ubuf += sizeof(compat_ulong_t); 710 } 711 712 if (valid_user_regs(&newregs.user_regs)) 713 *task_pt_regs(target) = newregs; 714 else 715 ret = -EINVAL; 716 717 out: 718 return ret; 719 } 720 721 static int compat_vfp_get(struct task_struct *target, 722 const struct user_regset *regset, 723 unsigned int pos, unsigned int count, 724 void *kbuf, void __user *ubuf) 725 { 726 struct user_fpsimd_state *uregs; 727 compat_ulong_t fpscr; 728 int ret; 729 730 uregs = &target->thread.fpsimd_state.user_fpsimd; 731 732 /* 733 * The VFP registers are packed into the fpsimd_state, so they all sit 734 * nicely together for us. We just need to create the fpscr separately. 735 */ 736 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, 737 VFP_STATE_SIZE - sizeof(compat_ulong_t)); 738 739 if (count && !ret) { 740 fpscr = (uregs->fpsr & VFP_FPSCR_STAT_MASK) | 741 (uregs->fpcr & VFP_FPSCR_CTRL_MASK); 742 ret = put_user(fpscr, (compat_ulong_t *)ubuf); 743 } 744 745 return ret; 746 } 747 748 static int compat_vfp_set(struct task_struct *target, 749 const struct user_regset *regset, 750 unsigned int pos, unsigned int count, 751 const void *kbuf, const void __user *ubuf) 752 { 753 struct user_fpsimd_state *uregs; 754 compat_ulong_t fpscr; 755 int ret; 756 757 if (pos + count > VFP_STATE_SIZE) 758 return -EIO; 759 760 uregs = &target->thread.fpsimd_state.user_fpsimd; 761 762 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, 763 VFP_STATE_SIZE - sizeof(compat_ulong_t)); 764 765 if (count && !ret) { 766 ret = get_user(fpscr, (compat_ulong_t *)ubuf); 767 uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK; 768 uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK; 769 } 770 771 return ret; 772 } 773 774 static const struct user_regset aarch32_regsets[] = { 775 [REGSET_COMPAT_GPR] = { 776 .core_note_type = NT_PRSTATUS, 777 .n = COMPAT_ELF_NGREG, 778 .size = sizeof(compat_elf_greg_t), 779 .align = sizeof(compat_elf_greg_t), 780 .get = compat_gpr_get, 781 .set = compat_gpr_set 782 }, 783 [REGSET_COMPAT_VFP] = { 784 .core_note_type = NT_ARM_VFP, 785 .n = VFP_STATE_SIZE / sizeof(compat_ulong_t), 786 .size = sizeof(compat_ulong_t), 787 .align = sizeof(compat_ulong_t), 788 .get = compat_vfp_get, 789 .set = compat_vfp_set 790 }, 791 }; 792 793 static const struct user_regset_view user_aarch32_view = { 794 .name = "aarch32", .e_machine = EM_ARM, 795 .regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets) 796 }; 797 798 static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off, 799 compat_ulong_t __user *ret) 800 { 801 compat_ulong_t tmp; 802 803 if (off & 3) 804 return -EIO; 805 806 if (off == COMPAT_PT_TEXT_ADDR) 807 tmp = tsk->mm->start_code; 808 else if (off == COMPAT_PT_DATA_ADDR) 809 tmp = tsk->mm->start_data; 810 else if (off == COMPAT_PT_TEXT_END_ADDR) 811 tmp = tsk->mm->end_code; 812 else if (off < sizeof(compat_elf_gregset_t)) 813 return copy_regset_to_user(tsk, &user_aarch32_view, 814 REGSET_COMPAT_GPR, off, 815 sizeof(compat_ulong_t), ret); 816 else if (off >= COMPAT_USER_SZ) 817 return -EIO; 818 else 819 tmp = 0; 820 821 return put_user(tmp, ret); 822 } 823 824 static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off, 825 compat_ulong_t val) 826 { 827 int ret; 828 829 if (off & 3 || off >= COMPAT_USER_SZ) 830 return -EIO; 831 832 if (off >= sizeof(compat_elf_gregset_t)) 833 return 0; 834 835 ret = copy_regset_from_user(tsk, &user_aarch32_view, 836 REGSET_COMPAT_GPR, off, 837 sizeof(compat_ulong_t), 838 &val); 839 return ret; 840 } 841 842 #ifdef CONFIG_HAVE_HW_BREAKPOINT 843 844 /* 845 * Convert a virtual register number into an index for a thread_info 846 * breakpoint array. Breakpoints are identified using positive numbers 847 * whilst watchpoints are negative. The registers are laid out as pairs 848 * of (address, control), each pair mapping to a unique hw_breakpoint struct. 849 * Register 0 is reserved for describing resource information. 850 */ 851 static int compat_ptrace_hbp_num_to_idx(compat_long_t num) 852 { 853 return (abs(num) - 1) >> 1; 854 } 855 856 static int compat_ptrace_hbp_get_resource_info(u32 *kdata) 857 { 858 u8 num_brps, num_wrps, debug_arch, wp_len; 859 u32 reg = 0; 860 861 num_brps = hw_breakpoint_slots(TYPE_INST); 862 num_wrps = hw_breakpoint_slots(TYPE_DATA); 863 864 debug_arch = debug_monitors_arch(); 865 wp_len = 8; 866 reg |= debug_arch; 867 reg <<= 8; 868 reg |= wp_len; 869 reg <<= 8; 870 reg |= num_wrps; 871 reg <<= 8; 872 reg |= num_brps; 873 874 *kdata = reg; 875 return 0; 876 } 877 878 static int compat_ptrace_hbp_get(unsigned int note_type, 879 struct task_struct *tsk, 880 compat_long_t num, 881 u32 *kdata) 882 { 883 u64 addr = 0; 884 u32 ctrl = 0; 885 886 int err, idx = compat_ptrace_hbp_num_to_idx(num);; 887 888 if (num & 1) { 889 err = ptrace_hbp_get_addr(note_type, tsk, idx, &addr); 890 *kdata = (u32)addr; 891 } else { 892 err = ptrace_hbp_get_ctrl(note_type, tsk, idx, &ctrl); 893 *kdata = ctrl; 894 } 895 896 return err; 897 } 898 899 static int compat_ptrace_hbp_set(unsigned int note_type, 900 struct task_struct *tsk, 901 compat_long_t num, 902 u32 *kdata) 903 { 904 u64 addr; 905 u32 ctrl; 906 907 int err, idx = compat_ptrace_hbp_num_to_idx(num); 908 909 if (num & 1) { 910 addr = *kdata; 911 err = ptrace_hbp_set_addr(note_type, tsk, idx, addr); 912 } else { 913 ctrl = *kdata; 914 err = ptrace_hbp_set_ctrl(note_type, tsk, idx, ctrl); 915 } 916 917 return err; 918 } 919 920 static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num, 921 compat_ulong_t __user *data) 922 { 923 int ret; 924 u32 kdata; 925 mm_segment_t old_fs = get_fs(); 926 927 set_fs(KERNEL_DS); 928 /* Watchpoint */ 929 if (num < 0) { 930 ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata); 931 /* Resource info */ 932 } else if (num == 0) { 933 ret = compat_ptrace_hbp_get_resource_info(&kdata); 934 /* Breakpoint */ 935 } else { 936 ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata); 937 } 938 set_fs(old_fs); 939 940 if (!ret) 941 ret = put_user(kdata, data); 942 943 return ret; 944 } 945 946 static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num, 947 compat_ulong_t __user *data) 948 { 949 int ret; 950 u32 kdata = 0; 951 mm_segment_t old_fs = get_fs(); 952 953 if (num == 0) 954 return 0; 955 956 ret = get_user(kdata, data); 957 if (ret) 958 return ret; 959 960 set_fs(KERNEL_DS); 961 if (num < 0) 962 ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata); 963 else 964 ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata); 965 set_fs(old_fs); 966 967 return ret; 968 } 969 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 970 971 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 972 compat_ulong_t caddr, compat_ulong_t cdata) 973 { 974 unsigned long addr = caddr; 975 unsigned long data = cdata; 976 void __user *datap = compat_ptr(data); 977 int ret; 978 979 switch (request) { 980 case PTRACE_PEEKUSR: 981 ret = compat_ptrace_read_user(child, addr, datap); 982 break; 983 984 case PTRACE_POKEUSR: 985 ret = compat_ptrace_write_user(child, addr, data); 986 break; 987 988 case COMPAT_PTRACE_GETREGS: 989 ret = copy_regset_to_user(child, 990 &user_aarch32_view, 991 REGSET_COMPAT_GPR, 992 0, sizeof(compat_elf_gregset_t), 993 datap); 994 break; 995 996 case COMPAT_PTRACE_SETREGS: 997 ret = copy_regset_from_user(child, 998 &user_aarch32_view, 999 REGSET_COMPAT_GPR, 1000 0, sizeof(compat_elf_gregset_t), 1001 datap); 1002 break; 1003 1004 case COMPAT_PTRACE_GET_THREAD_AREA: 1005 ret = put_user((compat_ulong_t)child->thread.tp_value, 1006 (compat_ulong_t __user *)datap); 1007 break; 1008 1009 case COMPAT_PTRACE_SET_SYSCALL: 1010 task_pt_regs(child)->syscallno = data; 1011 ret = 0; 1012 break; 1013 1014 case COMPAT_PTRACE_GETVFPREGS: 1015 ret = copy_regset_to_user(child, 1016 &user_aarch32_view, 1017 REGSET_COMPAT_VFP, 1018 0, VFP_STATE_SIZE, 1019 datap); 1020 break; 1021 1022 case COMPAT_PTRACE_SETVFPREGS: 1023 ret = copy_regset_from_user(child, 1024 &user_aarch32_view, 1025 REGSET_COMPAT_VFP, 1026 0, VFP_STATE_SIZE, 1027 datap); 1028 break; 1029 1030 #ifdef CONFIG_HAVE_HW_BREAKPOINT 1031 case COMPAT_PTRACE_GETHBPREGS: 1032 ret = compat_ptrace_gethbpregs(child, addr, datap); 1033 break; 1034 1035 case COMPAT_PTRACE_SETHBPREGS: 1036 ret = compat_ptrace_sethbpregs(child, addr, datap); 1037 break; 1038 #endif 1039 1040 default: 1041 ret = compat_ptrace_request(child, request, addr, 1042 data); 1043 break; 1044 } 1045 1046 return ret; 1047 } 1048 #endif /* CONFIG_COMPAT */ 1049 1050 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 1051 { 1052 #ifdef CONFIG_COMPAT 1053 if (is_compat_thread(task_thread_info(task))) 1054 return &user_aarch32_view; 1055 #endif 1056 return &user_aarch64_view; 1057 } 1058 1059 long arch_ptrace(struct task_struct *child, long request, 1060 unsigned long addr, unsigned long data) 1061 { 1062 return ptrace_request(child, request, addr, data); 1063 } 1064 1065 asmlinkage int syscall_trace(int dir, struct pt_regs *regs) 1066 { 1067 unsigned long saved_reg; 1068 1069 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 1070 return regs->syscallno; 1071 1072 if (is_compat_task()) { 1073 /* AArch32 uses ip (r12) for scratch */ 1074 saved_reg = regs->regs[12]; 1075 regs->regs[12] = dir; 1076 } else { 1077 /* 1078 * Save X7. X7 is used to denote syscall entry/exit: 1079 * X7 = 0 -> entry, = 1 -> exit 1080 */ 1081 saved_reg = regs->regs[7]; 1082 regs->regs[7] = dir; 1083 } 1084 1085 if (dir) 1086 tracehook_report_syscall_exit(regs, 0); 1087 else if (tracehook_report_syscall_entry(regs)) 1088 regs->syscallno = ~0UL; 1089 1090 if (is_compat_task()) 1091 regs->regs[12] = saved_reg; 1092 else 1093 regs->regs[7] = saved_reg; 1094 1095 return regs->syscallno; 1096 } 1097