All of lore.kernel.org
 help / color / mirror / Atom feed
From: Johan Almbladh <johan.almbladh@anyfinetworks.com>
To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org
Cc: kafai@fb.com, songliubraving@fb.com, yhs@fb.com,
	john.fastabend@gmail.com, kpsingh@kernel.org, iii@linux.ibm.com,
	paul@cilium.io, yangtiezhu@loongson.cn, netdev@vger.kernel.org,
	bpf@vger.kernel.org,
	Johan Almbladh <johan.almbladh@anyfinetworks.com>
Subject: [PATCH bpf v4 11/14] bpf/tests: Expand branch conversion JIT test
Date: Tue, 14 Sep 2021 11:18:39 +0200	[thread overview]
Message-ID: <20210914091842.4186267-12-johan.almbladh@anyfinetworks.com> (raw)
In-Reply-To: <20210914091842.4186267-1-johan.almbladh@anyfinetworks.com>

This patch expands the branch conversion test introduced by 66e5eb84
("bpf, tests: Add branch conversion JIT test"). The test now includes
a JMP with maximum eBPF offset. This triggers branch conversion for the
64-bit MIPS JIT. Additional variants are also added for cases when the
branch is taken or not taken.

Signed-off-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
---
 lib/test_bpf.c | 125 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 91 insertions(+), 34 deletions(-)

diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index ae261667ca0a..a515f9b670c9 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -463,47 +463,79 @@ static int bpf_fill_stxdw(struct bpf_test *self)
 	return __bpf_fill_stxdw(self, BPF_DW);
 }
 
-static int bpf_fill_long_jmp(struct bpf_test *self)
+static int __bpf_ld_imm64(struct bpf_insn insns[2], u8 reg, s64 imm64)
 {
-	unsigned int len = BPF_MAXINSNS;
-	struct bpf_insn *insn;
+	struct bpf_insn tmp[] = {BPF_LD_IMM64(reg, imm64)};
+
+	memcpy(insns, tmp, sizeof(tmp));
+	return 2;
+}
+
+/*
+ * Branch conversion tests. Complex operations can expand to a lot
+ * of instructions when JITed. This in turn may cause jump offsets
+ * to overflow the field size of the native instruction, triggering
+ * a branch conversion mechanism in some JITs.
+ */
+static int __bpf_fill_max_jmp(struct bpf_test *self, int jmp, int imm)
+{
+	struct bpf_insn *insns;
+	int len = S16_MAX + 5;
 	int i;
 
-	insn = kmalloc_array(len, sizeof(*insn), GFP_KERNEL);
-	if (!insn)
+	insns = kmalloc_array(len, sizeof(*insns), GFP_KERNEL);
+	if (!insns)
 		return -ENOMEM;
 
-	insn[0] = BPF_ALU64_IMM(BPF_MOV, R0, 1);
-	insn[1] = BPF_JMP_IMM(BPF_JEQ, R0, 1, len - 2 - 1);
+	i = __bpf_ld_imm64(insns, R1, 0x0123456789abcdefULL);
+	insns[i++] = BPF_ALU64_IMM(BPF_MOV, R0, 1);
+	insns[i++] = BPF_JMP_IMM(jmp, R0, imm, S16_MAX);
+	insns[i++] = BPF_ALU64_IMM(BPF_MOV, R0, 2);
+	insns[i++] = BPF_EXIT_INSN();
 
-	/*
-	 * Fill with a complex 64-bit operation that expands to a lot of
-	 * instructions on 32-bit JITs. The large jump offset can then
-	 * overflow the conditional branch field size, triggering a branch
-	 * conversion mechanism in some JITs.
-	 *
-	 * Note: BPF_MAXINSNS of ALU64 MUL is enough to trigger such branch
-	 * conversion on the 32-bit MIPS JIT. For other JITs, the instruction
-	 * count and/or operation may need to be modified to trigger the
-	 * branch conversion.
-	 */
-	for (i = 2; i < len - 1; i++)
-		insn[i] = BPF_ALU64_IMM(BPF_MUL, R0, (i << 16) + i);
+	while (i < len - 1) {
+		static const int ops[] = {
+			BPF_LSH, BPF_RSH, BPF_ARSH, BPF_ADD,
+			BPF_SUB, BPF_MUL, BPF_DIV, BPF_MOD,
+		};
+		int op = ops[(i >> 1) % ARRAY_SIZE(ops)];
 
-	insn[len - 1] = BPF_EXIT_INSN();
+		if (i & 1)
+			insns[i++] = BPF_ALU32_REG(op, R0, R1);
+		else
+			insns[i++] = BPF_ALU64_REG(op, R0, R1);
+	}
 
-	self->u.ptr.insns = insn;
+	insns[i++] = BPF_EXIT_INSN();
+	self->u.ptr.insns = insns;
 	self->u.ptr.len = len;
+	BUG_ON(i != len);
 
 	return 0;
 }
 
