Re: [PATCH 1/8] riscv/kprobe: Prepare the skeleton to implement RISCV OPTPROBES feature

From: liaochang (A)
Date: Tue Nov 01 2022 - 07:07:52 EST


Hi,Conor,

在 2022/11/1 3:42, Conor Dooley 写道:
> Hey Chen Guokai,
>
> On Sun, Oct 30, 2022 at 05:01:34PM +0800, Chen Guokai wrote:
>> From: Liao Chang <liaochang1@xxxxxxxxxx>
>>
>> Prepare skeleton to implement optimized kprobe on RISCV, it consists
>> of Makfile, Kconfig and some architecture specific files: kprobe.h and
>> opt.c opt.c includes some macro, type definition and functions required
>> by kprobe framework, opt_trampoline.S provides a piece of assembly code
>> template used to construct the detour buffer as the target of long jump
>> instruction(s) for each optimzed kprobe.
>>
>> Since the jump range of PC-relative instruction JAL is +/-1M, that is
>> too small to reach the detour buffer, hence the foudamental idea to
>> address OPTPROBES on RISCV is to replace 'EBREAK' with 'AUIPC+JALR'. which
>> means it needs to clobber one more instruction beside the kprobe
>> instruction, furthermore, RISCV supports hybird RVI and RVC in single
>> kernel binary, so in theory a pair of 'AUIPC/JALR' is about to clobber
>> 10 bytes(3 RVC and 1 RVI, 2 bytes is padding for alignment) at worst
>> case. The second hardsome problem is looking for one integer register as
>> the destination of 'AUIPC/JALR' without any side-effect.
>>
>> More solution details will be introduced in the coming commits.
>
> nit: you can drop this reference to future commits.
>
>>
>> Co-developed-by: Chen Guokai <chenguokai17@xxxxxxxxxxxxxxxx>
>> Signed-off-by: Chen Guokai <chenguokai17@xxxxxxxxxxxxxxxx>
>> Signed-off-by: Liao Chang <liaochang1@xxxxxxxxxx>
>
> FYI, your signoff should come last since you're sending the patches, so
> this would become:
>
>> Signed-off-by: Liao Chang <liaochang1@xxxxxxxxxx>
>> Co-developed-by: Chen Guokai <chenguokai17@xxxxxxxxxxxxxxxx>
>> Signed-off-by: Chen Guokai <chenguokai17@xxxxxxxxxxxxxxxx>
>
> I noticed on some of the other patches that your SoB is missing there,
> for example patch 2.

Yes, i have sent patch 2 to mailing list long time ago, got some feedback from
Palmer Debbelt. Because that patch is designed for riscv optprobe, so i bring it
to this patchset.

Thanks.

