From 33e544edf5711fcbc8fd94761890dd2e4d1b3929 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 12 Apr 2022 15:54:33 +0300 Subject: [PATCH 01/11] ARC: define uapi for BPF_PROG_TYPE_PERF_EVENT program type Define appropriate uapi for the BPF_PROG_TYPE_PERF_EVENT program type by exporting the user_regs_struct structure instead of the pt_regs structure that is in-kernel only. Signed-off-by: Sergey Matyukevich --- arch/arc/include/asm/perf_event.h | 4 ++++ arch/arc/include/uapi/asm/bpf_perf_event.h | 9 +++++++++ 2 files changed, 13 insertions(+) create mode 100644 arch/arc/include/uapi/asm/bpf_perf_event.h diff --git a/arch/arc/include/asm/perf_event.h b/arch/arc/include/asm/perf_event.h index d9c1d678638019..ea4c463e549fc0 100644 --- a/arch/arc/include/asm/perf_event.h +++ b/arch/arc/include/asm/perf_event.h @@ -65,6 +65,10 @@ struct arc_reg_cc_build { #define PERF_COUNT_ARC_HW_MAX (PERF_COUNT_HW_MAX + 8) +#ifdef CONFIG_PERF_EVENTS +#define perf_arch_bpf_user_pt_regs(regs) (struct user_regs_struct *)regs +#endif + /* * Some ARC pct quirks: * diff --git a/arch/arc/include/uapi/asm/bpf_perf_event.h b/arch/arc/include/uapi/asm/bpf_perf_event.h new file mode 100644 index 00000000000000..6cb1c2823288b2 --- /dev/null +++ b/arch/arc/include/uapi/asm/bpf_perf_event.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__ +#define _UAPI__ASM_BPF_PERF_EVENT_H__ + +#include + +typedef struct user_regs_struct bpf_user_pt_regs_t; + +#endif /* _UAPI__ASM_BPF_PERF_EVENT_H__ */ From eacf2529c0a8ce6044436cdf870aa69b373ef4fa Mon Sep 17 00:00:00 2001 From: Vladimir Isaev Date: Tue, 12 Apr 2022 15:59:11 +0300 Subject: [PATCH 02/11] libbpf: add ARC support to bpf_tracing.h Add PT_REGS macros suitable for ARCompact and ARCv2. Signed-off-by: Vladimir Isaev --- tools/include/uapi/asm/bpf_perf_event.h | 2 ++ tools/lib/bpf/bpf_tracing.h | 30 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/tools/include/uapi/asm/bpf_perf_event.h b/tools/include/uapi/asm/bpf_perf_event.h index 39acc149d84320..d7dfeab0d71ad3 100644 --- a/tools/include/uapi/asm/bpf_perf_event.h +++ b/tools/include/uapi/asm/bpf_perf_event.h @@ -1,5 +1,7 @@ #if defined(__aarch64__) #include "../../arch/arm64/include/uapi/asm/bpf_perf_event.h" +#elif defined(__arc__) +#include "../../arch/arc/include/uapi/asm/bpf_perf_event.h" #elif defined(__s390__) #include "../../arch/s390/include/uapi/asm/bpf_perf_event.h" #elif defined(__riscv) diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h index db05a593710560..7c7508600a6cc1 100644 --- a/tools/lib/bpf/bpf_tracing.h +++ b/tools/lib/bpf/bpf_tracing.h @@ -27,6 +27,9 @@ #elif defined(__TARGET_ARCH_riscv) #define bpf_target_riscv #define bpf_target_defined +#elif defined(__TARGET_ARCH_arc) + #define bpf_target_arc + #define bpf_target_defined #else /* Fall back to what the compiler says */ @@ -54,6 +57,9 @@ #elif defined(__riscv) && __riscv_xlen == 64 #define bpf_target_riscv #define bpf_target_defined +#elif defined(__arc__) + #define bpf_target_arc + #define bpf_target_defined #endif /* no compiler target */ #endif @@ -320,6 +326,30 @@ struct pt_regs; #define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), sp) #define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), epc) +#elif defined(bpf_target_arc) + +struct pt_regs; +#define PT_REGS_ARC const volatile struct user_regs_struct +#define PT_REGS_PARM1(x) (((PT_REGS_ARC *)(x))->scratch.r0) +#define PT_REGS_PARM2(x) (((PT_REGS_ARC *)(x))->scratch.r1) +#define PT_REGS_PARM3(x) (((PT_REGS_ARC *)(x))->scratch.r2) +#define PT_REGS_PARM4(x) (((PT_REGS_ARC *)(x))->scratch.r3) +#define PT_REGS_PARM5(x) (((PT_REGS_ARC *)(x))->scratch.r4) +#define PT_REGS_RET(x) (((PT_REGS_ARC *)(x))->scratch.blink) +#define PT_REGS_RC(x) (((PT_REGS_ARC *)(x))->scratch.r0) +#define PT_REGS_SP(x) (((PT_REGS_ARC *)(x))->scratch.sp) +#define PT_REGS_IP(x) (((PT_REGS_ARC *)(x))->scratch.ret) + +#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_ARC *)(x), scratch.r0) +#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_ARC *)(x), scratch.r1) +#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_ARC *)(x), scratch.r2) +#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_ARC *)(x), scratch.r3) +#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_ARC *)(x), scratch.r4) +#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_ARC *)(x), scratch.blink) +#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_ARC *)(x), scratch.r0) +#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_ARC *)(x), scratch.sp) +#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_ARC *)(x), scratch.ret) + #endif #if defined(bpf_target_powerpc) From 8f0350a89c83db993fd43982b29981225eaf8b7a Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 12 Apr 2022 16:11:57 +0300 Subject: [PATCH 03/11] ARC: enable HAVE_REGS_AND_STACK_ACCESS_API feature 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 | 26 ++++++++ arch/arc/kernel/ptrace.c | 119 ++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index b2260e24f10211..61739d6804e0ed 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -38,6 +38,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 549b49142d85e9..aaac7a683cdcf4 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__ @@ -53,6 +54,8 @@ struct pt_regs { ecr_reg ecr; }; +#define MAX_REG_OFFSET offsetof(struct pt_regs, ecr) + struct callee_regs { unsigned long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13; }; @@ -95,6 +98,8 @@ struct pt_regs { unsigned long status32; }; +#define MAX_REG_OFFSET offsetof(struct pt_regs, status32) + struct callee_regs { unsigned long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13; }; @@ -170,6 +175,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 72eea096a6ee00..cd58d991b7705e 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -11,6 +11,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(gp), + 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(ecr), + REG_OFFSET_END, +}; + +#else + +static const struct pt_regs_offset regoffset_table[] = { + REG_OFFSET_NAME(orig_r0), + REG_OFFSET_NAME(ecr), + REG_OFFSET_NAME(bta), + REG_OFFSET_NAME(fp), + REG_OFFSET_NAME(r30), + REG_OFFSET_NAME(r12), + REG_OFFSET_NAME(gp), +#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(sp), + 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), +#ifndef CONFIG_ARC_LACKS_ZOL + REG_OFFSET_NAME(lp_end), + REG_OFFSET_NAME(lp_start), + REG_OFFSET_NAME(lp_count), +#endif + 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 task_struct *tsk) { struct callee_regs *tmp = (struct callee_regs *)tsk->thread.callee_reg; @@ -290,3 +373,39 @@ asmlinkage void syscall_trace_exit(struct pt_regs *regs) { tracehook_report_syscall_exit(regs, 0); } + +int regs_query_register_offset(const char *name) +{ + const struct pt_regs_offset *roff; + + for (roff = regoffset_table; roff->name != NULL; roff++) + if (!strcmp(roff->name, name)) + return roff->offset; + return -EINVAL; +} + +const char *regs_query_register_name(unsigned int offset) +{ + const struct pt_regs_offset *roff; + for (roff = regoffset_table; roff->name != NULL; roff++) + if (roff->offset == offset) + return roff->name; + return NULL; +} + +bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) +{ + return (addr & ~(THREAD_SIZE - 1)) == + (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)); +} + +unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) +{ + unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); + + addr += n; + if (regs_within_kernel_stack(regs, (unsigned long)addr)) + return *addr; + else + return 0; +} From b25042436bd658a27149d6901ba89ace81de2c69 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 12 Apr 2022 16:14:32 +0300 Subject: [PATCH 04/11] ARC: entry: fix syscall_trace_exit argument 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 2061f7108a7293..7994f1bb690046 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -175,6 +175,7 @@ tracesys_exit: STR r0, sp, PT_r0 ; POST syscall trace hook + MOVR r0, sp ; pt_regs bl @syscall_trace_exit ; don't call ret_from_system_call as it saves r0, already done above From 5c7be9af0ad4ee12f10b6455f6749f46bfc0f18c Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 12 Apr 2022 16:19:28 +0300 Subject: [PATCH 05/11] ARC: implement syscall tracepoints 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 | 4 ++++ arch/arc/kernel/entry.S | 12 ++++++------ arch/arc/kernel/ptrace.c | 21 ++++++++++++++++++--- 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 61739d6804e0ed..0d6eef18aa4a8d 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -41,6 +41,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 0e0fdbe6b2a118..42a8995fe2ee0b 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 c4c0b3492326b4..94c1f5241c0f5b 100644 --- a/arch/arc/include/asm/thread_info.h +++ b/arch/arc/include/asm/thread_info.h @@ -82,6 +82,7 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void) #define TIF_NOTIFY_SIGNAL 5 /* signal notifications exist */ #define TIF_SYSCALL_TRACE 15 /* syscall trace active */ #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; @@ -363,15 +366,27 @@ long arch_ptrace(struct task_struct *child, long request, asmlinkage int syscall_trace_enter(struct pt_regs *regs) { - if (tracehook_report_syscall_entry(regs)) - return -1; + if (test_thread_flag(TIF_SYSCALL_TRACE)) + if (tracehook_report_syscall_entry(regs)) + return -1; + +#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) { - tracehook_report_syscall_exit(regs, 0); + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_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) From bfb98ad99210b33200b7017138aefdeb368cdb3d Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 12 Apr 2022 19:17:49 +0300 Subject: [PATCH 06/11] ARC: disasm: fix kprobe get/set functions Layout of pt_regs structure differs between ARCompact/ARCv2/ARCv3. Fix set_reg/get_reg functions to handle proper registers. Signed-off-by: Sergey Matyukevich --- arch/arc/kernel/disasm.c | 98 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c index 49be4e45b847de..24c90e2736e6fd 100644 --- a/arch/arc/kernel/disasm.c +++ b/arch/arc/kernel/disasm.c @@ -434,6 +434,7 @@ 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]; @@ -441,11 +442,44 @@ long __kprobes get_reg(int reg, struct pt_regs *regs, if (cregs && (reg <= 25)) { p = &cregs->r13; - return p[13-reg]; + return p[13 - reg]; } if (reg == 26) return regs->gp; + +#elif defined(CONFIG_ISA_ARCV2) + if (reg <= 11) { + p = ®s->r0; + return p[reg]; + } + + if (reg == 12) + return regs->r12; + + if (cregs && (reg <= 25)) { + p = &cregs->r13; + return p[13 - reg]; + } + + if (reg == 26) + return regs->gp; + +#else /* CONFIG_ISA_ARCV3 */ + if (reg <= 13) { + p = ®s->r0; + return p[reg]; + } + + if (cregs && (reg <= 26)) { + p = &cregs->r14; + return p[reg - 14]; + } + + if (reg == 30) + return regs->gp; +#endif + if (reg == 27) return regs->fp; if (reg == 28) @@ -461,6 +495,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 +504,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; + } +#elif defined(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: @@ -487,6 +552,35 @@ void __kprobes set_reg(int reg, long val, struct pt_regs *regs, default: break; } +#else /* CONFIG_ISA_ARCV3 */ + switch (reg) { + case 0 ... 13: + p = ®s->r0; + p[reg] = val; + break; + case 14 ... 26: + if (cregs) { + p = &cregs->r14; + p[reg - 14] = val; + } + break; + case 27: + regs->fp = val; + break; + case 28: + regs->sp = val; + break; + case 30: + regs->gp = val; + break; + case 31: + regs->blink = val; + break; + default: + break; + } + +#endif } /* From 0a62ac01c4a2ebfbbead2b186d0af9ebc575b117 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 12 Apr 2022 19:23:21 +0300 Subject: [PATCH 07/11] ARCv3: enable HAVE_REGS_AND_STACK_ACCESS_API All the supporting functions and defines are the same for all three ARC architecture flavors. Define missing regoffset_table for ARCv3. Signed-off-by: Sergey Matyukevich --- arch/arc/include/asm/ptrace.h | 2 ++ arch/arc/kernel/ptrace.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index aaac7a683cdcf4..a70c7e79966e6d 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -124,6 +124,8 @@ struct pt_regs { unsigned long status32; }; +#define MAX_REG_OFFSET offsetof(struct pt_regs, status32) + /* ARCv3 callee regs start from r14; gp is r30 not r26 */ struct callee_regs { unsigned long r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26; diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index d5ab7c20a3387c..9051cb60285bcd 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -52,7 +52,7 @@ static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_END, }; -#else +#elif defined(CONFIG_ISA_ARCV2) static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_NAME(orig_r0), @@ -95,6 +95,38 @@ static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_NAME(status32), REG_OFFSET_END, }; + +#else /* CONFIG_ISA_ARCV3 */ + +static const struct pt_regs_offset regoffset_table[] = { + REG_OFFSET_NAME(orig_r0), + REG_OFFSET_NAME(r58), + REG_OFFSET_NAME(r59), + REG_OFFSET_NAME(ecr), + REG_OFFSET_NAME(bta), + REG_OFFSET_NAME(fp), + REG_OFFSET_NAME(gp), + REG_OFFSET_NAME(sp), + 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(r12), + REG_OFFSET_NAME(r13), + REG_OFFSET_NAME(blink), + REG_OFFSET_NAME(ret), + REG_OFFSET_NAME(status32), + REG_OFFSET_END, +}; + #endif static struct callee_regs *task_callee_regs(struct task_struct *tsk) From 436160242c539d21ac20c0b58f99dc2115f5ae81 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 12 Apr 2022 20:33:34 +0300 Subject: [PATCH 08/11] ARC: disasm: add missing gp registers for ARCv2 Signed-off-by: Sergey Matyukevich --- arch/arc/kernel/disasm.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c index 24c90e2736e6fd..4248ced7d18e5b 100644 --- a/arch/arc/kernel/disasm.c +++ b/arch/arc/kernel/disasm.c @@ -464,6 +464,14 @@ long __kprobes get_reg(int reg, struct pt_regs *regs, if (reg == 26) return regs->gp; + 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 #else /* CONFIG_ISA_ARCV3 */ if (reg <= 13) { @@ -546,9 +554,20 @@ 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; } From 1c9ab043fb0890f94b8b0b2f3808ff840ebd26d4 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 12 Apr 2022 20:34:39 +0300 Subject: [PATCH 09/11] ARC: ptrace: fix typo in genregs_get Fix typo in genregs_get that makes it store field address instead of its value. Signed-off-by: Sergey Matyukevich --- arch/arc/kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 9051cb60285bcd..bbcf1d46687237 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -187,7 +187,7 @@ static int genregs_get(struct task_struct *target, membuf_store(&to, cregs->r15); membuf_store(&to, cregs->r14); #ifdef CONFIG_ISA_ARCV3 - membuf_store(&to, &ptregs->r13); + membuf_store(&to, ptregs->r13); #else membuf_store(&to, cregs->r13); #endif From b2500ed4e75dbaa2cce72a0a31b1e1542f83725f Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 12 Apr 2022 19:28:09 +0300 Subject: [PATCH 10/11] ARCv3: modify icache flush Properly handle kgdb and kprobes addresses in kernel translated memory. Update address check: throw bugs for user mappings and inconsistent vmalloc areas. Signed-off-by: Sergey Matyukevich --- arch/arc/mm/cache-arcv3.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arc/mm/cache-arcv3.c b/arch/arc/mm/cache-arcv3.c index 9dd2784a6c105d..8fcc0b201a02e4 100644 --- a/arch/arc/mm/cache-arcv3.c +++ b/arch/arc/mm/cache-arcv3.c @@ -315,14 +315,19 @@ void flush_icache_range(unsigned long kvaddr, unsigned long kvend) { unsigned int tot_sz = kvend - kvaddr; - BUG_ON((kvaddr < VMALLOC_START) || (kvend > VMALLOC_END)); + BUG_ON(is_vmalloc_addr((void *)kvaddr) && !is_vmalloc_addr((void *)kvend)); + BUG_ON(!is_vmalloc_addr((void *)kvaddr) && is_vmalloc_addr((void *)kvend)); + BUG_ON(kvaddr < TASK_SIZE); while (tot_sz > 0) { unsigned int off, sz; unsigned long paddr, pfn; off = kvaddr % PAGE_SIZE; - pfn = vmalloc_to_pfn((void *)kvaddr); + if (is_vmalloc_addr((void *)kvaddr)) + pfn = vmalloc_to_pfn((void *)kvaddr); + else + pfn = virt_to_pfn((void *)kvaddr); paddr = (pfn << PAGE_SHIFT) + off; sz = min_t(unsigned int, tot_sz, PAGE_SIZE - off); __sync_icache_dcache(paddr, kvaddr, sz); From b3f0ecc3df0d61265cb4550397fe922754d0f546 Mon Sep 17 00:00:00 2001 From: Vladimir Isaev Date: Tue, 12 Apr 2022 16:21:01 +0300 Subject: [PATCH 11/11] ARC: pahole: workaround ARC toolchains generate 'complex float' DIE entries in libgcc. At the moment such entries are not yet handled by pahole. So for now disable BTF floats. Signed-off-by: Vladimir Isaev --- scripts/pahole-flags.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pahole-flags.sh b/scripts/pahole-flags.sh index e6093adf4c06d7..12cd096be97a3b 100755 --- a/scripts/pahole-flags.sh +++ b/scripts/pahole-flags.sh @@ -14,7 +14,7 @@ if [ "${pahole_ver}" -ge "118" ] && [ "${pahole_ver}" -le "121" ]; then extra_paholeopt="${extra_paholeopt} --skip_encoding_btf_vars" fi if [ "${pahole_ver}" -ge "121" ]; then - extra_paholeopt="${extra_paholeopt} --btf_gen_floats" + extra_paholeopt="${extra_paholeopt}" fi echo ${extra_paholeopt}