All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next 0/4] RV64 BPF JIT Optimizations
@ 2020-05-06  0:03 ` Luke Nelson
  0 siblings, 0 replies; 14+ messages in thread
From: Luke Nelson @ 2020-05-06  0:03 UTC (permalink / raw)
  To: bpf
  Cc: Luke Nelson, Xi Wang, Björn Töpel, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexei Starovoitov, Daniel Borkmann,
	Martin KaFai Lau, Song Liu, Yonghong Song, Andrii Nakryiko,
	John Fastabend, KP Singh, netdev, linux-riscv, linux-kernel

This patch series introduces a set of optimizations to the BPF JIT
on RV64. The optimizations are related to the verifier zero-extension
optimization and BPF_JMP BPF_K.

We tested the optimizations on a QEMU riscv64 virt machine, using
lib/test_bpf and test_verifier, and formally verified their correctness
using Serval.

Luke Nelson (4):
  bpf, riscv: Enable missing verifier_zext optimizations on RV64
  bpf, riscv: Optimize FROM_LE using verifier_zext on RV64
  bpf, riscv: Optimize BPF_JMP BPF_K when imm == 0 on RV64
  bpf, riscv: Optimize BPF_JSET BPF_K using andi on RV64

 arch/riscv/net/bpf_jit_comp64.c | 64 ++++++++++++++++++++++-----------
 1 file changed, 44 insertions(+), 20 deletions(-)

Cc: Xi Wang <xi.wang@gmail.com>

-- 
2.17.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH bpf-next 0/4] RV64 BPF JIT Optimizations
@ 2020-05-06  0:03 ` Luke Nelson
  0 siblings, 0 replies; 14+ messages in thread
From: Luke Nelson @ 2020-05-06  0:03 UTC (permalink / raw)
  To: bpf
  Cc: Song Liu, Albert Ou, Daniel Borkmann, Luke Nelson,
	Björn Töpel, John Fastabend, Alexei Starovoitov,
	linux-kernel, netdev, Palmer Dabbelt, Paul Walmsley, KP Singh,
	Yonghong Song, linux-riscv, Andrii Nakryiko, Martin KaFai Lau,
	Xi Wang

This patch series introduces a set of optimizations to the BPF JIT
on RV64. The optimizations are related to the verifier zero-extension
optimization and BPF_JMP BPF_K.

We tested the optimizations on a QEMU riscv64 virt machine, using
lib/test_bpf and test_verifier, and formally verified their correctness
using Serval.

Luke Nelson (4):
  bpf, riscv: Enable missing verifier_zext optimizations on RV64
  bpf, riscv: Optimize FROM_LE using verifier_zext on RV64
  bpf, riscv: Optimize BPF_JMP BPF_K when imm == 0 on RV64
  bpf, riscv: Optimize BPF_JSET BPF_K using andi on RV64

 arch/riscv/net/bpf_jit_comp64.c | 64 ++++++++++++++++++++++-----------
 1 file changed, 44 insertions(+), 20 deletions(-)

Cc: Xi Wang <xi.wang@gmail.com>

-- 
2.17.1



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH bpf-next 1/4] bpf, riscv: Enable missing verifier_zext optimizations on RV64
  2020-05-06  0:03 ` Luke Nelson
@ 2020-05-06  0:03   ` Luke Nelson
  -1 siblings, 0 replies; 14+ messages in thread
From: Luke Nelson @ 2020-05-06  0:03 UTC (permalink / raw)
  To: bpf
  Cc: Luke Nelson, Xi Wang, Björn Töpel, Alexei Starovoitov,
	Daniel Borkmann, Martin KaFai Lau, Song Liu, Yonghong Song,
	Andrii Nakryiko, John Fastabend, KP Singh, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, netdev, linux-riscv, linux-kernel

