[PATCH v2 3/4] ARC: implement syscall tracepoints
From: Sergey Matyukevich Implement all the bits required to support HAVE_SYSCALL_TRACEPOINTS according to Documentation/trace/ftrace-design.rst. Signed-off-by: Sergey Matyukevich --- arch/arc/Kconfig | 1 + arch/arc/include/asm/syscall.h | 2 ++ arch/arc/include/asm/thread_info.h | 5 - arch/arc/kernel/entry.S| 12 ++-- arch/arc/kernel/ptrace.c | 21 ++--- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 3c850d0f431c..9e3653253ef2 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -39,6 +39,7 @@ config ARC select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_MOD_ARCH_SPECIFIC select HAVE_PERF_EVENTS + select HAVE_SYSCALL_TRACEPOINTS select IRQ_DOMAIN select MODULES_USE_ELF_RELA select OF diff --git a/arch/arc/include/asm/syscall.h b/arch/arc/include/asm/syscall.h index 94529e89dff0..9709256e31c8 100644 --- a/arch/arc/include/asm/syscall.h +++ b/arch/arc/include/asm/syscall.h @@ -12,6 +12,8 @@ #include #include /* in_syscall() */ +extern void *sys_call_table[]; + static inline long syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { diff --git a/arch/arc/include/asm/thread_info.h b/arch/arc/include/asm/thread_info.h index 1e0b2e3914d5..6ba7fe417095 100644 --- a/arch/arc/include/asm/thread_info.h +++ b/arch/arc/include/asm/thread_info.h @@ -78,9 +78,9 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void) #define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */ #define TIF_NOTIFY_SIGNAL 5 /* signal notifications exist */ #define TIF_SYSCALL_TRACE 15 /* syscall trace active */ - /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 16 +#define TIF_SYSCALL_TRACEPOINT 17 /* syscall tracepoint instrumentation */ #define _TIF_SYSCALL_TRACE (1< #include +#define CREATE_TRACE_POINTS +#include + struct pt_regs_offset { const char *name; int offset; @@ -340,15 +343,27 @@ long arch_ptrace(struct task_struct *child, long request, asmlinkage int syscall_trace_entry(struct pt_regs *regs) { - if (ptrace_report_syscall_entry(regs)) - return ULONG_MAX; + if (test_thread_flag(TIF_SYSCALL_TRACE)) + if (ptrace_report_syscall_entry(regs)) + return ULONG_MAX; + +#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) + trace_sys_enter(regs, syscall_get_nr(current, regs)); +#endif return regs->r8; } asmlinkage void syscall_trace_exit(struct pt_regs *regs) { - ptrace_report_syscall_exit(regs, 0); + if (test_thread_flag(TIF_SYSCALL_TRACE)) + ptrace_report_syscall_exit(regs, 0); + +#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) + trace_sys_exit(regs, regs_return_value(regs)); +#endif } int regs_query_register_offset(const char *name) -- 2.35.1 ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
[PATCH v2 4/4] ARC: disasm: handle ARCv2 case in kprobe get/set functions
From: Sergey Matyukevich Current implementation of get_reg/set_reg implies ARCompact layout of pt_regs structure. Meanwhile pt_regs structure differs between ARCompact and ARCv2. Update those functions to handle ARCv2. Signed-off-by: Sergey Matyukevich --- arch/arc/kernel/disasm.c | 64 ++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c index 03f8b1be0c3a..38f5f8325322 100644 --- a/arch/arc/kernel/disasm.c +++ b/arch/arc/kernel/disasm.c @@ -434,14 +434,31 @@ long __kprobes get_reg(int reg, struct pt_regs *regs, { long *p; +#if defined(CONFIG_ISA_ARCOMPACT) if (reg <= 12) { p = ®s->r0; return p[-reg]; } +#else /* CONFIG_ISA_ARCV2 */ + if (reg <= 11) { + p = ®s->r0; + return p[reg]; + } + if (reg == 12) + return regs->r12; + if (reg == 30) + return regs->r30; +#ifdef CONFIG_ARC_HAS_ACCL_REGS + if (reg == 58) + return regs->r58; + if (reg == 59) + return regs->r59; +#endif +#endif if (cregs && (reg <= 25)) { p = &cregs->r13; - return p[13-reg]; + return p[13 - reg]; } if (reg == 26) @@ -461,6 +478,7 @@ void __kprobes set_reg(int reg, long val, struct pt_regs *regs, { long *p; +#if defined(CONFIG_ISA_ARCOMPACT) switch (reg) { case 0 ... 12: p = ®s->r0; @@ -469,7 +487,37 @@ void __kprobes set_reg(int reg, long val, struct pt_regs *regs, case 13 ... 25: if (cregs) { p = &cregs->r13; - p[13-reg] = val; + p[13 - reg] = val; + } + break; + case 26: + regs->gp = val; + break; + case 27: + regs->fp = val; + break; + case 28: + regs->sp = val; + break; + case 31: + regs->blink = val; + break; + default: + break; + } +#else /* CONFIG_ISA_ARCV2 */ + switch (reg) { + case 0 ... 11: + p = ®s->r0; + p[reg] = val; + break; + case 12: + regs->r12 = val; + break; + case 13 ... 25: + if (cregs) { + p = &cregs->r13; + p[13 - reg] = val; } break; case 26: @@ -481,12 +529,24 @@ void __kprobes set_reg(int reg, long val, struct pt_regs *regs, case 28: regs->sp = val; break; + case 30: + regs->r30 = val; + break; case 31: regs->blink = val; break; +#ifdef CONFIG_ARC_HAS_ACCL_REGS + case 58: + regs->r58 = val; + break; + case 59: + regs->r59 = val; + break; +#endif default: break; } +#endif } /* -- 2.35.1 ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
[PATCH v2 2/4] ARC: entry: fix syscall_trace_exit argument
From: Sergey Matyukevich Function syscall_trace_exit expects pointer to pt_regs. However r0 is also used to keep syscall return value. Restore pointer to pt_regs before calling syscall_trace_exit. Signed-off-by: Sergey Matyukevich --- arch/arc/kernel/entry.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index dd77a0c8f740..66ba549b520f 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -196,6 +196,7 @@ tracesys_exit: st r0, [sp, PT_r0] ; sys call return value in pt_regs ;POST Sys Call Ptrace Hook + mov r0, sp ; pt_regs needed bl @syscall_trace_exit b ret_from_exception ; NOT ret_from_system_call at is saves r0 which ; we'd done before calling post hook above -- 2.35.1 ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
[PATCH v2 1/4] ARC: enable HAVE_REGS_AND_STACK_ACCESS_API feature
From: Sergey Matyukevich Enable HAVE_REGS_AND_STACK_ACCESS_API feature for ARC architecture, including ARCcompact and ARCv2 flavors. Add supporting functions and defines. Signed-off-by: Sergey Matyukevich --- arch/arc/Kconfig | 1 + arch/arc/include/asm/ptrace.h | 27 arch/arc/kernel/ptrace.c | 119 ++ 3 files changed, 147 insertions(+) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index e0a60a27e14d..3c850d0f431c 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -36,6 +36,7 @@ config ARC select HAVE_KERNEL_LZMA select HAVE_KPROBES select HAVE_KRETPROBES + select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_MOD_ARCH_SPECIFIC select HAVE_PERF_EVENTS select IRQ_DOMAIN diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index cca8d6583e31..5869a74c0db2 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -8,6 +8,7 @@ #define __ASM_ARC_PTRACE_H #include +#include #ifndef __ASSEMBLY__ @@ -54,6 +55,9 @@ struct pt_regs { unsigned long user_r25; }; + +#define MAX_REG_OFFSET offsetof(struct pt_regs, user_r25) + #else struct pt_regs { @@ -102,6 +106,8 @@ struct pt_regs { unsigned long status32; }; +#define MAX_REG_OFFSET offsetof(struct pt_regs, status32) + #endif /* Callee saved registers - need to be saved only when you are scheduled out */ @@ -154,6 +160,27 @@ static inline void instruction_pointer_set(struct pt_regs *regs, { instruction_pointer(regs) = val; } + +static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ + return regs->sp; +} + +extern int regs_query_register_offset(const char *name); +extern const char *regs_query_register_name(unsigned int offset); +extern bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr); +extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, + unsigned int n); + +static inline unsigned long regs_get_register(struct pt_regs *regs, + unsigned int offset) +{ + if (unlikely(offset > MAX_REG_OFFSET)) + return 0; + + return *(unsigned long *)((unsigned long)regs + offset); +} + #endif /* !__ASSEMBLY__ */ #endif /* __ASM_PTRACE_H */ diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 54b419ac8bda..5fa5bceb83f3 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -9,6 +9,89 @@ #include #include +struct pt_regs_offset { + const char *name; + int offset; +}; + +#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} +#define REG_OFFSET_END {.name = NULL, .offset = 0} + +#ifdef CONFIG_ISA_ARCOMPACT +static const struct pt_regs_offset regoffset_table[] = { + REG_OFFSET_NAME(bta), + REG_OFFSET_NAME(lp_start), + REG_OFFSET_NAME(lp_end), + REG_OFFSET_NAME(lp_count), + REG_OFFSET_NAME(status32), + REG_OFFSET_NAME(ret), + REG_OFFSET_NAME(blink), + REG_OFFSET_NAME(fp), + REG_OFFSET_NAME(r26), + REG_OFFSET_NAME(r12), + REG_OFFSET_NAME(r11), + REG_OFFSET_NAME(r10), + REG_OFFSET_NAME(r9), + REG_OFFSET_NAME(r8), + REG_OFFSET_NAME(r7), + REG_OFFSET_NAME(r6), + REG_OFFSET_NAME(r5), + REG_OFFSET_NAME(r4), + REG_OFFSET_NAME(r3), + REG_OFFSET_NAME(r2), + REG_OFFSET_NAME(r1), + REG_OFFSET_NAME(r0), + REG_OFFSET_NAME(sp), + REG_OFFSET_NAME(orig_r0), + REG_OFFSET_NAME(event), + REG_OFFSET_NAME(user_r25), + REG_OFFSET_END, +}; + +#else + +static const struct pt_regs_offset regoffset_table[] = { + REG_OFFSET_NAME(orig_r0), + REG_OFFSET_NAME(event), + REG_OFFSET_NAME(bta), + REG_OFFSET_NAME(user_r25), + REG_OFFSET_NAME(r26), + REG_OFFSET_NAME(fp), + REG_OFFSET_NAME(sp), + REG_OFFSET_NAME(r12), + REG_OFFSET_NAME(r30), +#ifdef CONFIG_ARC_HAS_ACCL_REGS + REG_OFFSET_NAME(r58), + REG_OFFSET_NAME(r59), +#endif +#ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS + REG_OFFSET_NAME(DSP_CTRL), +#endif + REG_OFFSET_NAME(r0), + REG_OFFSET_NAME(r1), + REG_OFFSET_NAME(r2), + REG_OFFSET_NAME(r3), + REG_OFFSET_NAME(r4), + REG_OFFSET_NAME(r5), + REG_OFFSET_NAME(r6), + REG_OFFSET_NAME(r7), + REG_OFFSET_NAME(r8), + REG_OFFSET_NAME(r9), + REG_OFFSET_NAME(r10), + REG_OFFSET_NAME(r11), + REG_OFFSET_NAME(blink), + REG_OFFSET_NAME(lp_end), + REG_OFFSET_NAME(lp_start), + REG_OFFSET_NAME(lp_count), + REG_OFFSET_NAME(ei), + REG_OFFSET_NAME(ldi), + REG_OFFSET_NAME(jli), + REG_OFFSET_NAME(ret), + REG_OFFSET_NAME(status32), + REG_OFFSET_END, +}; +#endif + static struct callee_regs *task_callee_regs(struct tas
[PATCH v2 0/4] ARC: add missing bits for better BPF support
Hi Vineet and all, Here is the second revision of the patch series implementing the following two features for ARC: - HAVE_REGS_AND_STACK_ACCESS_API - HAVE_SYSCALL_TRACEPOINTS Adding these features enables more BPF programs for ARC kernels, including KPROBE, TRACEPOINT, PERF_EVENT program types. Regards, Sergey v1 -> v2: - drop path with uapi for BPF_PROG_TYPE_PERF_EVENT program type: send it via bpf mailing list - add patch with ARCv2 changes for kprobe disasm Sergey Matyukevich (4): ARC: enable HAVE_REGS_AND_STACK_ACCESS_API feature ARC: entry: fix syscall_trace_exit argument ARC: implement syscall tracepoints ARC: disasm: handle ARCv2 case in kprobe get/set functions arch/arc/Kconfig | 2 + arch/arc/include/asm/ptrace.h | 27 ++ arch/arc/include/asm/syscall.h | 2 + arch/arc/include/asm/thread_info.h | 5 +- arch/arc/kernel/disasm.c | 64 - arch/arc/kernel/entry.S| 13 +-- arch/arc/kernel/ptrace.c | 140 - 7 files changed, 241 insertions(+), 12 deletions(-) -- 2.35.1 ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc