diff options
author | Michael Holzheu <holzheu@linux.vnet.ibm.com> | 2015-04-27 05:12:25 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2015-04-30 07:50:34 -0400 |
commit | 771aada9ace7e5dd837a69ef0bca08b5455b2d36 (patch) | |
tree | 761f957eb0d7284e4e3e5b549f8ae4d2c57afc0a /arch/s390/net | |
parent | 3d99e3fe13d473ac4578c37f477a59b829530764 (diff) |
s390/bpf: Adjust ALU64_DIV/MOD to match interpreter change
The s390x ALU64_DIV/MOD has been implemented according to the eBPF
interpreter specification that used do_div(). This function does a 64-bit
by 32-bit divide. It turned out that this was wrong and now the interpreter
uses div64_u64_rem() for full 64-bit division.
So fix this and use full 64-bit division in the s390x eBPF backend code.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/net')
-rw-r--r-- | arch/s390/net/bpf_jit_comp.c | 14 |
1 files changed, 6 insertions, 8 deletions
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 7690dc8e1ab5..065aca02bc65 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c | |||
@@ -588,8 +588,8 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i) | |||
588 | EMIT4(0xb9160000, dst_reg, rc_reg); | 588 | EMIT4(0xb9160000, dst_reg, rc_reg); |
589 | break; | 589 | break; |
590 | } | 590 | } |
591 | case BPF_ALU64 | BPF_DIV | BPF_X: /* dst = dst / (u32) src */ | 591 | case BPF_ALU64 | BPF_DIV | BPF_X: /* dst = dst / src */ |
592 | case BPF_ALU64 | BPF_MOD | BPF_X: /* dst = dst % (u32) src */ | 592 | case BPF_ALU64 | BPF_MOD | BPF_X: /* dst = dst % src */ |
593 | { | 593 | { |
594 | int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0; | 594 | int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0; |
595 | 595 | ||
@@ -602,10 +602,8 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i) | |||
602 | EMIT4_IMM(0xa7090000, REG_W0, 0); | 602 | EMIT4_IMM(0xa7090000, REG_W0, 0); |
603 | /* lgr %w1,%dst */ | 603 | /* lgr %w1,%dst */ |
604 | EMIT4(0xb9040000, REG_W1, dst_reg); | 604 | EMIT4(0xb9040000, REG_W1, dst_reg); |
605 | /* llgfr %dst,%src (u32 cast) */ | ||
606 | EMIT4(0xb9160000, dst_reg, src_reg); | ||
607 | /* dlgr %w0,%dst */ | 605 | /* dlgr %w0,%dst */ |
608 | EMIT4(0xb9870000, REG_W0, dst_reg); | 606 | EMIT4(0xb9870000, REG_W0, src_reg); |
609 | /* lgr %dst,%rc */ | 607 | /* lgr %dst,%rc */ |
610 | EMIT4(0xb9040000, dst_reg, rc_reg); | 608 | EMIT4(0xb9040000, dst_reg, rc_reg); |
611 | break; | 609 | break; |
@@ -632,8 +630,8 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i) | |||
632 | EMIT4(0xb9160000, dst_reg, rc_reg); | 630 | EMIT4(0xb9160000, dst_reg, rc_reg); |
633 | break; | 631 | break; |
634 | } | 632 | } |
635 | case BPF_ALU64 | BPF_DIV | BPF_K: /* dst = dst / (u32) imm */ | 633 | case BPF_ALU64 | BPF_DIV | BPF_K: /* dst = dst / imm */ |
636 | case BPF_ALU64 | BPF_MOD | BPF_K: /* dst = dst % (u32) imm */ | 634 | case BPF_ALU64 | BPF_MOD | BPF_K: /* dst = dst % imm */ |
637 | { | 635 | { |
638 | int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0; | 636 | int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0; |
639 | 637 | ||
@@ -649,7 +647,7 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i) | |||
649 | EMIT4(0xb9040000, REG_W1, dst_reg); | 647 | EMIT4(0xb9040000, REG_W1, dst_reg); |
650 | /* dlg %w0,<d(imm)>(%l) */ | 648 | /* dlg %w0,<d(imm)>(%l) */ |
651 | EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0, REG_L, | 649 | EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0, REG_L, |
652 | EMIT_CONST_U64((u32) imm)); | 650 | EMIT_CONST_U64(imm)); |
653 | /* lgr %dst,%rc */ | 651 | /* lgr %dst,%rc */ |
654 | EMIT4(0xb9040000, dst_reg, rc_reg); | 652 | EMIT4(0xb9040000, dst_reg, rc_reg); |
655 | break; | 653 | break; |