Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Support new unconditional bswap instruction

The existing 'be' and 'le' insns will do conditional bswap
depends on host endianness. This patch implements
unconditional bswap insns.

Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20230728011213.3712808-1-yonghong.song@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Yonghong Song and committed by
Alexei Starovoitov
0845c3db 1f1e864b

+20 -2
+1
arch/x86/net/bpf_jit_comp.c
··· 1322 1322 break; 1323 1323 1324 1324 case BPF_ALU | BPF_END | BPF_FROM_BE: 1325 + case BPF_ALU64 | BPF_END | BPF_FROM_LE: 1325 1326 switch (imm32) { 1326 1327 case 16: 1327 1328 /* Emit 'ror %ax, 8' to swap lower 2 bytes */
+14
kernel/bpf/core.c
··· 1524 1524 INSN_3(ALU64, DIV, X), \ 1525 1525 INSN_3(ALU64, MOD, X), \ 1526 1526 INSN_2(ALU64, NEG), \ 1527 + INSN_3(ALU64, END, TO_LE), \ 1527 1528 /* Immediate based. */ \ 1528 1529 INSN_3(ALU64, ADD, K), \ 1529 1530 INSN_3(ALU64, SUB, K), \ ··· 1846 1845 break; 1847 1846 case 64: 1848 1847 DST = (__force u64) cpu_to_le64(DST); 1848 + break; 1849 + } 1850 + CONT; 1851 + ALU64_END_TO_LE: 1852 + switch (IMM) { 1853 + case 16: 1854 + DST = (__force u16) __swab16(DST); 1855 + break; 1856 + case 32: 1857 + DST = (__force u32) __swab32(DST); 1858 + break; 1859 + case 64: 1860 + DST = (__force u64) __swab64(DST); 1849 1861 break; 1850 1862 } 1851 1863 CONT;
+5 -2
kernel/bpf/verifier.c
··· 3012 3012 } 3013 3013 } 3014 3014 3015 + if (class == BPF_ALU64 && op == BPF_END && (insn->imm == 16 || insn->imm == 32)) 3016 + return false; 3017 + 3015 3018 if (class == BPF_ALU64 || class == BPF_JMP || 3016 - /* BPF_END always use BPF_ALU class. */ 3017 3019 (class == BPF_ALU && op == BPF_END && insn->imm == 64)) 3018 3020 return true; 3019 3021 ··· 13078 13076 } else { 13079 13077 if (insn->src_reg != BPF_REG_0 || insn->off != 0 || 13080 13078 (insn->imm != 16 && insn->imm != 32 && insn->imm != 64) || 13081 - BPF_CLASS(insn->code) == BPF_ALU64) { 13079 + (BPF_CLASS(insn->code) == BPF_ALU64 && 13080 + BPF_SRC(insn->code) != BPF_TO_LE)) { 13082 13081 verbose(env, "BPF_END uses reserved fields\n"); 13083 13082 return -EINVAL; 13084 13083 }