Commit 66d0d5a854a6 ("riscv: bpf: eliminate zero extension code-gen")
added support for the verifier zero-extension optimization on RV64 and
commit 46dd3d7d287b ("bpf, riscv: Enable zext optimization for more
RV64G ALU ops") enabled it for more instruction cases.

However, BPF_LSH BPF_X and BPF_{LSH,RSH,ARSH} BPF_K are still missing
the optimization.

This patch enables the zero-extension optimization for these remaining
cases.

Co-developed-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
---
 arch/riscv/net/bpf_jit_comp64.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index d208a9fd6c52..e2636902a74e 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -515,7 +515,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 	case BPF_ALU | BPF_LSH | BPF_X:
 	case BPF_ALU64 | BPF_LSH | BPF_X:
 		emit(is64 ? rv_sll(rd, rd, rs) : rv_sllw(rd, rd, rs), ctx);
-		if (!is64)
+		if (!is64 && !aux->verifier_zext)
 			emit_zext_32(rd, ctx);
 		break;
 	case BPF_ALU | BPF_RSH | BPF_X:
@@ -692,19 +692,19 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 	case BPF_ALU | BPF_LSH | BPF_K:
 	case BPF_ALU64 | BPF_LSH | BPF_K:
 		emit(is64 ? rv_slli(rd, rd, imm) : rv_slliw(rd, rd, imm), ctx);
-		if (!is64)
+		if (!is64 && !aux->verifier_zext)
 			emit_zext_32(rd, ctx);
 		break;
 	case BPF_ALU | BPF_RSH | BPF_K:
 	case BPF_ALU64 | BPF_RSH | BPF_K:
 		emit(is64 ? rv_srli(rd, rd, imm) : rv_srliw(rd, rd, imm), ctx);
-		if (!is64)
+		if (!is64 && !aux->verifier_zext)
 			emit_zext_32(rd, ctx);
 		break;
 	case BPF_ALU | BPF_ARSH | BPF_K:
 	case BPF_ALU64 | BPF_ARSH | BPF_K:
 		emit(is64 ? rv_srai(rd, rd, imm) : rv_sraiw(rd, rd, imm), ctx);
-		if (!is64)
+		if (!is64 && !aux->verifier_zext)
 			emit_zext_32(rd, ctx);
 		break;
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH bpf-next 1/4] bpf, riscv: Enable missing verifier_zext optimizations on RV64
@ 2020-05-06  0:03   ` Luke Nelson
  0 siblings, 0 replies; 14+ messages in thread
From: Luke Nelson @ 2020-05-06  0:03 UTC (permalink / raw)
  To: bpf
  Cc: Song Liu, Albert Ou, Daniel Borkmann, Luke Nelson,
	Björn Töpel, John Fastabend, Alexei Starovoitov,
	linux-kernel, netdev, Palmer Dabbelt, Paul Walmsley, KP Singh,
	Yonghong Song, linux-riscv, Andrii Nakryiko, Martin KaFai Lau,
	Xi Wang

Commit 66d0d5a854a6 ("riscv: bpf: eliminate zero extension code-gen")
added support for the verifier zero-extension optimization on RV64 and
commit 46dd3d7d287b ("bpf, riscv: Enable zext optimization for more
RV64G ALU ops") enabled it for more instruction cases.

However, BPF_LSH BPF_X and BPF_{LSH,RSH,ARSH} BPF_K are still missing
the optimization.

This patch enables the zero-extension optimization for these remaining
cases.

Co-developed-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
---
 arch/riscv/net/bpf_jit_comp64.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index d208a9fd6c52..e2636902a74e 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -515,7 +515,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 	case BPF_ALU | BPF_LSH | BPF_X:
 	case BPF_ALU64 | BPF_LSH | BPF_X:
 		emit(is64 ? rv_sll(rd, rd, rs) : rv_sllw(rd, rd, rs), ctx);
-		if (!is64)
+		if (!is64 && !aux->verifier_zext)
 			emit_zext_32(rd, ctx);
 		break;
 	case BPF_ALU | BPF_RSH | BPF_X:
@@ -692,19 +692,19 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 	case BPF_ALU | BPF_LSH | BPF_K:
 	case BPF_ALU64 | BPF_LSH | BPF_K:
 		emit(is64 ? rv_slli(rd, rd, imm) : rv_slliw(rd, rd, imm), ctx);
-		if (!is64)
+		if (!is64 && !aux->verifier_zext)
 			emit_zext_32(rd, ctx);
 		break;
 	case BPF_ALU | BPF_RSH | BPF_K:
 	case BPF_ALU64 | BPF_RSH | BPF_K:
 		emit(is64 ? rv_srli(rd, rd, imm) : rv_srliw(rd, rd, imm), ctx);
-		if (!is64)
+		if (!is64 && !aux->verifier_zext)
 			emit_zext_32(rd, ctx);
 		break;
 	case BPF_ALU | BPF_ARSH | BPF_K:
 	case BPF_ALU64 | BPF_ARSH | BPF_K:
 		emit(is64 ? rv_srai(rd, rd, imm) : rv_sraiw(rd, rd, imm), ctx);
-		if (!is64)
+		if (!is64 && !aux->verifier_zext)
 			emit_zext_32(rd, ctx);
 		break;
 
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH bpf-next 2/4] bpf, riscv: Optimize FROM_LE using verifier_zext on RV64
  2020-05-06  0:03 ` Luke Nelson
@ 2020-05-06  0:03   ` Luke Nelson
  -1 siblings, 0 replies; 14+ messages in thread
From: Luke Nelson @ 2020-05-06  0:03 UTC (permalink / raw)
  To: bpf
  Cc: Luke Nelson, Xi Wang, Björn Töpel, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexei Starovoitov, Daniel Borkmann,
	Martin KaFai Lau, Song Liu, Yonghong Song, Andrii Nakryiko,
	John Fastabend, KP Singh, netdev, linux-riscv, linux-kernel

This patch adds two optimizations for BPF_ALU BPF_END BPF_FROM_LE in
the RV64 BPF JIT.

First, it enables the verifier zero-extension optimization to avoid zero
extension when imm == 32. Second, it avoids generating code for imm ==
64, since it is equivalent to a no-op.

Co-developed-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
---
 arch/riscv/net/bpf_jit_comp64.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index e2636902a74e..c3ce9a911b66 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -542,13 +542,21 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 
 	/* dst = BSWAP##imm(dst) */
 	case BPF_ALU | BPF_END | BPF_FROM_LE:
-	{
-		int shift = 64 - imm;
-
-		emit(rv_slli(rd, rd, shift), ctx);
-		emit(rv_srli(rd, rd, shift), ctx);
+		switch (imm) {
+		case 16:
+			emit(rv_slli(rd, rd, 48), ctx);
+			emit(rv_srli(rd, rd, 48), ctx);
+			break;
+		case 32:
+			if (!aux->verifier_zext)
+				emit_zext_32(rd, ctx);
+			break;
+		case 64:
+			/* Do nothing */
+			break;
+		}
 		break;
-	}
+
 	case BPF_ALU | BPF_END | BPF_FROM_BE:
 		emit(rv_addi(RV_REG_T2, RV_REG_ZERO, 0), ctx);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH bpf-next 2/4] bpf, riscv: Optimize FROM_LE using verifier_zext on RV64
@ 2020-05-06  0:03   ` Luke Nelson
  0 siblings, 0 replies; 14+ messages in thread
From: Luke Nelson @ 2020-05-06  0:03 UTC (permalink / raw)
  To: bpf
  Cc: Song Liu, Albert Ou, Daniel Borkmann, Luke Nelson,
	Björn Töpel, John Fastabend, Alexei Starovoitov,
	linux-kernel, netdev, Palmer Dabbelt, Paul Walmsley, KP Singh,
	Yonghong Song, linux-riscv, Andrii Nakryiko, Martin KaFai Lau,
	Xi Wang

This patch adds two optimizations for BPF_ALU BPF_END BPF_FROM_LE in
the RV64 BPF JIT.

First, it enables the verifier zero-extension optimization to avoid zero
extension when imm == 32. Second, it avoids generating code for imm ==
64, since it is equivalent to a no-op.

Co-developed-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
---
 arch/riscv/net/bpf_jit_comp64.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index e2636902a74e..c3ce9a911b66 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -542,13 +542,21 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 
 	/* dst = BSWAP##imm(dst) */
 	case BPF_ALU | BPF_END | BPF_FROM_LE:
-	{
-		int shift = 64 - imm;
-
-		emit(rv_slli(rd, rd, shift), ctx);
-		emit(rv_srli(rd, rd, shift), ctx);
+		switch (imm) {
+		case 16:
+			emit(rv_slli(rd, rd, 48), ctx);
+			emit(rv_srli(rd, rd, 48), ctx);
+			break;
+		case 32:
+			if (!aux->verifier_zext)
+				emit_zext_32(rd, ctx);
+			break;
+		case 64:
+			/* Do nothing */
+			break;
+		}
 		break;
-	}
+
 	case BPF_ALU | BPF_END | BPF_FROM_BE:
 		emit(rv_addi(RV_REG_T2, RV_REG_ZERO, 0), ctx);
 
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH bpf-next 3/4] bpf, riscv: Optimize BPF_JMP BPF_K when imm == 0 on RV64
  2020-05-06  0:03 ` Luke Nelson
@ 2020-05-06  0:03   ` Luke Nelson
  -1 siblings, 0 replies; 14+ messages in thread
