aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/net
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2015-12-17 17:51:54 -0500
committerDavid S. Miller <davem@davemloft.net>2015-12-18 16:04:51 -0500
commit8b614aebecdf2b1f72d51b1527f5a75d218b78e2 (patch)
tree4ac23e78eaa9111f694ac114b0ec04c071ab0a9e /arch/s390/net
parent05c74e5e53f6cb07502c3e6a820f33e2777b6605 (diff)
bpf: move clearing of A/X into classic to eBPF migration prologue
Back in the days where eBPF (or back then "internal BPF" ;->) was not exposed to user space, and only the classic BPF programs internally translated into eBPF programs, we missed the fact that for classic BPF A and X needed to be cleared. It was fixed back then via 83d5b7ef99c9 ("net: filter: initialize A and X registers"), and thus classic BPF specifics were added to the eBPF interpreter core to work around it. This added some confusion for JIT developers later on that take the eBPF interpreter code as an example for deriving their JIT. F.e. in f75298f5c3fe ("s390/bpf: clear correct BPF accumulator register"), at least X could leak stack memory. Furthermore, since this is only needed for classic BPF translations and not for eBPF (verifier takes care that read access to regs cannot be done uninitialized), more complexity is added to JITs as they need to determine whether they deal with migrations or native eBPF where they can just omit clearing A/X in their prologue and thus reduce image size a bit, see f.e. cde66c2d88da ("s390/bpf: Only clear A and X for converted BPF programs"). In other cases (x86, arm64), A and X is being cleared in the prologue also for eBPF case, which is unnecessary. Lets move this into the BPF migration in bpf_convert_filter() where it actually belongs as long as the number of eBPF JITs are still few. It can thus be done generically; allowing us to remove the quirk from __bpf_prog_run() and to slightly reduce JIT image size in case of eBPF, while reducing code duplication on this matter in current(/future) eBPF JITs. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Tested-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Cc: Zi Shen Lim <zlim.lnx@gmail.com> Cc: Yang Shi <yang.shi@linaro.org> Acked-by: Yang Shi <yang.shi@linaro.org> Acked-by: Zi Shen Lim <zlim.lnx@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/s390/net')
-rw-r--r--arch/s390/net/bpf_jit_comp.c13
1 files changed, 2 insertions, 11 deletions
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 9a0c4c22e536..3c0bfc1f2694 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -408,7 +408,7 @@ static void emit_load_skb_data_hlen(struct bpf_jit *jit)
408 * Save registers and create stack frame if necessary. 408 * Save registers and create stack frame if necessary.
409 * See stack frame layout desription in "bpf_jit.h"! 409 * See stack frame layout desription in "bpf_jit.h"!
410 */ 410 */
411static void bpf_jit_prologue(struct bpf_jit *jit, bool is_classic) 411static void bpf_jit_prologue(struct bpf_jit *jit)
412{ 412{
413 if (jit->seen & SEEN_TAIL_CALL) { 413 if (jit->seen & SEEN_TAIL_CALL) {
414 /* xc STK_OFF_TCCNT(4,%r15),STK_OFF_TCCNT(%r15) */ 414 /* xc STK_OFF_TCCNT(4,%r15),STK_OFF_TCCNT(%r15) */
@@ -448,15 +448,6 @@ static void bpf_jit_prologue(struct bpf_jit *jit, bool is_classic)
448 /* stg %b1,ST_OFF_SKBP(%r0,%r15) */ 448 /* stg %b1,ST_OFF_SKBP(%r0,%r15) */
449 EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15, 449 EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15,
450 STK_OFF_SKBP); 450 STK_OFF_SKBP);
451 /* Clear A (%b0) and X (%b7) registers for converted BPF programs */
452 if (is_classic) {
453 if (REG_SEEN(BPF_REG_A))
454 /* lghi %ba,0 */
455 EMIT4_IMM(0xa7090000, BPF_REG_A, 0);
456 if (REG_SEEN(BPF_REG_X))
457 /* lghi %bx,0 */
458 EMIT4_IMM(0xa7090000, BPF_REG_X, 0);
459 }
460} 451}
461 452
462/* 453/*
@@ -1245,7 +1236,7 @@ static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp)
1245 jit->lit = jit->lit_start; 1236 jit->lit = jit->lit_start;
1246 jit->prg = 0; 1237 jit->prg = 0;
1247 1238
1248 bpf_jit_prologue(jit, bpf_prog_was_classic(fp)); 1239 bpf_jit_prologue(jit);
1249 for (i = 0; i < fp->len; i += insn_count) { 1240 for (i = 0; i < fp->len; i += insn_count) {
1250 insn_count = bpf_jit_insn(jit, fp, i); 1241 insn_count = bpf_jit_insn(jit, fp, i);
1251 if (insn_count < 0) 1242 if (insn_count < 0)