uprobes.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. #include <linux/highmem.h>
  3. #include <linux/ptrace.h>
  4. #include <linux/sched.h>
  5. #include <linux/uprobes.h>
  6. #include <asm/cacheflush.h>
  7. #define UPROBE_TRAP_NR UINT_MAX
  8. int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe,
  9. struct mm_struct *mm, unsigned long addr)
  10. {
  11. int idx;
  12. union loongarch_instruction insn;
  13. if (addr & 0x3)
  14. return -EILSEQ;
  15. for (idx = ARRAY_SIZE(auprobe->insn) - 1; idx >= 0; idx--) {
  16. insn.word = auprobe->insn[idx];
  17. if (insns_not_supported(insn))
  18. return -EINVAL;
  19. }
  20. if (insns_need_simulation(insn)) {
  21. auprobe->ixol[0] = larch_insn_gen_nop();
  22. auprobe->simulate = true;
  23. } else {
  24. auprobe->ixol[0] = auprobe->insn[0];
  25. auprobe->simulate = false;
  26. }
  27. auprobe->ixol[1] = UPROBE_XOLBP_INSN;
  28. return 0;
  29. }
  30. int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
  31. {
  32. struct uprobe_task *utask = current->utask;
  33. utask->autask.saved_trap_nr = current->thread.trap_nr;
  34. current->thread.trap_nr = UPROBE_TRAP_NR;
  35. instruction_pointer_set(regs, utask->xol_vaddr);
  36. return 0;
  37. }
  38. int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
  39. {
  40. struct uprobe_task *utask = current->utask;
  41. WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR);
  42. current->thread.trap_nr = utask->autask.saved_trap_nr;
  43. instruction_pointer_set(regs, utask->vaddr + LOONGARCH_INSN_SIZE);
  44. return 0;
  45. }
  46. void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
  47. {
  48. struct uprobe_task *utask = current->utask;
  49. current->thread.trap_nr = utask->autask.saved_trap_nr;
  50. instruction_pointer_set(regs, utask->vaddr);
  51. }
  52. bool arch_uprobe_xol_was_trapped(struct task_struct *t)
  53. {
  54. if (t->thread.trap_nr != UPROBE_TRAP_NR)
  55. return true;
  56. return false;
  57. }
  58. bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
  59. {
  60. union loongarch_instruction insn;
  61. if (!auprobe->simulate)
  62. return false;
  63. insn.word = auprobe->insn[0];
  64. arch_simulate_insn(insn, regs);
  65. return true;
  66. }
  67. unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
  68. struct pt_regs *regs)
  69. {
  70. unsigned long ra = regs->regs[1];
  71. regs->regs[1] = trampoline_vaddr;
  72. return ra;
  73. }
  74. bool arch_uretprobe_is_alive(struct return_instance *ret,
  75. enum rp_check ctx, struct pt_regs *regs)
  76. {
  77. if (ctx == RP_CHECK_CHAIN_CALL)
  78. return regs->regs[3] <= ret->stack;
  79. else
  80. return regs->regs[3] < ret->stack;
  81. }
  82. int arch_uprobe_exception_notify(struct notifier_block *self,
  83. unsigned long val, void *data)
  84. {
  85. return NOTIFY_DONE;
  86. }
  87. bool uprobe_breakpoint_handler(struct pt_regs *regs)
  88. {
  89. if (uprobe_pre_sstep_notifier(regs))
  90. return true;
  91. return false;
  92. }
  93. bool uprobe_singlestep_handler(struct pt_regs *regs)
  94. {
  95. if (uprobe_post_sstep_notifier(regs))
  96. return true;
  97. return false;
  98. }
  99. unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
  100. {
  101. return instruction_pointer(regs);
  102. }
  103. void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
  104. void *src, unsigned long len)
  105. {
  106. void *kaddr = kmap_local_page(page);
  107. void *dst = kaddr + (vaddr & ~PAGE_MASK);
  108. memcpy(dst, src, len);
  109. flush_icache_range((unsigned long)dst, (unsigned long)dst + len);
  110. kunmap_local(kaddr);
  111. }