From: Luke Nelson @ 2020-05-06  0:03 UTC (permalink / raw)
  To: bpf
  Cc: Luke Nelson, Xi Wang, Björn Töpel, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexei Starovoitov, Daniel Borkmann,
	Martin KaFai Lau, Song Liu, Yonghong Song, Andrii Nakryiko,
	John Fastabend, KP Singh, netdev, linux-riscv, linux-kernel

This patch adds an optimization to BPF_JMP (32- and 64-bit) BPF_K for
when the BPF immediate is zero.

When the immediate is zero, the code can directly use the RISC-V zero
register instead of loading a zero immediate to a temporary register
first.

Co-developed-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
---
 arch/riscv/net/bpf_jit_comp64.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index c3ce9a911b66..b07cef952019 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -796,7 +796,13 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 	case BPF_JMP32 | BPF_JSET | BPF_K:
 		rvoff = rv_offset(i, off, ctx);
 		s = ctx->ninsns;
-		emit_imm(RV_REG_T1, imm, ctx);
+		if (imm) {
+			emit_imm(RV_REG_T1, imm, ctx);
+			rs = RV_REG_T1;
+		} else {
+			/* If imm is 0, simply use zero register. */
+			rs = RV_REG_ZERO;
+		}
 		if (!is64) {
 			if (is_signed_bpf_cond(BPF_OP(code)))
 				emit_sext_32_rd(&rd, ctx);
@@ -811,11 +817,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 		if (BPF_OP(code) == BPF_JSET) {
 			/* Adjust for and */
 			rvoff -= 4;
-			emit(rv_and(RV_REG_T1, rd, RV_REG_T1), ctx);
-			emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff,
-				    ctx);
+			emit(rv_and(rs, rd, rs), ctx);
+			emit_branch(BPF_JNE, rs, RV_REG_ZERO, rvoff, ctx);
 		} else {
-			emit_branch(BPF_OP(code), rd, RV_REG_T1, rvoff, ctx);
+			emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
 		}
 		break;
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH bpf-next 3/4] bpf, riscv: Optimize BPF_JMP BPF_K when imm == 0 on RV64
@ 2020-05-06  0:03   ` Luke Nelson
  0 siblings, 0 replies; 14+ messages in thread
From: Luke Nelson @ 2020-05-06  0:03 UTC (permalink / raw)
  To: bpf
  Cc: Song Liu, Albert Ou, Daniel Borkmann, Luke Nelson,
	Björn Töpel, John Fastabend, Alexei Starovoitov,
	linux-kernel, netdev, Palmer Dabbelt, Paul Walmsley, KP Singh,
	Yonghong Song, linux-riscv, Andrii Nakryiko, Martin KaFai Lau,
	Xi Wang

This patch adds an optimization to BPF_JMP (32- and 64-bit) BPF_K for
when the BPF immediate is zero.

When the immediate is zero, the code can directly use the RISC-V zero
register instead of loading a zero immediate to a temporary register
first.

Co-developed-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
---
 arch/riscv/net/bpf_jit_comp64.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index c3ce9a911b66..b07cef952019 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -796,7 +796,13 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 	case BPF_JMP32 | BPF_JSET | BPF_K:
 		rvoff = rv_offset(i, off, ctx);
 		s = ctx->ninsns;
-		emit_imm(RV_REG_T1, imm, ctx);
+		if (imm) {
+			emit_imm(RV_REG_T1, imm, ctx);
+			rs = RV_REG_T1;
+		} else {
+			/* If imm is 0, simply use zero register. */
+			rs = RV_REG_ZERO;
+		}
 		if (!is64) {
 			if (is_signed_bpf_cond(BPF_OP(code)))
 				emit_sext_32_rd(&rd, ctx);
@@ -811,11 +817,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 		if (BPF_OP(code) == BPF_JSET) {
 			/* Adjust for and */
 			rvoff -= 4;
-			emit(rv_and(RV_REG_T1, rd, RV_REG_T1), ctx);
-			emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff,
-				    ctx);
+			emit(rv_and(rs, rd, rs), ctx);
+			emit_branch(BPF_JNE, rs, RV_REG_ZERO, rvoff, ctx);
 		} else {
-			emit_branch(BPF_OP(code), rd, RV_REG_T1, rvoff, ctx);
+			emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
 		}
 		break;
 
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH bpf-next 4/4] bpf, riscv: Optimize BPF_JSET BPF_K using andi on RV64
  2020-05-06  0:03 ` Luke Nelson
