diff mbox series

[v1,4/6] bpf, core: Add weak arch_prepare_goto()

Message ID 20241015113915.12623-5-yangtiezhu@loongson.cn (mailing list archive)
State Not Applicable
Delegated to: BPF
Headers show
Series Add jump table support for objtool on LoongArch | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-17 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-18 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-32 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-40 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-31 success Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-38 success Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-39 success Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-8 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-7 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-13 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-15 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Guessed tree name to be net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 5 this patch: 5
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers fail 12 maintainers not CCed: song@kernel.org haoluo@google.com ast@kernel.org andrii@kernel.org john.fastabend@gmail.com sdf@fomichev.me martin.lau@linux.dev daniel@iogearbox.net kpsingh@kernel.org yonghong.song@linux.dev eddyz87@gmail.com jolsa@kernel.org
netdev/build_clang success Errors and warnings before: 3 this patch: 3
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 11 this patch: 11
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 21 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Tiezhu Yang Oct. 15, 2024, 11:39 a.m. UTC
The objtool program needs to analysis the control flow of each
object file generated by compiler toolchain, it needs to know
all the locations that a branch instruction may jump into.

In the past, objtool only works on x86, where objtool can find
the relocation against the nearest instruction before the jump
instruction, which points to the goto table, because there is
only one table jump instruction even if there is more than one
computed goto in a function such as ___bpf_prog_run().

In fact, the compiler behaviors are different for various archs.
On RISC machines (for example LoongArch) this approach does not
work: with -fsection-anchors (often enabled at -O1 or above) the
relocation entry may actually points to the section anchor instead
of the table. Furthermore, objdump kernel/bpf/core.o shows that
there are many table jump instructions in ___bpf_prog_run() with
more than one computed gotos, but there are no relocations which
actually points to the table for some table jump instructions on
LoongArch.

For the jump table of switch cases, a GCC patch "LoongArch: Add
support to annotate tablejump" has been merged into the upstream
mainline, it makes life much easier with the additional section
".discard.tablejump_annotate" which stores the jump info as pairs
of addresses, each pair contains the address of jump instruction
and the address of jump table.

For the jump table of computed gotos, it is indeed not so easy
to implement in the compiler, especially if there is more than
one computed goto in a function.

Without the help of compiler, in order to figure out the address
of goto table by interpreting the LoongArch machine code, add a
function arch_prepare_goto() for goto table, it is an empty weak
definition and is only overridden by archs that have special
requirements.

This is preparation for later patch on LoongArch, there is no any
effect for the other archs with this patch.

Suggested-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 kernel/bpf/core.c | 9 +++++++++
 1 file changed, 9 insertions(+)

Comments

