Commit 7ba4f43e authored by Ilya Leoshkevich's avatar Ilya Leoshkevich Committed by Daniel Borkmann

s390/bpf: Change seen_reg to a mask

Using a mask instead of an array saves a small amount of memory and
allows marking multiple registers as seen with a simple "or". Another
positive side-effect is that it speeds up verification with jitterbug.
Signed-off-by: default avatarIlya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20240703005047.40915-2-iii@linux.ibm.com
parent bc239eb2
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
struct bpf_jit { struct bpf_jit {
u32 seen; /* Flags to remember seen eBPF instructions */ u32 seen; /* Flags to remember seen eBPF instructions */
u32 seen_reg[16]; /* Array to remember which registers are used */ u16 seen_regs; /* Mask to remember which registers are used */
u32 *addrs; /* Array with relative instruction addresses */ u32 *addrs; /* Array with relative instruction addresses */
u8 *prg_buf; /* Start of program */ u8 *prg_buf; /* Start of program */
int size; /* Size of program and literal pool */ int size; /* Size of program and literal pool */
...@@ -120,8 +120,8 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1) ...@@ -120,8 +120,8 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
{ {
u32 r1 = reg2hex[b1]; u32 r1 = reg2hex[b1];
if (r1 >= 6 && r1 <= 15 && !jit->seen_reg[r1]) if (r1 >= 6 && r1 <= 15)
jit->seen_reg[r1] = 1; jit->seen_regs |= (1 << r1);
} }
#define REG_SET_SEEN(b1) \ #define REG_SET_SEEN(b1) \
...@@ -129,8 +129,6 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1) ...@@ -129,8 +129,6 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
reg_set_seen(jit, b1); \ reg_set_seen(jit, b1); \
}) })
#define REG_SEEN(b1) jit->seen_reg[reg2hex[(b1)]]
/* /*
* EMIT macros for code generation * EMIT macros for code generation
*/ */
...@@ -438,12 +436,12 @@ static void restore_regs(struct bpf_jit *jit, u32 rs, u32 re, u32 stack_depth) ...@@ -438,12 +436,12 @@ static void restore_regs(struct bpf_jit *jit, u32 rs, u32 re, u32 stack_depth)
/* /*
* Return first seen register (from start) * Return first seen register (from start)
*/ */
static int get_start(struct bpf_jit *jit, int start) static int get_start(u16 seen_regs, int start)
{ {
int i; int i;
for (i = start; i <= 15; i++) { for (i = start; i <= 15; i++) {
if (jit->seen_reg[i]) if (seen_regs & (1 << i))
return i; return i;
} }
return 0; return 0;
...@@ -452,15 +450,15 @@ static int get_start(struct bpf_jit *jit, int start) ...@@ -452,15 +450,15 @@ static int get_start(struct bpf_jit *jit, int start)
/* /*
* Return last seen register (from start) (gap >= 2) * Return last seen register (from start) (gap >= 2)
*/ */
static int get_end(struct bpf_jit *jit, int start) static int get_end(u16 seen_regs, int start)
{ {
int i; int i;
for (i = start; i < 15; i++) { for (i = start; i < 15; i++) {
if (!jit->seen_reg[i] && !jit->seen_reg[i + 1]) if (!(seen_regs & (3 << i)))
return i - 1; return i - 1;
} }
return jit->seen_reg[15] ? 15 : 14; return (seen_regs & (1 << 15)) ? 15 : 14;
} }
#define REGS_SAVE 1 #define REGS_SAVE 1
...@@ -469,8 +467,10 @@ static int get_end(struct bpf_jit *jit, int start) ...@@ -469,8 +467,10 @@ static int get_end(struct bpf_jit *jit, int start)
* Save and restore clobbered registers (6-15) on stack. * Save and restore clobbered registers (6-15) on stack.
* We save/restore registers in chunks with gap >= 2 registers. * We save/restore registers in chunks with gap >= 2 registers.
*/ */
static void save_restore_regs(struct bpf_jit *jit, int op, u32 stack_depth) static void save_restore_regs(struct bpf_jit *jit, int op, u32 stack_depth,
u16 extra_regs)
{ {
u16 seen_regs = jit->seen_regs | extra_regs;
const int last = 15, save_restore_size = 6; const int last = 15, save_restore_size = 6;
int re = 6, rs; int re = 6, rs;
...@@ -484,10 +484,10 @@ static void save_restore_regs(struct bpf_jit *jit, int op, u32 stack_depth) ...@@ -484,10 +484,10 @@ static void save_restore_regs(struct bpf_jit *jit, int op, u32 stack_depth)
} }
do { do {
rs = get_start(jit, re); rs = get_start(seen_regs, re);
if (!rs) if (!rs)
break; break;
re = get_end(jit, rs + 1); re = get_end(seen_regs, rs + 1);
if (op == REGS_SAVE) if (op == REGS_SAVE)
save_regs(jit, rs, re); save_regs(jit, rs, re);
else else
...@@ -573,7 +573,7 @@ static void bpf_jit_prologue(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -573,7 +573,7 @@ static void bpf_jit_prologue(struct bpf_jit *jit, struct bpf_prog *fp,
/* Tail calls have to skip above initialization */ /* Tail calls have to skip above initialization */
jit->tail_call_start = jit->prg; jit->tail_call_start = jit->prg;
/* Save registers */ /* Save registers */
save_restore_regs(jit, REGS_SAVE, stack_depth); save_restore_regs(jit, REGS_SAVE, stack_depth, 0);
/* Setup literal pool */ /* Setup literal pool */
if (is_first_pass(jit) || (jit->seen & SEEN_LITERAL)) { if (is_first_pass(jit) || (jit->seen & SEEN_LITERAL)) {
if (!is_first_pass(jit) && if (!is_first_pass(jit) &&
...@@ -649,7 +649,7 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth) ...@@ -649,7 +649,7 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth)
/* Load exit code: lgr %r2,%b0 */ /* Load exit code: lgr %r2,%b0 */
EMIT4(0xb9040000, REG_2, BPF_REG_0); EMIT4(0xb9040000, REG_2, BPF_REG_0);
/* Restore registers */ /* Restore registers */
save_restore_regs(jit, REGS_RESTORE, stack_depth); save_restore_regs(jit, REGS_RESTORE, stack_depth, 0);
if (nospec_uses_trampoline()) { if (nospec_uses_trampoline()) {
jit->r14_thunk_ip = jit->prg; jit->r14_thunk_ip = jit->prg;
/* Generate __s390_indirect_jump_r14 thunk */ /* Generate __s390_indirect_jump_r14 thunk */
...@@ -1847,7 +1847,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, ...@@ -1847,7 +1847,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
/* /*
* Restore registers before calling function * Restore registers before calling function
*/ */
save_restore_regs(jit, REGS_RESTORE, stack_depth); save_restore_regs(jit, REGS_RESTORE, stack_depth, 0);
/* /*
* goto *(prog->bpf_func + tail_call_start); * goto *(prog->bpf_func + tail_call_start);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment