提交 0642af24 编写于 作者: M Mao Minkai 提交者: guzitao

sw64: fix incorrect gp after uretprobe triggered

Sunway inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I56OLG

--------------------------------

SW64 use r26 to calculate gp after function return, so r26 needs to be
restored when uretprobe trampoline is hit.

Since uretprobe is handled in generic code, we will modify r26 before we
return to user space.
Signed-off-by: NMao Minkai <maominkai@wxiat.com>
Reviewed-by: NHe Sheng <hesheng@wxiat.com>
Signed-off-by: NGu Zitao <guzitao@wxiat.com>
上级 d0991acd
...@@ -35,4 +35,6 @@ struct arch_uprobe_task { ...@@ -35,4 +35,6 @@ struct arch_uprobe_task {
unsigned long saved_trap_nr; unsigned long saved_trap_nr;
}; };
extern void sw64_fix_uretprobe(struct pt_regs *regs);
#endif /* _ASM_SW64_UPROBES_H */ #endif /* _ASM_SW64_UPROBES_H */
...@@ -267,12 +267,14 @@ do_entIF(unsigned long inst_type, struct pt_regs *regs) ...@@ -267,12 +267,14 @@ do_entIF(unsigned long inst_type, struct pt_regs *regs)
case BREAK_KPROBE_SS: case BREAK_KPROBE_SS:
if (notify_die(DIE_SSTEPBP, "single_step", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) if (notify_die(DIE_SSTEPBP, "single_step", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
return; return;
#ifdef CONFIG_UPROBES
case UPROBE_BRK_UPROBE: case UPROBE_BRK_UPROBE:
if (notify_die(DIE_UPROBE, "uprobe", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) if (notify_die(DIE_UPROBE, "uprobe", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
return; return sw64_fix_uretprobe(regs);
case UPROBE_BRK_UPROBE_XOL: case UPROBE_BRK_UPROBE_XOL:
if (notify_die(DIE_UPROBE_XOL, "uprobe_xol", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) if (notify_die(DIE_UPROBE_XOL, "uprobe_xol", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
return; return sw64_fix_uretprobe(regs);
#endif
} }
if (user_mode(regs)) if (user_mode(regs))
......
...@@ -151,3 +151,41 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) ...@@ -151,3 +151,41 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
{ {
return 0; return 0;
} }
/*
* struct xol_area and get_trampoline_vaddr() are copied from
* kernel/events/uprobes.c to avoid modifying arch-independent
* code.
*/
struct xol_area {
wait_queue_head_t wq;
atomic_t slot_count;
unsigned long *bitmap;
struct vm_special_mapping xol_mapping;
struct page *pages[2];
unsigned long vaddr;
};
static unsigned long get_trampoline_vaddr(void)
{
struct xol_area *area;
unsigned long trampoline_vaddr = -1;
area = READ_ONCE(current->mm->uprobes_state.xol_area);
if (area)
trampoline_vaddr = area->vaddr;
return trampoline_vaddr;
}
void sw64_fix_uretprobe(struct pt_regs *regs)
{
unsigned long bp_vaddr;
bp_vaddr = uprobe_get_swbp_addr(regs);
/*
* regs->pc has been changed to orig_ret_vaddr in handle_trampoline().
*/
if (bp_vaddr == get_trampoline_vaddr())
regs->r26 = regs->pc;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册