>
> Thanks,
> Conor.
>
>> ---
>> arch/riscv/Kconfig | 1 +
>> arch/riscv/include/asm/kprobes.h | 32 ++++++++++++++
>> arch/riscv/kernel/probes/Makefile | 1 +
>> arch/riscv/kernel/probes/opt.c | 51 +++++++++++++++++++++++
>> arch/riscv/kernel/probes/opt_trampoline.S | 12 ++++++
>> 5 files changed, 97 insertions(+)
>> create mode 100644 arch/riscv/kernel/probes/opt.c
>> create mode 100644 arch/riscv/kernel/probes/opt_trampoline.S
>>
>> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
>> index 6b48a3ae9843..ca29306c93e2 100644
>> --- a/arch/riscv/Kconfig
>> +++ b/arch/riscv/Kconfig
>> @@ -99,6 +99,7 @@ config RISCV
>> select HAVE_KPROBES if !XIP_KERNEL
>> select HAVE_KPROBES_ON_FTRACE if !XIP_KERNEL
>> select HAVE_KRETPROBES if !XIP_KERNEL
>> + select HAVE_OPTPROBES if !XIP_KERNEL
>> select HAVE_MOVE_PMD
>> select HAVE_MOVE_PUD
>> select HAVE_PCI
>> diff --git a/arch/riscv/include/asm/kprobes.h b/arch/riscv/include/asm/kprobes.h
>> index 217ef89f22b9..22b73a2fd1fd 100644
>> --- a/arch/riscv/include/asm/kprobes.h
>> +++ b/arch/riscv/include/asm/kprobes.h
>> @@ -43,5 +43,37 @@ bool kprobe_single_step_handler(struct pt_regs *regs);
>> void __kretprobe_trampoline(void);
>> void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
>>
>> +#ifdef CONFIG_OPTPROBES
>> +
>> +/* optinsn template addresses */
>> +extern __visible kprobe_opcode_t optprobe_template_entry[];
>> +extern __visible kprobe_opcode_t optprobe_template_end[];
>> +
>> +#define MAX_OPTINSN_SIZE \
>> + ((unsigned long)optprobe_template_end - \
>> + (unsigned long)optprobe_template_entry)
>> +
>> +/*
>> + * For RVI and RVC hybird encoding kernel, althought long jump just needs
>> + * 2 RVI instructions(AUIPC+JALR), optimized instructions is 10 bytes long
>> + * at most to ensure no RVI would be truncated actually, so it means four
>> + * combinations:
>> + * - 2 RVI
>> + * - 4 RVC
>> + * - 2 RVC + 1 RVI
>> + * - 3 RVC + 1 RVI (truncated, need padding)
>> + */
>> +#define MAX_COPIED_INSN 4
>> +#define MAX_OPTIMIZED_LENGTH 10
>> +
>> +struct arch_optimized_insn {
>> + kprobe_opcode_t copied_insn[MAX_COPIED_INSN];
>> + /* detour code buffer */
>> + kprobe_opcode_t *insn;
>> + unsigned long length;
>> + int rd;
>> +};
>> +
>> +#endif /* CONFIG_OPTPROBES */
>> #endif /* CONFIG_KPROBES */
>> #endif /* _ASM_RISCV_KPROBES_H */
>> diff --git a/arch/riscv/kernel/probes/Makefile b/arch/riscv/kernel/probes/Makefile
>> index 7f0840dcc31b..6255b4600875 100644
>> --- a/arch/riscv/kernel/probes/Makefile
>> +++ b/arch/riscv/kernel/probes/Makefile
>> @@ -3,4 +3,5 @@ obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o simulate-insn.o
>> obj-$(CONFIG_KPROBES) += kprobes_trampoline.o
>> obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o
>> obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o simulate-insn.o
>> +obj-$(CONFIG_OPTPROBES) += opt.o opt_trampoline.o
>> CFLAGS_REMOVE_simulate-insn.o = $(CC_FLAGS_FTRACE)
>> diff --git a/arch/riscv/kernel/probes/opt.c b/arch/riscv/kernel/probes/opt.c
>> new file mode 100644
>> index 000000000000..56c8a227c857
>> --- /dev/null
>> +++ b/arch/riscv/kernel/probes/opt.c
>> @@ -0,0 +1,51 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * Kernel Probes Jump Optimization (Optprobes)
>> + *
>> + * Copyright (C) Guokai Chen, 2022
>> + * Author: Guokai Chen chenguokai17@xxxxxxxxxxxxxxxx
>> + */
>> +
>> +#define pr_fmt(fmt) "optprobe: " fmt
>> +
>> +#include <linux/kprobes.h>
>> +#include <asm/kprobes.h>
>> +
>> +int arch_prepared_optinsn(struct arch_optimized_insn *optinsn)
>> +{
>> + return 0;
>> +}
>> +
>> +int arch_check_optimized_kprobe(struct optimized_kprobe *op)
>> +{
>> + return 0;
>> +}
>> +
>> +int arch_prepare_optimized_kprobe(struct optimized_kprobe *op,
>> + struct kprobe *orig)
>> +{
>> + return 0;
>> +}
>> +
>> +void arch_remove_optimized_kprobe(struct optimized_kprobe *op)
>> +{
>> +}
>> +
>> +void arch_optimize_kprobes(struct list_head *oplist)
>> +{
>> +}
>> +
>> +void arch_unoptimize_kprobes(struct list_head *oplist,
>> + struct list_head *done_list)
>> +{
>> +}
>> +
>> +void arch_unoptimize_kprobe(struct optimized_kprobe *op)
>> +{
>> +}
>> +
>> +int arch_within_optimized_kprobe(struct optimized_kprobe *op,
>> + kprobe_opcode_t *addr)
>> +{
>> + return 0;
>> +}
>> diff --git a/arch/riscv/kernel/probes/opt_trampoline.S b/arch/riscv/kernel/probes/opt_trampoline.S
>> new file mode 100644
>> index 000000000000..16160c4367ff
>> --- /dev/null
>> +++ b/arch/riscv/kernel/probes/opt_trampoline.S
>> @@ -0,0 +1,12 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (C) 2022 Guokai Chen
>> + */
>> +
>> +#include <linux/linkage.h>
>> +
>> +#incldue <asm/csr.h>
>> +#include <asm/asm-offsets.h>
>> +
>> +SYM_ENTRY(optprobe_template_entry, SYM_L_GLOBAL, SYM_A_NONE)
>> +SYM_ENTRY(optprobe_template_end, SYM_L_GLOBAL, SYM_A_NONE)
>> --
>> 2.25.1
>>
>>
>> _______________________________________________
>> linux-riscv mailing list
>> linux-riscv@xxxxxxxxxxxxxxxxxxx
>> http://lists.infradead.org/mailman/listinfo/linux-riscv
> .

--
BR,
Liao, Chang