@ 2020-05-06  0:03   ` Luke Nelson
  -1 siblings, 0 replies; 14+ messages in thread
From: Luke Nelson @ 2020-05-06  0:03 UTC (permalink / raw)
  To: bpf
  Cc: Luke Nelson, Xi Wang, Björn Töpel, Alexei Starovoitov,
	Daniel Borkmann, Martin KaFai Lau, Song Liu, Yonghong Song,
	Andrii Nakryiko, John Fastabend, KP Singh, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, netdev, linux-riscv, linux-kernel

This patch optimizes BPF_JSET BPF_K by using a RISC-V andi instruction
when the BPF immediate fits in 12 bits, instead of first loading the
immediate to a temporary register.

Examples of generated code with and without this optimization:

BPF_JMP_IMM(BPF_JSET, R1, 2, 1) without optimization:

  20: li    t1,2
  24: and   t1,a0,t1
  28: bnez  t1,0x30

BPF_JMP_IMM(BPF_JSET, R1, 2, 1) with optimization:

  20: andi  t1,a0,2
  24: bnez  t1,0x2c

BPF_JMP32_IMM(BPF_JSET, R1, 2, 1) without optimization:

  20: li    t1,2
  24: mv    t2,a0
  28: slli  t2,t2,0x20
  2c: srli  t2,t2,0x20
  30: slli  t1,t1,0x20
  34: srli  t1,t1,0x20
  38: and   t1,t2,t1
  3c: bnez  t1,0x44

BPF_JMP32_IMM(BPF_JSET, R1, 2, 1) with optimization:

  20: andi  t1,a0,2
  24: bnez  t1,0x2c

In these examples, because the upper 32 bits of the sign-extended
immediate are 0, BPF_JMP BPF_JSET and BPF_JMP32 BPF_JSET are equivalent
and therefore the JIT produces identical code for them.

Co-developed-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
---
 arch/riscv/net/bpf_jit_comp64.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index b07cef952019..6cfd164cbe88 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -792,8 +792,6 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 	case BPF_JMP32 | BPF_JSGE | BPF_K:
 	case BPF_JMP | BPF_JSLE | BPF_K:
 	case BPF_JMP32 | BPF_JSLE | BPF_K:
-	case BPF_JMP | BPF_JSET | BPF_K:
-	case BPF_JMP32 | BPF_JSET | BPF_K:
 		rvoff = rv_offset(i, off, ctx);
 		s = ctx->ninsns;
 		if (imm) {
@@ -813,15 +811,28 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 
 		/* Adjust for extra insns */
 		rvoff -= (e - s) << 2;
+		emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
+		break;
 
-		if (BPF_OP(code) == BPF_JSET) {
-			/* Adjust for and */
-			rvoff -= 4;
-			emit(rv_and(rs, rd, rs), ctx);
-			emit_branch(BPF_JNE, rs, RV_REG_ZERO, rvoff, ctx);
+	case BPF_JMP | BPF_JSET | BPF_K:
+	case BPF_JMP32 | BPF_JSET | BPF_K:
+		rvoff = rv_offset(i, off, ctx);
+		s = ctx->ninsns;
+		if (is_12b_int(imm)) {
+			emit(rv_andi(RV_REG_T1, rd, imm), ctx);
 		} else {
-			emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
+			emit_imm(RV_REG_T1, imm, ctx);
+			emit(rv_and(RV_REG_T1, rd, RV_REG_T1), ctx);
 		}
+		/* For jset32, we should clear the upper 32 bits of t1, but
+		 * sign-extension is sufficient here and saves one instruction,
+		 * as t1 is used only in comparison against zero.
+		 */
+		if (!is64 && imm < 0)
+			emit(rv_addiw(RV_REG_T1, RV_REG_T1, 0), ctx);
+		e = ctx->ninsns;
+		rvoff -= (e - s) << 2;
+		emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff, ctx);
 		break;
 
 	/* function call */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH bpf-next 4/4] bpf, riscv: Optimize BPF_JSET BPF_K using andi on RV64
@ 2020-05-06  0:03   ` Luke Nelson
  0 siblings, 0 replies; 14+ messages in thread