-static int __bpf_ld_imm64(struct bpf_insn insns[2], u8 reg, s64 imm64)
+/* Branch taken by runtime decision */
+static int bpf_fill_max_jmp_taken(struct bpf_test *self)
 {
-	struct bpf_insn tmp[] = {BPF_LD_IMM64(reg, imm64)};
+	return __bpf_fill_max_jmp(self, BPF_JEQ, 1);
+}
 
-	memcpy(insns, tmp, sizeof(tmp));
-	return 2;
+/* Branch not taken by runtime decision */
+static int bpf_fill_max_jmp_not_taken(struct bpf_test *self)
+{
+	return __bpf_fill_max_jmp(self, BPF_JEQ, 0);
+}
+
+/* Branch always taken, known at JIT time */
+static int bpf_fill_max_jmp_always_taken(struct bpf_test *self)
+{
+	return __bpf_fill_max_jmp(self, BPF_JGE, 0);
+}
+
+/* Branch never taken, known at JIT time */
+static int bpf_fill_max_jmp_never_taken(struct bpf_test *self)
+{
+	return __bpf_fill_max_jmp(self, BPF_JLT, 0);
 }
 
 /* Test an ALU shift operation for all valid shift values */
@@ -8653,14 +8685,6 @@ static struct bpf_test tests[] = {
 		{ },
 		{ { 0, 1 } },
 	},
-	{	/* Mainly checking JIT here. */
-		"BPF_MAXINSNS: Very long conditional jump",
-		{ },
-		INTERNAL | FLAG_NO_DATA,
-		{ },
-		{ { 0, 1 } },
-		.fill_helper = bpf_fill_long_jmp,
-	},
 	{
 		"JMP_JA: Jump, gap, jump, ...",
 		{ },
@@ -11009,6 +11033,39 @@ static struct bpf_test tests[] = {
 		{ },
 		{ { 0, 0 } },
 	},
+	/* Conditional branch conversions */
+	{
+		"Long conditional jump: taken at runtime",
+		{ },
+		INTERNAL | FLAG_NO_DATA,
+		{ },
+		{ { 0, 1 } },
+		.fill_helper = bpf_fill_max_jmp_taken,
+	},
+	{
+		"Long conditional jump: not taken at runtime",
+		{ },
+		INTERNAL | FLAG_NO_DATA,
+		{ },
+		{ { 0, 2 } },
+		.fill_helper = bpf_fill_max_jmp_not_taken,
+	},
+	{
+		"Long conditional jump: always taken, known at JIT time",
+		{ },
+		INTERNAL | FLAG_NO_DATA,
+		{ },
+		{ { 0, 1 } },
+		.fill_helper = bpf_fill_max_jmp_always_taken,
+	},
+	{
+		"Long conditional jump: never taken, known at JIT time",
+		{ },
+		INTERNAL | FLAG_NO_DATA,
+		{ },
+		{ { 0, 2 } },
+		.fill_helper = bpf_fill_max_jmp_never_taken,
+	},
 	/* Staggered jump sequences, immediate */
 	{
 		"Staggered jumps: JMP_JA",
-- 
2.30.2


  parent reply	other threads:[~2021-09-14  9:19 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-14  9:18 [PATCH bpf v4 00/14] bpf/tests: Extend JIT test suite coverage Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 01/14] bpf/tests: Allow different number of runs per test case Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 02/14] bpf/tests: Reduce memory footprint of test suite Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 03/14] bpf/tests: Add exhaustive tests of ALU shift values Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 04/14] bpf/tests: Add exhaustive tests of ALU operand magnitudes Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 05/14] bpf/tests: Add exhaustive tests of JMP " Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 06/14] bpf/tests: Add staggered JMP and JMP32 tests Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 07/14] bpf/tests: Add exhaustive test of LD_IMM64 immediate magnitudes Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 08/14] bpf/tests: Add test case flag for verifier zero-extension Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 09/14] bpf/tests: Add JMP tests with small offsets Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 10/14] bpf/tests: Add JMP tests with degenerate conditional Johan Almbladh
2021-09-14  9:18 ` Johan Almbladh [this message]
2021-09-14  9:18 ` [PATCH bpf v4 12/14] bpf/tests: Add more BPF_END byte order conversion tests Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 13/14] bpf/tests: Fix error in tail call limit tests Johan Almbladh
2021-09-14 12:41   ` Tiezhu Yang
2021-09-14 12:55     ` Tiezhu Yang
2021-09-14 13:09       ` Johan Almbladh
2021-09-14  9:18 ` [PATCH bpf v4 14/14] bpf/tests: Add tail call limit test with external function call Johan Almbladh
2021-09-15 20:00 ` [PATCH bpf v4 00/14] bpf/tests: Extend JIT test suite coverage patchwork-bot+netdevbpf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210914091842.4186267-12-johan.almbladh@anyfinetworks.com \
    --to=johan.almbladh@anyfinetworks.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=iii@linux.ibm.com \
    --cc=john.fastabend@gmail.com \
    --cc=kafai@fb.com \
    --cc=kpsingh@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=paul@cilium.io \
    --cc=songliubraving@fb.com \
    --cc=yangtiezhu@loongson.cn \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.