Alexei Starovoitov Oct. 15, 2024, 6:36 p.m. UTC | #1
On Tue, Oct 15, 2024 at 4:50 AM Tiezhu Yang <yangtiezhu@loongson.cn> wrote:
>
> The objtool program needs to analysis the control flow of each
> object file generated by compiler toolchain, it needs to know
> all the locations that a branch instruction may jump into.
>
> In the past, objtool only works on x86, where objtool can find
> the relocation against the nearest instruction before the jump
> instruction, which points to the goto table, because there is
> only one table jump instruction even if there is more than one
> computed goto in a function such as ___bpf_prog_run().
>
> In fact, the compiler behaviors are different for various archs.
> On RISC machines (for example LoongArch) this approach does not
> work: with -fsection-anchors (often enabled at -O1 or above) the
> relocation entry may actually points to the section anchor instead
> of the table. Furthermore, objdump kernel/bpf/core.o shows that
> there are many table jump instructions in ___bpf_prog_run() with
> more than one computed gotos, but there are no relocations which
> actually points to the table for some table jump instructions on
> LoongArch.
>
> For the jump table of switch cases, a GCC patch "LoongArch: Add
> support to annotate tablejump" has been merged into the upstream
> mainline, it makes life much easier with the additional section
> ".discard.tablejump_annotate" which stores the jump info as pairs
> of addresses, each pair contains the address of jump instruction
> and the address of jump table.
>
> For the jump table of computed gotos, it is indeed not so easy
> to implement in the compiler, especially if there is more than
> one computed goto in a function.
>
> Without the help of compiler, in order to figure out the address
> of goto table by interpreting the LoongArch machine code, add a
> function arch_prepare_goto() for goto table, it is an empty weak
> definition and is only overridden by archs that have special
> requirements.
>
> This is preparation for later patch on LoongArch, there is no any
> effect for the other archs with this patch.
>
> Suggested-by: Xi Ruoyao <xry111@xry111.site>
> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
> ---
>  kernel/bpf/core.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> index 5e77c58e0601..81e5d42619d5 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -1706,6 +1706,14 @@ bool bpf_opcode_in_insntable(u8 code)
>  }
>
>  #ifndef CONFIG_BPF_JIT_ALWAYS_ON
> +/*
> + * This symbol is an empty weak definition and is only overridden
> + * by archs that have special requirements.
> + */
> +#ifndef arch_prepare_goto
> +#define arch_prepare_goto()
> +#endif
> +
>  /**
>   *     ___bpf_prog_run - run eBPF program on a given context
>   *     @regs: is the array of MAX_BPF_EXT_REG eBPF pseudo-registers
> @@ -1743,6 +1751,7 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
>  #define CONT_JMP ({ insn++; goto select_insn; })
>
>  select_insn:
> +       arch_prepare_goto();
>         goto *jumptable[insn->code];

That looks fragile. There is no guarantee that compiler will keep
asm statement next to indirect goto.
It has all rights to move/copy such goto around.
There are other parts in the kernel which are not annotated either:
drm_exec_retry_on_contention(),
drivers/misc/lkdtm/cfi.c

You're arguing that it's hard to properly in the compiler,
but that's the only option. It has to be done by the compiler.
Tiezhu Yang Oct. 24, 2024, 9:03 a.m. UTC | #2
On 10/16/2024 02:36 AM, Alexei Starovoitov wrote:
> On Tue, Oct 15, 2024 at 4:50 AM Tiezhu Yang <yangtiezhu@loongson.cn> wrote:
>>
>> The objtool program needs to analysis the control flow of each
>> object file generated by compiler toolchain, it needs to know
>> all the locations that a branch instruction may jump into.

...

>> +       arch_prepare_goto();
>>         goto *jumptable[insn->code];
>
> That looks fragile. There is no guarantee that compiler will keep
> asm statement next to indirect goto.
> It has all rights to move/copy such goto around.
> There are other parts in the kernel which are not annotated either:
> drm_exec_retry_on_contention(),
> drivers/misc/lkdtm/cfi.c
>
> You're arguing that it's hard to properly in the compiler,
> but that's the only option. It has to be done by the compiler.

Thank you very much for your reply. I will drop this patch
and try to find a proper way to handle this case.

By the way, I spent more time to test and analysis with gcc
and clang on x86 and loongarch, it needs to fix some corner
issues for the other patches compiled with clang.

Anyway, I will submit v2 series without changing bpf file,
patch #4 and patch #5 will be removed.

Thanks,
Tiezhu
diff mbox series

Patch

diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 5e77c58e0601..81e5d42619d5 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1706,6 +1706,14 @@  bool bpf_opcode_in_insntable(u8 code)
 }
 
 #ifndef CONFIG_BPF_JIT_ALWAYS_ON
+/*
+ * This symbol is an empty weak definition and is only overridden
+ * by archs that have special requirements.
+ */
+#ifndef arch_prepare_goto
+#define arch_prepare_goto()
+#endif
+
 /**
  *	___bpf_prog_run - run eBPF program on a given context
  *	@regs: is the array of MAX_BPF_EXT_REG eBPF pseudo-registers
@@ -1743,6 +1751,7 @@  static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
 #define CONT_JMP ({ insn++; goto select_insn; })
 
 select_insn:
+	arch_prepare_goto();
 	goto *jumptable[insn->code];
 
 	/* Explicitly mask the register-based shift amounts with 63 or 31