From: Luke Nelson @ 2020-05-06  0:03 UTC (permalink / raw)
  To: bpf
  Cc: Song Liu, Albert Ou, Daniel Borkmann, Luke Nelson,
	Björn Töpel, John Fastabend, Alexei Starovoitov,
	linux-kernel, netdev, Palmer Dabbelt, Paul Walmsley, KP Singh,
	Yonghong Song, linux-riscv, Andrii Nakryiko, Martin KaFai Lau,
	Xi Wang

This patch optimizes BPF_JSET BPF_K by using a RISC-V andi instruction
when the BPF immediate fits in 12 bits, instead of first loading the
immediate to a temporary register.

Examples of generated code with and without this optimization:

BPF_JMP_IMM(BPF_JSET, R1, 2, 1) without optimization:

  20: li    t1,2
  24: and   t1,a0,t1
  28: bnez  t1,0x30

BPF_JMP_IMM(BPF_JSET, R1, 2, 1) with optimization:

  20: andi  t1,a0,2
  24: bnez  t1,0x2c

BPF_JMP32_IMM(BPF_JSET, R1, 2, 1) without optimization:

  20: li    t1,2
  24: mv    t2,a0
  28: slli  t2,t2,0x20
  2c: srli  t2,t2,0x20
  30: slli  t1,t1,0x20
  34: srli  t1,t1,0x20
  38: and   t1,t2,t1
  3c: bnez  t1,0x44

BPF_JMP32_IMM(BPF_JSET, R1, 2, 1) with optimization:

  20: andi  t1,a0,2
  24: bnez  t1,0x2c

In these examples, because the upper 32 bits of the sign-extended
immediate are 0, BPF_JMP BPF_JSET and BPF_JMP32 BPF_JSET are equivalent
and therefore the JIT produces identical code for them.

Co-developed-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
---
 arch/riscv/net/bpf_jit_comp64.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index b07cef952019..6cfd164cbe88 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -792,8 +792,6 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 	case BPF_JMP32 | BPF_JSGE | BPF_K:
 	case BPF_JMP | BPF_JSLE | BPF_K:
 	case BPF_JMP32 | BPF_JSLE | BPF_K:
-	case BPF_JMP | BPF_JSET | BPF_K:
-	case BPF_JMP32 | BPF_JSET | BPF_K:
 		rvoff = rv_offset(i, off, ctx);
 		s = ctx->ninsns;
 		if (imm) {
@@ -813,15 +811,28 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 
 		/* Adjust for extra insns */
 		rvoff -= (e - s) << 2;
+		emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
+		break;
 
-		if (BPF_OP(code) == BPF_JSET) {
-			/* Adjust for and */
-			rvoff -= 4;
-			emit(rv_and(rs, rd, rs), ctx);
-			emit_branch(BPF_JNE, rs, RV_REG_ZERO, rvoff, ctx);
+	case BPF_JMP | BPF_JSET | BPF_K:
+	case BPF_JMP32 | BPF_JSET | BPF_K:
+		rvoff = rv_offset(i, off, ctx);
+		s = ctx->ninsns;
+		if (is_12b_int(imm)) {
+			emit(rv_andi(RV_REG_T1, rd, imm), ctx);
 		} else {
-			emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
+			emit_imm(RV_REG_T1, imm, ctx);
+			emit(rv_and(RV_REG_T1, rd, RV_REG_T1), ctx);
 		}
+		/* For jset32, we should clear the upper 32 bits of t1, but
+		 * sign-extension is sufficient here and saves one instruction,
+		 * as t1 is used only in comparison against zero.
+		 */
+		if (!is64 && imm < 0)
+			emit(rv_addiw(RV_REG_T1, RV_REG_T1, 0), ctx);
+		e = ctx->ninsns;
+		rvoff -= (e - s) << 2;
+		emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff, ctx);
 		break;
 
 	/* function call */
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf-next 0/4] RV64 BPF JIT Optimizations
  2020-05-06  0:03 ` Luke Nelson
@ 2020-05-06  7:08   ` Björn Töpel
  -1 siblings, 0 replies; 14+ messages in thread
From: Björn Töpel @ 2020-05-06  7:08 UTC (permalink / raw)
  To: Luke Nelson
  Cc: bpf, Luke Nelson, Xi Wang, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau,
	Song Liu, Yonghong Song, Andrii Nakryiko, John Fastabend,
	KP Singh, Netdev, linux-riscv, LKML

