Message ID | 20231122144018.4047232-1-tao.lyu@epfl.ch (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | C inlined assembly for reproducing max<min | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Not a local patch, async |
bpf/vmtest-bpf-next-PR | fail | PR summary |
bpf/vmtest-bpf-next-VM_Test-2 | success | Logs for Validate matrix.py |
bpf/vmtest-bpf-next-VM_Test-0 | success | Logs for Lint |
bpf/vmtest-bpf-next-VM_Test-1 | success | Logs for ShellCheck |
bpf/vmtest-bpf-next-VM_Test-5 | success | Logs for aarch64-gcc / veristat |
bpf/vmtest-bpf-next-VM_Test-3 | fail | Logs for aarch64-gcc / build / build for aarch64 with gcc |
bpf/vmtest-bpf-next-VM_Test-4 | success | Logs for aarch64-gcc / test |
bpf/vmtest-bpf-next-VM_Test-7 | success | Logs for s390x-gcc / test |
bpf/vmtest-bpf-next-VM_Test-12 | success | Logs for x86_64-gcc / veristat |
bpf/vmtest-bpf-next-VM_Test-13 | fail | Logs for x86_64-llvm-16 / build / build for x86_64 with llvm-16 |
bpf/vmtest-bpf-next-VM_Test-10 | fail | Logs for x86_64-gcc / build / build for x86_64 with gcc |
bpf/vmtest-bpf-next-VM_Test-8 | success | Logs for s390x-gcc / veristat |
bpf/vmtest-bpf-next-VM_Test-11 | success | Logs for x86_64-gcc / test |
bpf/vmtest-bpf-next-VM_Test-6 | fail | Logs for s390x-gcc / build / build for s390x with gcc |
bpf/vmtest-bpf-next-VM_Test-9 | success | Logs for set-matrix |
bpf/vmtest-bpf-next-VM_Test-15 | success | Logs for x86_64-llvm-16 / veristat |
bpf/vmtest-bpf-next-VM_Test-14 | success | Logs for x86_64-llvm-16 / test |
On 11/22/23 9:40 AM, Tao Lyu wrote: > Hi Yonghong, > > Thanks for your reply. > The C inlined assembly code is attached. > I'm using clang-16, but it still fails. > > Best, > Tao > > Signed-off-by: Tao Lyu <tao.lyu@epfl.ch> > --- > .../selftests/bpf/prog_tests/verifier.c | 2 ++ > .../selftests/bpf/progs/verifier_range.c | 25 +++++++++++++++++++ > 2 files changed, 27 insertions(+) > create mode 100644 tools/testing/selftests/bpf/progs/verifier_range.c > > diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c > index e5c61aa6604a..3a5d746f392d 100644 > --- a/tools/testing/selftests/bpf/prog_tests/verifier.c > +++ b/tools/testing/selftests/bpf/prog_tests/verifier.c > @@ -77,6 +77,7 @@ > #include "verifier_xadd.skel.h" > #include "verifier_xdp.skel.h" > #include "verifier_xdp_direct_packet_access.skel.h" > +#include "verifier_range.skel.h" > > #define MAX_ENTRIES 11 > > @@ -184,6 +185,7 @@ void test_verifier_var_off(void) { RUN(verifier_var_off); } > void test_verifier_xadd(void) { RUN(verifier_xadd); } > void test_verifier_xdp(void) { RUN(verifier_xdp); } > void test_verifier_xdp_direct_packet_access(void) { RUN(verifier_xdp_direct_packet_access); } > +void test_verifier_range(void) { RUN(verifier_range); } > > static int init_test_val_map(struct bpf_object *obj, char *map_name) > { > diff --git a/tools/testing/selftests/bpf/progs/verifier_range.c b/tools/testing/selftests/bpf/progs/verifier_range.c > new file mode 100644 > index 000000000000..27597eb8135c > --- /dev/null > +++ b/tools/testing/selftests/bpf/progs/verifier_range.c > @@ -0,0 +1,25 @@ > +#include <linux/bpf.h> > +#include <bpf/bpf_helpers.h> > +#include "bpf_misc.h" > + > +SEC("?tc") > +__log_level(2) > +int test_verifier_range(void) > +{ > + asm volatile ( > + "r5 = 100; \ > + r5 /= 3; \ > + w5 >>= 7; \ > + r5 &= -386969681; \ > + r5 -= -884670597; \ > + w0 = w5; \ > + if w0 & 0x894b6a55 goto +2; \ So actually it is 'if w0 & 0x894b6a55 goto +2' failed the compilation. Indeed, the above operation is not supported in llvm. See https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/BPF/BPFInstrFormats.td#L62-L74 the missing BPFJumpOp<0x4> which corresponds to JSET. The following llvm patch (on top of llvm-project main branch): diff --git a/llvm/lib/Target/BPF/BPFInstrFormats.td b/llvm/lib/Target/BPF/BPFInstrFormats.td index 841d97efc01c..6ed83d877ac0 100644 --- a/llvm/lib/Target/BPF/BPFInstrFormats.td +++ b/llvm/lib/Target/BPF/BPFInstrFormats.td @@ -63,6 +63,7 @@ def BPF_JA : BPFJumpOp<0x0>; def BPF_JEQ : BPFJumpOp<0x1>; def BPF_JGT : BPFJumpOp<0x2>; def BPF_JGE : BPFJumpOp<0x3>; +def BPF_JSET : BPFJumpOp<0x4>; def BPF_JNE : BPFJumpOp<0x5>; def BPF_JSGT : BPFJumpOp<0x6>; def BPF_JSGE : BPFJumpOp<0x7>; diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td index 305cbbd34d27..9e75f35efe70 100644 --- a/llvm/lib/Target/BPF/BPFInstrInfo.td +++ b/llvm/lib/Target/BPF/BPFInstrInfo.td @@ -246,6 +246,70 @@ class JMP_RI_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond> let BPFClass = BPF_JMP32; } +class JSET_RR<string OpcodeStr> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value, + (outs), + (ins GPR:$dst, GPR:$src, brtarget:$BrDst), + "if $dst "#OpcodeStr#" $src goto $BrDst", + []> { + bits<4> dst; + bits<4> src; + bits<16> BrDst; + + let Inst{55-52} = src; + let Inst{51-48} = dst; + let Inst{47-32} = BrDst; + let BPFClass = BPF_JMP; +} + +class JSET_RI<string OpcodeStr> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value, + (outs), + (ins GPR:$dst, i64imm:$imm, brtarget:$BrDst), + "if $dst "#OpcodeStr#" $imm goto $BrDst", + []> { + bits<4> dst; + bits<16> BrDst; + bits<32> imm; + + let Inst{51-48} = dst; + let Inst{47-32} = BrDst; + let Inst{31-0} = imm; + let BPFClass = BPF_JMP; +} + +class JSET_RR_32<string OpcodeStr> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value, + (outs), + (ins GPR32:$dst, GPR32:$src, brtarget:$BrDst), + "if $dst "#OpcodeStr#" $src goto $BrDst", + []> { + bits<4> dst; + bits<4> src; + bits<16> BrDst; + + let Inst{55-52} = src; + let Inst{51-48} = dst; + let Inst{47-32} = BrDst; + let BPFClass = BPF_JMP32; +} + +class JSET_RI_32<string OpcodeStr> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value, + (outs), + (ins GPR32:$dst, i32imm:$imm, brtarget:$BrDst), + "if $dst "#OpcodeStr#" $imm goto $BrDst", + []> { + bits<4> dst; + bits<16> BrDst; + bits<32> imm; + + let Inst{51-48} = dst; + let Inst{47-32} = BrDst; + let Inst{31-0} = imm; + let BPFClass = BPF_JMP32; +} + multiclass J<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond, PatLeaf Cond32> { def _rr : JMP_RR<Opc, OpcodeStr, Cond>; def _ri : JMP_RI<Opc, OpcodeStr, Cond>; @@ -265,6 +329,10 @@ defm JULT : J<BPF_JLT, "<", BPF_CC_LTU, BPF_CC_LTU_32>; defm JULE : J<BPF_JLE, "<=", BPF_CC_LEU, BPF_CC_LEU_32>; defm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT, BPF_CC_LT_32>; defm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE, BPF_CC_LE_32>; +def JSET_RR : JSET_RR<"&">; +def JSET_RI : JSET_RI<"&">; +def JSET_RR_32 : JSET_RR_32<"&">; +def JSET_RI_32 : JSET_RI_32<"&">; } // ALU instructions can solve your inline asm issue. We will discuss whether llvm compiler should be implementing this instruction from source or not. > + r2 = 1; \ > + r2 = 1; \ > + r0 = 0; \ > + " > + ); > + return 0; > +} > + > +char _license[] SEC("license") = "GPL";
On Wed, Nov 22, 2023 at 10:08 AM Yonghong Song <yonghong.song@linux.dev> wrote: > > > +SEC("?tc") > > +__log_level(2) > > +int test_verifier_range(void) > > +{ > > + asm volatile ( > > + "r5 = 100; \ > > + r5 /= 3; \ > > + w5 >>= 7; \ > > + r5 &= -386969681; \ > > + r5 -= -884670597; \ > > + w0 = w5; \ > > + if w0 & 0x894b6a55 goto +2; \ > > So actually it is 'if w0 & 0x894b6a55 goto +2' failed > the compilation. > > Indeed, the above operation is not supported in llvm. > See > https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/BPF/BPFInstrFormats.td#L62-L74 > the missing BPFJumpOp<0x4> which corresponds to JSET. > > The following llvm patch (on top of llvm-project main branch): > > diff --git a/llvm/lib/Target/BPF/BPFInstrFormats.td b/llvm/lib/Target/BPF/BPFInstrFormats.td > index 841d97efc01c..6ed83d877ac0 100644 > --- a/llvm/lib/Target/BPF/BPFInstrFormats.td > +++ b/llvm/lib/Target/BPF/BPFInstrFormats.td > @@ -63,6 +63,7 @@ def BPF_JA : BPFJumpOp<0x0>; > def BPF_JEQ : BPFJumpOp<0x1>; > def BPF_JGT : BPFJumpOp<0x2>; > def BPF_JGE : BPFJumpOp<0x3>; > +def BPF_JSET : BPFJumpOp<0x4>; > def BPF_JNE : BPFJumpOp<0x5>; > def BPF_JSGT : BPFJumpOp<0x6>; > def BPF_JSGE : BPFJumpOp<0x7>; > diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td > index 305cbbd34d27..9e75f35efe70 100644 > --- a/llvm/lib/Target/BPF/BPFInstrInfo.td > +++ b/llvm/lib/Target/BPF/BPFInstrInfo.td > @@ -246,6 +246,70 @@ class JMP_RI_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond> > let BPFClass = BPF_JMP32; > } > > +class JSET_RR<string OpcodeStr> > + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value, > + (outs), > + (ins GPR:$dst, GPR:$src, brtarget:$BrDst), > + "if $dst "#OpcodeStr#" $src goto $BrDst", > + []> { > + bits<4> dst; > + bits<4> src; > + bits<16> BrDst; > + > + let Inst{55-52} = src; > + let Inst{51-48} = dst; > + let Inst{47-32} = BrDst; > + let BPFClass = BPF_JMP; > +} > + > +class JSET_RI<string OpcodeStr> > + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value, > + (outs), > + (ins GPR:$dst, i64imm:$imm, brtarget:$BrDst), > + "if $dst "#OpcodeStr#" $imm goto $BrDst", > + []> { > + bits<4> dst; > + bits<16> BrDst; > + bits<32> imm; > + > + let Inst{51-48} = dst; > + let Inst{47-32} = BrDst; > + let Inst{31-0} = imm; > + let BPFClass = BPF_JMP; > +} > + > +class JSET_RR_32<string OpcodeStr> > + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value, > + (outs), > + (ins GPR32:$dst, GPR32:$src, brtarget:$BrDst), > + "if $dst "#OpcodeStr#" $src goto $BrDst", > + []> { > + bits<4> dst; > + bits<4> src; > + bits<16> BrDst; > + > + let Inst{55-52} = src; > + let Inst{51-48} = dst; > + let Inst{47-32} = BrDst; > + let BPFClass = BPF_JMP32; > +} > + > +class JSET_RI_32<string OpcodeStr> > + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value, > + (outs), > + (ins GPR32:$dst, i32imm:$imm, brtarget:$BrDst), > + "if $dst "#OpcodeStr#" $imm goto $BrDst", > + []> { > + bits<4> dst; > + bits<16> BrDst; > + bits<32> imm; > + > + let Inst{51-48} = dst; > + let Inst{47-32} = BrDst; > + let Inst{31-0} = imm; > + let BPFClass = BPF_JMP32; > +} > + > multiclass J<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond, PatLeaf Cond32> { > def _rr : JMP_RR<Opc, OpcodeStr, Cond>; > def _ri : JMP_RI<Opc, OpcodeStr, Cond>; > @@ -265,6 +329,10 @@ defm JULT : J<BPF_JLT, "<", BPF_CC_LTU, BPF_CC_LTU_32>; > defm JULE : J<BPF_JLE, "<=", BPF_CC_LEU, BPF_CC_LEU_32>; > defm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT, BPF_CC_LT_32>; > defm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE, BPF_CC_LE_32>; > +def JSET_RR : JSET_RR<"&">; > +def JSET_RI : JSET_RI<"&">; > +def JSET_RR_32 : JSET_RR_32<"&">; > +def JSET_RI_32 : JSET_RI_32<"&">; > } > > // ALU instructions > > can solve your inline asm issue. We will discuss whether llvm compiler > should be implementing this instruction from source or not. I'd say 'yes'. clang/llvm should support such asm syntax. Jose, Eduard, Thoughts?
> On Wed, Nov 22, 2023 at 10:08 AM Yonghong Song <yonghong.song@linux.dev> wrote: >> >> > +SEC("?tc") >> > +__log_level(2) >> > +int test_verifier_range(void) >> > +{ >> > + asm volatile ( >> > + "r5 = 100; \ >> > + r5 /= 3; \ >> > + w5 >>= 7; \ >> > + r5 &= -386969681; \ >> > + r5 -= -884670597; \ >> > + w0 = w5; \ >> > + if w0 & 0x894b6a55 goto +2; \ >> >> So actually it is 'if w0 & 0x894b6a55 goto +2' failed >> the compilation. >> >> Indeed, the above operation is not supported in llvm. >> See >> https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/BPF/BPFInstrFormats.td#L62-L74 >> the missing BPFJumpOp<0x4> which corresponds to JSET. >> >> The following llvm patch (on top of llvm-project main branch): >> >> diff --git a/llvm/lib/Target/BPF/BPFInstrFormats.td b/llvm/lib/Target/BPF/BPFInstrFormats.td >> index 841d97efc01c..6ed83d877ac0 100644 >> --- a/llvm/lib/Target/BPF/BPFInstrFormats.td >> +++ b/llvm/lib/Target/BPF/BPFInstrFormats.td >> @@ -63,6 +63,7 @@ def BPF_JA : BPFJumpOp<0x0>; >> def BPF_JEQ : BPFJumpOp<0x1>; >> def BPF_JGT : BPFJumpOp<0x2>; >> def BPF_JGE : BPFJumpOp<0x3>; >> +def BPF_JSET : BPFJumpOp<0x4>; >> def BPF_JNE : BPFJumpOp<0x5>; >> def BPF_JSGT : BPFJumpOp<0x6>; >> def BPF_JSGE : BPFJumpOp<0x7>; >> diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td >> index 305cbbd34d27..9e75f35efe70 100644 >> --- a/llvm/lib/Target/BPF/BPFInstrInfo.td >> +++ b/llvm/lib/Target/BPF/BPFInstrInfo.td >> @@ -246,6 +246,70 @@ class JMP_RI_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond> >> let BPFClass = BPF_JMP32; >> } >> >> +class JSET_RR<string OpcodeStr> >> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value, >> + (outs), >> + (ins GPR:$dst, GPR:$src, brtarget:$BrDst), >> + "if $dst "#OpcodeStr#" $src goto $BrDst", >> + []> { >> + bits<4> dst; >> + bits<4> src; >> + bits<16> BrDst; >> + >> + let Inst{55-52} = src; >> + let Inst{51-48} = dst; >> + let Inst{47-32} = BrDst; >> + let BPFClass = BPF_JMP; >> +} >> + >> +class JSET_RI<string OpcodeStr> >> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value, >> + (outs), >> + (ins GPR:$dst, i64imm:$imm, brtarget:$BrDst), >> + "if $dst "#OpcodeStr#" $imm goto $BrDst", >> + []> { >> + bits<4> dst; >> + bits<16> BrDst; >> + bits<32> imm; >> + >> + let Inst{51-48} = dst; >> + let Inst{47-32} = BrDst; >> + let Inst{31-0} = imm; >> + let BPFClass = BPF_JMP; >> +} >> + >> +class JSET_RR_32<string OpcodeStr> >> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value, >> + (outs), >> + (ins GPR32:$dst, GPR32:$src, brtarget:$BrDst), >> + "if $dst "#OpcodeStr#" $src goto $BrDst", >> + []> { >> + bits<4> dst; >> + bits<4> src; >> + bits<16> BrDst; >> + >> + let Inst{55-52} = src; >> + let Inst{51-48} = dst; >> + let Inst{47-32} = BrDst; >> + let BPFClass = BPF_JMP32; >> +} >> + >> +class JSET_RI_32<string OpcodeStr> >> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value, >> + (outs), >> + (ins GPR32:$dst, i32imm:$imm, brtarget:$BrDst), >> + "if $dst "#OpcodeStr#" $imm goto $BrDst", >> + []> { >> + bits<4> dst; >> + bits<16> BrDst; >> + bits<32> imm; >> + >> + let Inst{51-48} = dst; >> + let Inst{47-32} = BrDst; >> + let Inst{31-0} = imm; >> + let BPFClass = BPF_JMP32; >> +} >> + >> multiclass J<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond, PatLeaf Cond32> { >> def _rr : JMP_RR<Opc, OpcodeStr, Cond>; >> def _ri : JMP_RI<Opc, OpcodeStr, Cond>; >> @@ -265,6 +329,10 @@ defm JULT : J<BPF_JLT, "<", BPF_CC_LTU, BPF_CC_LTU_32>; >> defm JULE : J<BPF_JLE, "<=", BPF_CC_LEU, BPF_CC_LEU_32>; >> defm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT, BPF_CC_LT_32>; >> defm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE, BPF_CC_LE_32>; >> +def JSET_RR : JSET_RR<"&">; >> +def JSET_RI : JSET_RI<"&">; >> +def JSET_RR_32 : JSET_RR_32<"&">; >> +def JSET_RI_32 : JSET_RI_32<"&">; >> } >> >> // ALU instructions >> >> can solve your inline asm issue. We will discuss whether llvm compiler >> should be implementing this instruction from source or not. > > I'd say 'yes'. clang/llvm should support such asm syntax. > > Jose, Eduard, > Thoughts? We already support it in GAS: $ echo 'if w0 & 0x894b6a55 goto +2' | bpf-unknown-none-as -mdialect=pseudoc - $ bpf-unknown-none-objdump -M hex,pseudoc -d a.out a.out: file format elf64-bpfle Disassembly of section .text: 0000000000000000 <.text>: 0: 46 00 02 00 55 6a 4b 89 if w0&0x894b6a55 goto 0x2 We weren't aware we were diverging with llvm by doing so. We support syntax for all the conditional jump instructions using the following operators: BPF_JEQ == BPF_JGT > BPF_JSGT s> BPF_JGE >= BPF_JSGE s>= BPF_JLT < BPF_JLST s< BPF_JLE <= BPF_JSLE s<= BPF_JSET & BPF_JNE !=
On Wed, 2023-11-22 at 10:15 -0800, Alexei Starovoitov wrote: [...] > > multiclass J<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond, PatLeaf Cond32> { > > def _rr : JMP_RR<Opc, OpcodeStr, Cond>; > > def _ri : JMP_RI<Opc, OpcodeStr, Cond>; > > @@ -265,6 +329,10 @@ defm JULT : J<BPF_JLT, "<", BPF_CC_LTU, BPF_CC_LTU_32>; > > defm JULE : J<BPF_JLE, "<=", BPF_CC_LEU, BPF_CC_LEU_32>; > > defm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT, BPF_CC_LT_32>; > > defm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE, BPF_CC_LE_32>; > > +def JSET_RR : JSET_RR<"&">; > > +def JSET_RI : JSET_RI<"&">; > > +def JSET_RR_32 : JSET_RR_32<"&">; > > +def JSET_RI_32 : JSET_RI_32<"&">; > > } > > > > // ALU instructions > > > > can solve your inline asm issue. We will discuss whether llvm compiler > > should be implementing this instruction from source or not. > > I'd say 'yes'. clang/llvm should support such asm syntax. > > Jose, Eduard, > Thoughts? I agree, since instruction is documented it should have assembly representation. All other instructions from instruction-set.rst seem to have one.
On 11/22/23 1:37 PM, Jose E. Marchesi wrote: >> On Wed, Nov 22, 2023 at 10:08 AM Yonghong Song <yonghong.song@linux.dev> wrote: >>>> +SEC("?tc") >>>> +__log_level(2) >>>> +int test_verifier_range(void) >>>> +{ >>>> + asm volatile ( >>>> + "r5 = 100; \ >>>> + r5 /= 3; \ >>>> + w5 >>= 7; \ >>>> + r5 &= -386969681; \ >>>> + r5 -= -884670597; \ >>>> + w0 = w5; \ >>>> + if w0 & 0x894b6a55 goto +2; \ >>> So actually it is 'if w0 & 0x894b6a55 goto +2' failed >>> the compilation. >>> >>> Indeed, the above operation is not supported in llvm. >>> See >>> https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/BPF/BPFInstrFormats.td#L62-L74 >>> the missing BPFJumpOp<0x4> which corresponds to JSET. >>> >>> The following llvm patch (on top of llvm-project main branch): >>> >>> diff --git a/llvm/lib/Target/BPF/BPFInstrFormats.td b/llvm/lib/Target/BPF/BPFInstrFormats.td >>> index 841d97efc01c..6ed83d877ac0 100644 >>> --- a/llvm/lib/Target/BPF/BPFInstrFormats.td >>> +++ b/llvm/lib/Target/BPF/BPFInstrFormats.td >>> @@ -63,6 +63,7 @@ def BPF_JA : BPFJumpOp<0x0>; >>> def BPF_JEQ : BPFJumpOp<0x1>; >>> def BPF_JGT : BPFJumpOp<0x2>; >>> def BPF_JGE : BPFJumpOp<0x3>; >>> +def BPF_JSET : BPFJumpOp<0x4>; >>> def BPF_JNE : BPFJumpOp<0x5>; >>> def BPF_JSGT : BPFJumpOp<0x6>; >>> def BPF_JSGE : BPFJumpOp<0x7>; >>> diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td >>> index 305cbbd34d27..9e75f35efe70 100644 >>> --- a/llvm/lib/Target/BPF/BPFInstrInfo.td >>> +++ b/llvm/lib/Target/BPF/BPFInstrInfo.td >>> @@ -246,6 +246,70 @@ class JMP_RI_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond> >>> let BPFClass = BPF_JMP32; >>> } >>> >>> +class JSET_RR<string OpcodeStr> >>> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value, >>> + (outs), >>> + (ins GPR:$dst, GPR:$src, brtarget:$BrDst), >>> + "if $dst "#OpcodeStr#" $src goto $BrDst", >>> + []> { >>> + bits<4> dst; >>> + bits<4> src; >>> + bits<16> BrDst; >>> + >>> + let Inst{55-52} = src; >>> + let Inst{51-48} = dst; >>> + let Inst{47-32} = BrDst; >>> + let BPFClass = BPF_JMP; >>> +} >>> + >>> +class JSET_RI<string OpcodeStr> >>> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value, >>> + (outs), >>> + (ins GPR:$dst, i64imm:$imm, brtarget:$BrDst), >>> + "if $dst "#OpcodeStr#" $imm goto $BrDst", >>> + []> { >>> + bits<4> dst; >>> + bits<16> BrDst; >>> + bits<32> imm; >>> + >>> + let Inst{51-48} = dst; >>> + let Inst{47-32} = BrDst; >>> + let Inst{31-0} = imm; >>> + let BPFClass = BPF_JMP; >>> +} >>> + >>> +class JSET_RR_32<string OpcodeStr> >>> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value, >>> + (outs), >>> + (ins GPR32:$dst, GPR32:$src, brtarget:$BrDst), >>> + "if $dst "#OpcodeStr#" $src goto $BrDst", >>> + []> { >>> + bits<4> dst; >>> + bits<4> src; >>> + bits<16> BrDst; >>> + >>> + let Inst{55-52} = src; >>> + let Inst{51-48} = dst; >>> + let Inst{47-32} = BrDst; >>> + let BPFClass = BPF_JMP32; >>> +} >>> + >>> +class JSET_RI_32<string OpcodeStr> >>> + : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value, >>> + (outs), >>> + (ins GPR32:$dst, i32imm:$imm, brtarget:$BrDst), >>> + "if $dst "#OpcodeStr#" $imm goto $BrDst", >>> + []> { >>> + bits<4> dst; >>> + bits<16> BrDst; >>> + bits<32> imm; >>> + >>> + let Inst{51-48} = dst; >>> + let Inst{47-32} = BrDst; >>> + let Inst{31-0} = imm; >>> + let BPFClass = BPF_JMP32; >>> +} >>> + >>> multiclass J<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond, PatLeaf Cond32> { >>> def _rr : JMP_RR<Opc, OpcodeStr, Cond>; >>> def _ri : JMP_RI<Opc, OpcodeStr, Cond>; >>> @@ -265,6 +329,10 @@ defm JULT : J<BPF_JLT, "<", BPF_CC_LTU, BPF_CC_LTU_32>; >>> defm JULE : J<BPF_JLE, "<=", BPF_CC_LEU, BPF_CC_LEU_32>; >>> defm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT, BPF_CC_LT_32>; >>> defm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE, BPF_CC_LE_32>; >>> +def JSET_RR : JSET_RR<"&">; >>> +def JSET_RI : JSET_RI<"&">; >>> +def JSET_RR_32 : JSET_RR_32<"&">; >>> +def JSET_RI_32 : JSET_RI_32<"&">; >>> } >>> >>> // ALU instructions >>> >>> can solve your inline asm issue. We will discuss whether llvm compiler >>> should be implementing this instruction from source or not. >> I'd say 'yes'. clang/llvm should support such asm syntax. >> >> Jose, Eduard, >> Thoughts? > We already support it in GAS: > > > $ echo 'if w0 & 0x894b6a55 goto +2' | bpf-unknown-none-as -mdialect=pseudoc - > $ bpf-unknown-none-objdump -M hex,pseudoc -d a.out > > a.out: file format elf64-bpfle > > > Disassembly of section .text: > > 0000000000000000 <.text>: > 0: 46 00 02 00 55 6a 4b 89 if w0&0x894b6a55 goto 0x2 > > > We weren't aware we were diverging with llvm by doing so. We support > syntax for all the conditional jump instructions using the following > operators: > > BPF_JEQ == > BPF_JGT > > BPF_JSGT s> > BPF_JGE >= > BPF_JSGE s>= > BPF_JLT < > BPF_JLST s< > BPF_JLE <= > BPF_JSLE s<= > BPF_JSET & > BPF_JNE != Sounds good. Eduard inthe other thread has similar opinion. Will add asm support in llvm soon.
diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c index e5c61aa6604a..3a5d746f392d 100644 --- a/tools/testing/selftests/bpf/prog_tests/verifier.c +++ b/tools/testing/selftests/bpf/prog_tests/verifier.c @@ -77,6 +77,7 @@ #include "verifier_xadd.skel.h" #include "verifier_xdp.skel.h" #include "verifier_xdp_direct_packet_access.skel.h" +#include "verifier_range.skel.h" #define MAX_ENTRIES 11 @@ -184,6 +185,7 @@ void test_verifier_var_off(void) { RUN(verifier_var_off); } void test_verifier_xadd(void) { RUN(verifier_xadd); } void test_verifier_xdp(void) { RUN(verifier_xdp); } void test_verifier_xdp_direct_packet_access(void) { RUN(verifier_xdp_direct_packet_access); } +void test_verifier_range(void) { RUN(verifier_range); } static int init_test_val_map(struct bpf_object *obj, char *map_name) { diff --git a/tools/testing/selftests/bpf/progs/verifier_range.c b/tools/testing/selftests/bpf/progs/verifier_range.c new file mode 100644 index 000000000000..27597eb8135c --- /dev/null +++ b/tools/testing/selftests/bpf/progs/verifier_range.c @@ -0,0 +1,25 @@ +#include <linux/bpf.h> +#include <bpf/bpf_helpers.h> +#include "bpf_misc.h" + +SEC("?tc") +__log_level(2) +int test_verifier_range(void) +{ + asm volatile ( + "r5 = 100; \ + r5 /= 3; \ + w5 >>= 7; \ + r5 &= -386969681; \ + r5 -= -884670597; \ + w0 = w5; \ + if w0 & 0x894b6a55 goto +2; \ + r2 = 1; \ + r2 = 1; \ + r0 = 0; \ + " + ); + return 0; +} + +char _license[] SEC("license") = "GPL";
Hi Yonghong, Thanks for your reply. The C inlined assembly code is attached. I'm using clang-16, but it still fails. Best, Tao Signed-off-by: Tao Lyu <tao.lyu@epfl.ch> --- .../selftests/bpf/prog_tests/verifier.c | 2 ++ .../selftests/bpf/progs/verifier_range.c | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/verifier_range.c