On Wed, 6 May 2020 at 02:03, Luke Nelson <lukenels@cs.washington.edu> wrote:
>
> This patch series introduces a set of optimizations to the BPF JIT
> on RV64. The optimizations are related to the verifier zero-extension
> optimization and BPF_JMP BPF_K.
>
> We tested the optimizations on a QEMU riscv64 virt machine, using
> lib/test_bpf and test_verifier, and formally verified their correctness
> using Serval.
>

Luke and Xi,

Thanks a lot for working on this! Very nice series!

For the series:
Reviewed-by: Björn Töpel <bjorn.topel@gmail.com>
Acked-by: Björn Töpel <bjorn.topel@gmail.com>

> Luke Nelson (4):
>   bpf, riscv: Enable missing verifier_zext optimizations on RV64
>   bpf, riscv: Optimize FROM_LE using verifier_zext on RV64
>   bpf, riscv: Optimize BPF_JMP BPF_K when imm == 0 on RV64
>   bpf, riscv: Optimize BPF_JSET BPF_K using andi on RV64
>
>  arch/riscv/net/bpf_jit_comp64.c | 64 ++++++++++++++++++++++-----------
>  1 file changed, 44 insertions(+), 20 deletions(-)
>
> Cc: Xi Wang <xi.wang@gmail.com>
>
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf-next 0/4] RV64 BPF JIT Optimizations
@ 2020-05-06  7:08   ` Björn Töpel
  0 siblings, 0 replies; 14+ messages in thread
From: Björn Töpel @ 2020-05-06  7:08 UTC (permalink / raw)
  To: Luke Nelson
  Cc: Song Liu, Albert Ou, Daniel Borkmann, Luke Nelson, Netdev,
	John Fastabend, Alexei Starovoitov, linux-riscv, LKML,
	Palmer Dabbelt, Paul Walmsley, KP Singh, Yonghong Song, bpf,
	Andrii Nakryiko, Martin KaFai Lau, Xi Wang

On Wed, 6 May 2020 at 02:03, Luke Nelson <lukenels@cs.washington.edu> wrote:
>
> This patch series introduces a set of optimizations to the BPF JIT
> on RV64. The optimizations are related to the verifier zero-extension
> optimization and BPF_JMP BPF_K.
>
> We tested the optimizations on a QEMU riscv64 virt machine, using
> lib/test_bpf and test_verifier, and formally verified their correctness
> using Serval.
>

Luke and Xi,

Thanks a lot for working on this! Very nice series!

For the series:
Reviewed-by: Björn Töpel <bjorn.topel@gmail.com>
Acked-by: Björn Töpel <bjorn.topel@gmail.com>

> Luke Nelson (4):
>   bpf, riscv: Enable missing verifier_zext optimizations on RV64
>   bpf, riscv: Optimize FROM_LE using verifier_zext on RV64
>   bpf, riscv: Optimize BPF_JMP BPF_K when imm == 0 on RV64
>   bpf, riscv: Optimize BPF_JSET BPF_K using andi on RV64
>
>  arch/riscv/net/bpf_jit_comp64.c | 64 ++++++++++++++++++++++-----------
>  1 file changed, 44 insertions(+), 20 deletions(-)
>
> Cc: Xi Wang <xi.wang@gmail.com>
>
> --
> 2.17.1
>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf-next 0/4] RV64 BPF JIT Optimizations
  2020-05-06  7:08   ` Björn Töpel
@ 2020-05-06  8:08     ` Daniel Borkmann
  -1 siblings, 0 replies; 14+ messages in thread
From: Daniel Borkmann @ 2020-05-06  8:08 UTC (permalink / raw)
  To: Björn Töpel, Luke Nelson
  Cc: bpf, Luke Nelson, Xi Wang, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexei Starovoitov, Martin KaFai Lau, Song Liu,
	Yonghong Song, Andrii Nakryiko, John Fastabend, KP Singh, Netdev,
	linux-riscv, LKML

On 5/6/20 9:08 AM, Björn Töpel wrote:
> On Wed, 6 May 2020 at 02:03, Luke Nelson <lukenels@cs.washington.edu> wrote:
>>
>> This patch series introduces a set of optimizations to the BPF JIT
>> on RV64. The optimizations are related to the verifier zero-extension
>> optimization and BPF_JMP BPF_K.
>>
>> We tested the optimizations on a QEMU riscv64 virt machine, using
>> lib/test_bpf and test_verifier, and formally verified their correctness
>> using Serval.
>>
> 
> Luke and Xi,
> 
> Thanks a lot for working on this! Very nice series!
> 
> For the series:
> Reviewed-by: Björn Töpel <bjorn.topel@gmail.com>
> Acked-by: Björn Töpel <bjorn.topel@gmail.com>
> 
>> Luke Nelson (4):
>>    bpf, riscv: Enable missing verifier_zext optimizations on RV64
>>    bpf, riscv: Optimize FROM_LE using verifier_zext on RV64
>>    bpf, riscv: Optimize BPF_JMP BPF_K when imm == 0 on RV64
>>    bpf, riscv: Optimize BPF_JSET BPF_K using andi on RV64
>>
>>   arch/riscv/net/bpf_jit_comp64.c | 64 ++++++++++++++++++++++-----------
>>   1 file changed, 44 insertions(+), 20 deletions(-)
>>
>> Cc: Xi Wang <xi.wang@gmail.com>

Applied, thanks everyone!

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH bpf-next 0/4] RV64 BPF JIT Optimizations
@ 2020-05-06  8:08     ` Daniel Borkmann
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Borkmann @ 2020-05-06  8:08 UTC (permalink / raw)
  To: Björn Töpel, Luke Nelson
  Cc: Song Liu, Albert Ou, Luke Nelson, Netdev, John Fastabend,
	Alexei Starovoitov, linux-riscv, LKML, Palmer Dabbelt,
	Paul Walmsley, KP Singh, Yonghong Song, bpf, Andrii Nakryiko,
	Martin KaFai Lau, Xi Wang

On 5/6/20 9:08 AM, Björn Töpel wrote:
> On Wed, 6 May 2020 at 02:03, Luke Nelson <lukenels@cs.washington.edu> wrote:
>>
>> This patch series introduces a set of optimizations to the BPF JIT
>> on RV64. The optimizations are related to the verifier zero-extension
>> optimization and BPF_JMP BPF_K.
>>
>> We tested the optimizations on a QEMU riscv64 virt machine, using
>> lib/test_bpf and test_verifier, and formally verified their correctness
>> using Serval.
>>
> 
> Luke and Xi,
> 
> Thanks a lot for working on this! Very nice series!
> 
> For the series:
> Reviewed-by: Björn Töpel <bjorn.topel@gmail.com>
> Acked-by: Björn Töpel <bjorn.topel@gmail.com>
> 
>> Luke Nelson (4):
>>    bpf, riscv: Enable missing verifier_zext optimizations on RV64
>>    bpf, riscv: Optimize FROM_LE using verifier_zext on RV64
>>    bpf, riscv: Optimize BPF_JMP BPF_K when imm == 0 on RV64
>>    bpf, riscv: Optimize BPF_JSET BPF_K using andi on RV64
>>
>>   arch/riscv/net/bpf_jit_comp64.c | 64 ++++++++++++++++++++++-----------
>>   1 file changed, 44 insertions(+), 20 deletions(-)
>>
>> Cc: Xi Wang <xi.wang@gmail.com>

Applied, thanks everyone!


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2020-05-06  8:09 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-06  0:03 [PATCH bpf-next 0/4] RV64 BPF JIT Optimizations Luke Nelson
2020-05-06  0:03 ` Luke Nelson
2020-05-06  0:03 ` [PATCH bpf-next 1/4] bpf, riscv: Enable missing verifier_zext optimizations on RV64 Luke Nelson
2020-05-06  0:03   ` Luke Nelson
2020-05-06  0:03 ` [PATCH bpf-next 2/4] bpf, riscv: Optimize FROM_LE using verifier_zext " Luke Nelson
2020-05-06  0:03   ` Luke Nelson
2020-05-06  0:03 ` [PATCH bpf-next 3/4] bpf, riscv: Optimize BPF_JMP BPF_K when imm == 0 " Luke Nelson
2020-05-06  0:03   ` Luke Nelson
2020-05-06  0:03 ` [PATCH bpf-next 4/4] bpf, riscv: Optimize BPF_JSET BPF_K using andi " Luke Nelson
2020-05-06  0:03   ` Luke Nelson
2020-05-06  7:08 ` [PATCH bpf-next 0/4] RV64 BPF JIT Optimizations Björn Töpel
2020-05-06  7:08   ` Björn Töpel
2020-05-06  8:08   ` Daniel Borkmann
2020-05-06  8:08     ` Daniel Borkmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.