All of lore.kernel.org
 help / color / mirror / Atom feed
* [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler
@ 2021-10-12 12:30 ` Hari Bathini
  0 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev, Hari Bathini

Patch #1 & #2 are simple cleanup patches. Patch #3 refactors JIT
compiler code with the aim to simplify adding BPF_PROBE_MEM support.
Patch #4 introduces PPC_RAW_BRANCH() macro instead of open coding
branch instruction. Patch #5 & #7 add BPF_PROBE_MEM support for PPC64
& PPC32 JIT compilers respectively. Patch #6 & #8 handle bad userspace
pointers for PPC64 & PPC32 cases respectively.


Resending v4 after rebasing the series on top of bpf fix patches
posted by Naveen:

  - https://patchwork.ozlabs.org/project/linuxppc-dev/cover/cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com/
    ("[v2,00/10] powerpc/bpf: Various fixes")

Also, added Reviewed-by tag from Christophe for patches #3, #5, #6, #7 & #8.


Hari Bathini (4):
  bpf powerpc: refactor JIT compiler code
  powerpc/ppc-opcode: introduce PPC_RAW_BRANCH() macro
  bpf ppc32: Add BPF_PROBE_MEM support for JIT
  bpf ppc32: Access only if addr is kernel address

Ravi Bangoria (4):
  bpf powerpc: Remove unused SEEN_STACK
  bpf powerpc: Remove extra_pass from bpf_jit_build_body()
  bpf ppc64: Add BPF_PROBE_MEM support for JIT
  bpf ppc64: Access only if addr is kernel address

 arch/powerpc/include/asm/ppc-opcode.h |   2 +
 arch/powerpc/net/bpf_jit.h            |  17 ++++-
 arch/powerpc/net/bpf_jit_comp.c       |  68 +++++++++++++++--
 arch/powerpc/net/bpf_jit_comp32.c     | 101 ++++++++++++++++++++++----
 arch/powerpc/net/bpf_jit_comp64.c     |  72 ++++++++++++++----
 5 files changed, 219 insertions(+), 41 deletions(-)

-- 
2.31.1


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

* [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler
@ 2021-10-12 12:30 ` Hari Bathini
  0 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: songliubraving, netdev, john.fastabend, andrii, kpsingh, paulus,
	yhs, bpf, linuxppc-dev, kafai, Hari Bathini

Patch #1 & #2 are simple cleanup patches. Patch #3 refactors JIT
compiler code with the aim to simplify adding BPF_PROBE_MEM support.
Patch #4 introduces PPC_RAW_BRANCH() macro instead of open coding
branch instruction. Patch #5 & #7 add BPF_PROBE_MEM support for PPC64
& PPC32 JIT compilers respectively. Patch #6 & #8 handle bad userspace
pointers for PPC64 & PPC32 cases respectively.


Resending v4 after rebasing the series on top of bpf fix patches
posted by Naveen:

  - https://patchwork.ozlabs.org/project/linuxppc-dev/cover/cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com/
    ("[v2,00/10] powerpc/bpf: Various fixes")

Also, added Reviewed-by tag from Christophe for patches #3, #5, #6, #7 & #8.


Hari Bathini (4):
  bpf powerpc: refactor JIT compiler code
  powerpc/ppc-opcode: introduce PPC_RAW_BRANCH() macro
  bpf ppc32: Add BPF_PROBE_MEM support for JIT
  bpf ppc32: Access only if addr is kernel address

Ravi Bangoria (4):
  bpf powerpc: Remove unused SEEN_STACK
  bpf powerpc: Remove extra_pass from bpf_jit_build_body()
  bpf ppc64: Add BPF_PROBE_MEM support for JIT
  bpf ppc64: Access only if addr is kernel address

 arch/powerpc/include/asm/ppc-opcode.h |   2 +
 arch/powerpc/net/bpf_jit.h            |  17 ++++-
 arch/powerpc/net/bpf_jit_comp.c       |  68 +++++++++++++++--
 arch/powerpc/net/bpf_jit_comp32.c     | 101 ++++++++++++++++++++++----
 arch/powerpc/net/bpf_jit_comp64.c     |  72 ++++++++++++++----
 5 files changed, 219 insertions(+), 41 deletions(-)

-- 
2.31.1


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

* [RESEND PATCH v4 1/8] bpf powerpc: Remove unused SEEN_STACK
  2021-10-12 12:30 ` Hari Bathini
@ 2021-10-12 12:30   ` Hari Bathini
  -1 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev, Ravi Bangoria

From: Ravi Bangoria <ravi.bangoria@linux.ibm.com>

SEEN_STACK is unused on PowerPC. Remove it. Also, have
SEEN_TAILCALL use 0x40000000.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

* No changes in v4.


 arch/powerpc/net/bpf_jit.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 7e9b978b768e..89bd744c2bff 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -125,8 +125,7 @@
 #define COND_LE		(CR0_GT | COND_CMP_FALSE)
 
 #define SEEN_FUNC	0x20000000 /* might call external helpers */
-#define SEEN_STACK	0x40000000 /* uses BPF stack */
-#define SEEN_TAILCALL	0x80000000 /* uses tail calls */
+#define SEEN_TAILCALL	0x40000000 /* uses tail calls */
 
 #define SEEN_VREG_MASK	0x1ff80000 /* Volatile registers r3-r12 */
 #define SEEN_NVREG_MASK	0x0003ffff /* Non volatile registers r14-r31 */
-- 
2.31.1


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

* [RESEND PATCH v4 1/8] bpf powerpc: Remove unused SEEN_STACK
@ 2021-10-12 12:30   ` Hari Bathini
  0 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: Ravi Bangoria, songliubraving, netdev, john.fastabend, andrii,
	kpsingh, paulus, yhs, bpf, linuxppc-dev, kafai

From: Ravi Bangoria <ravi.bangoria@linux.ibm.com>

SEEN_STACK is unused on PowerPC. Remove it. Also, have
SEEN_TAILCALL use 0x40000000.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

* No changes in v4.


 arch/powerpc/net/bpf_jit.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 7e9b978b768e..89bd744c2bff 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -125,8 +125,7 @@
 #define COND_LE		(CR0_GT | COND_CMP_FALSE)
 
 #define SEEN_FUNC	0x20000000 /* might call external helpers */
-#define SEEN_STACK	0x40000000 /* uses BPF stack */
-#define SEEN_TAILCALL	0x80000000 /* uses tail calls */
+#define SEEN_TAILCALL	0x40000000 /* uses tail calls */
 
 #define SEEN_VREG_MASK	0x1ff80000 /* Volatile registers r3-r12 */
 #define SEEN_NVREG_MASK	0x0003ffff /* Non volatile registers r14-r31 */
-- 
2.31.1


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

* [RESEND PATCH v4 2/8] bpf powerpc: Remove extra_pass from bpf_jit_build_body()
  2021-10-12 12:30 ` Hari Bathini
@ 2021-10-12 12:30   ` Hari Bathini
  -1 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev, Ravi Bangoria

From: Ravi Bangoria <ravi.bangoria@linux.ibm.com>

In case of extra_pass, usual JIT passes are always skipped. So,
extra_pass is always false while calling bpf_jit_build_body() and
can be removed.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
---

* No changes in v4.


 arch/powerpc/net/bpf_jit.h        | 2 +-
 arch/powerpc/net/bpf_jit_comp.c   | 6 +++---
 arch/powerpc/net/bpf_jit_comp32.c | 4 ++--
 arch/powerpc/net/bpf_jit_comp64.c | 4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 89bd744c2bff..7145b651fc2a 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -175,7 +175,7 @@ static inline void bpf_clear_seen_register(struct codegen_context *ctx, int i)
 
 void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func);
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs, bool extra_pass);
+		       u32 *addrs);
 void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx);
 void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx);
 void bpf_jit_realloc_regs(struct codegen_context *ctx);
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index fcbf7a917c56..f7972b2c21f6 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -149,7 +149,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	cgctx.stack_size = round_up(fp->aux->stack_depth, 16);
 
 	/* Scouting faux-generate pass 0 */
-	if (bpf_jit_build_body(fp, 0, &cgctx, addrs, false)) {
+	if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) {
 		/* We hit something illegal or unsupported. */
 		fp = org_fp;
 		goto out_addrs;
@@ -162,7 +162,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	 */
 	if (cgctx.seen & SEEN_TAILCALL) {
 		cgctx.idx = 0;
-		if (bpf_jit_build_body(fp, 0, &cgctx, addrs, false)) {
+		if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) {
 			fp = org_fp;
 			goto out_addrs;
 		}
@@ -210,7 +210,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 		/* Now build the prologue, body code & epilogue for real. */
 		cgctx.idx = 0;
 		bpf_jit_build_prologue(code_base, &cgctx);
-		if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, extra_pass)) {
+		if (bpf_jit_build_body(fp, code_base, &cgctx, addrs)) {
 			bpf_jit_binary_free(bpf_hdr);
 			fp = org_fp;
 			goto out_addrs;
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 0da31d41d413..903f945601c0 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -268,7 +268,7 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
 
 /* Assemble the body code between the prologue & epilogue */
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs, bool extra_pass)
+		       u32 *addrs)
 {
 	const struct bpf_insn *insn = fp->insnsi;
 	int flen = fp->len;
@@ -862,7 +862,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		case BPF_JMP | BPF_CALL:
 			ctx->seen |= SEEN_FUNC;
 
-			ret = bpf_jit_get_func_addr(fp, &insn[i], extra_pass,
+			ret = bpf_jit_get_func_addr(fp, &insn[i], false,
 						    &func_addr, &func_addr_fixed);
 			if (ret < 0)
 				return ret;
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index 8b5157ccfeba..b25bf9b11b9d 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -297,7 +297,7 @@ asm (
 
 /* Assemble the body code between the prologue & epilogue */
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs, bool extra_pass)
+		       u32 *addrs)
 {
 	enum stf_barrier_type stf_barrier = stf_barrier_type_get();
 	const struct bpf_insn *insn = fp->insnsi;
@@ -831,7 +831,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		case BPF_JMP | BPF_CALL:
 			ctx->seen |= SEEN_FUNC;
 
-			ret = bpf_jit_get_func_addr(fp, &insn[i], extra_pass,
+			ret = bpf_jit_get_func_addr(fp, &insn[i], false,
 						    &func_addr, &func_addr_fixed);
 			if (ret < 0)
 				return ret;
-- 
2.31.1


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

* [RESEND PATCH v4 2/8] bpf powerpc: Remove extra_pass from bpf_jit_build_body()
@ 2021-10-12 12:30   ` Hari Bathini
  0 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: Ravi Bangoria, songliubraving, netdev, john.fastabend, andrii,
	kpsingh, paulus, yhs, bpf, linuxppc-dev, kafai

From: Ravi Bangoria <ravi.bangoria@linux.ibm.com>

In case of extra_pass, usual JIT passes are always skipped. So,
extra_pass is always false while calling bpf_jit_build_body() and
can be removed.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
---

* No changes in v4.


 arch/powerpc/net/bpf_jit.h        | 2 +-
 arch/powerpc/net/bpf_jit_comp.c   | 6 +++---
 arch/powerpc/net/bpf_jit_comp32.c | 4 ++--
 arch/powerpc/net/bpf_jit_comp64.c | 4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 89bd744c2bff..7145b651fc2a 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -175,7 +175,7 @@ static inline void bpf_clear_seen_register(struct codegen_context *ctx, int i)
 
 void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func);
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs, bool extra_pass);
+		       u32 *addrs);
 void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx);
 void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx);
 void bpf_jit_realloc_regs(struct codegen_context *ctx);
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index fcbf7a917c56..f7972b2c21f6 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -149,7 +149,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	cgctx.stack_size = round_up(fp->aux->stack_depth, 16);
 
 	/* Scouting faux-generate pass 0 */
-	if (bpf_jit_build_body(fp, 0, &cgctx, addrs, false)) {
+	if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) {
 		/* We hit something illegal or unsupported. */
 		fp = org_fp;
 		goto out_addrs;
@@ -162,7 +162,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	 */
 	if (cgctx.seen & SEEN_TAILCALL) {
 		cgctx.idx = 0;
-		if (bpf_jit_build_body(fp, 0, &cgctx, addrs, false)) {
+		if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) {
 			fp = org_fp;
 			goto out_addrs;
 		}
@@ -210,7 +210,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 		/* Now build the prologue, body code & epilogue for real. */
 		cgctx.idx = 0;
 		bpf_jit_build_prologue(code_base, &cgctx);
-		if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, extra_pass)) {
+		if (bpf_jit_build_body(fp, code_base, &cgctx, addrs)) {
 			bpf_jit_binary_free(bpf_hdr);
 			fp = org_fp;
 			goto out_addrs;
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 0da31d41d413..903f945601c0 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -268,7 +268,7 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
 
 /* Assemble the body code between the prologue & epilogue */
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs, bool extra_pass)
+		       u32 *addrs)
 {
 	const struct bpf_insn *insn = fp->insnsi;
 	int flen = fp->len;
@@ -862,7 +862,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		case BPF_JMP | BPF_CALL:
 			ctx->seen |= SEEN_FUNC;
 
-			ret = bpf_jit_get_func_addr(fp, &insn[i], extra_pass,
+			ret = bpf_jit_get_func_addr(fp, &insn[i], false,
 						    &func_addr, &func_addr_fixed);
 			if (ret < 0)
 				return ret;
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index 8b5157ccfeba..b25bf9b11b9d 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -297,7 +297,7 @@ asm (
 
 /* Assemble the body code between the prologue & epilogue */
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs, bool extra_pass)
+		       u32 *addrs)
 {
 	enum stf_barrier_type stf_barrier = stf_barrier_type_get();
 	const struct bpf_insn *insn = fp->insnsi;
@@ -831,7 +831,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		case BPF_JMP | BPF_CALL:
 			ctx->seen |= SEEN_FUNC;
 
-			ret = bpf_jit_get_func_addr(fp, &insn[i], extra_pass,
+			ret = bpf_jit_get_func_addr(fp, &insn[i], false,
 						    &func_addr, &func_addr_fixed);
 			if (ret < 0)
 				return ret;
-- 
2.31.1


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

* [RESEND PATCH v4 3/8] bpf powerpc: refactor JIT compiler code
  2021-10-12 12:30 ` Hari Bathini
@ 2021-10-12 12:30   ` Hari Bathini
  -1 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev, Hari Bathini

Refactor powerpc LDX JITing code to simplify adding BPF_PROBE_MEM
support.

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

Changes in v4:
* Dropped the default case in the switch statement for bpf size.
* Dropped explicit fallthrough statement for empty switch cases.


 arch/powerpc/net/bpf_jit_comp32.c | 33 ++++++++++++++++++-------------
 arch/powerpc/net/bpf_jit_comp64.c | 31 +++++++++++++++++------------
 2 files changed, 37 insertions(+), 27 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 903f945601c0..8b2ac1c27f1f 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -284,6 +284,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		u32 src_reg = bpf_to_ppc(ctx, insn[i].src_reg);
 		u32 src_reg_h = src_reg - 1;
 		u32 tmp_reg = bpf_to_ppc(ctx, TMP_REG);
+		u32 size = BPF_SIZE(code);
 		s16 off = insn[i].off;
 		s32 imm = insn[i].imm;
 		bool func_addr_fixed;
@@ -812,23 +813,27 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		 * BPF_LDX
 		 */
 		case BPF_LDX | BPF_MEM | BPF_B: /* dst = *(u8 *)(ul) (src + off) */
-			EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
-			if (!fp->aux->verifier_zext)
-				EMIT(PPC_RAW_LI(dst_reg_h, 0));
-			break;
 		case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */
-			EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off));
-			if (!fp->aux->verifier_zext)
-				EMIT(PPC_RAW_LI(dst_reg_h, 0));
-			break;
 		case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */
-			EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off));
-			if (!fp->aux->verifier_zext)
-				EMIT(PPC_RAW_LI(dst_reg_h, 0));
-			break;
 		case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */
-			EMIT(PPC_RAW_LWZ(dst_reg_h, src_reg, off));
-			EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off + 4));
+			switch (size) {
+			case BPF_B:
+				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
+				break;
+			case BPF_H:
+				EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off));
+				break;
+			case BPF_W:
+				EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off));
+				break;
+			case BPF_DW:
+				EMIT(PPC_RAW_LWZ(dst_reg_h, src_reg, off));
+				EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off + 4));
+				break;
+			}
+
+			if (size != BPF_DW && !fp->aux->verifier_zext)
+				EMIT(PPC_RAW_LI(dst_reg_h, 0));
 			break;
 
 		/*
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index b25bf9b11b9d..ad852f15ca61 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -311,6 +311,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		u32 code = insn[i].code;
 		u32 dst_reg = b2p[insn[i].dst_reg];
 		u32 src_reg = b2p[insn[i].src_reg];
+		u32 size = BPF_SIZE(code);
 		s16 off = insn[i].off;
 		s32 imm = insn[i].imm;
 		bool func_addr_fixed;
@@ -778,25 +779,29 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		 */
 		/* dst = *(u8 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_B:
-			EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
-			if (insn_is_zext(&insn[i + 1]))
-				addrs[++i] = ctx->idx * 4;
-			break;
 		/* dst = *(u16 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_H:
-			EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off));
-			if (insn_is_zext(&insn[i + 1]))
-				addrs[++i] = ctx->idx * 4;
-			break;
 		/* dst = *(u32 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_W:
-			EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off));
-			if (insn_is_zext(&insn[i + 1]))
-				addrs[++i] = ctx->idx * 4;
-			break;
 		/* dst = *(u64 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_DW:
-			PPC_BPF_LL(dst_reg, src_reg, off);
+			switch (size) {
+			case BPF_B:
+				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
+				break;
+			case BPF_H:
+				EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off));
+				break;
+			case BPF_W:
+				EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off));
+				break;
+			case BPF_DW:
+				PPC_BPF_LL(dst_reg, src_reg, off);
+				break;
+			}
+
+			if (size != BPF_DW && insn_is_zext(&insn[i + 1]))
+				addrs[++i] = ctx->idx * 4;
 			break;
 
 		/*
-- 
2.31.1


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

* [RESEND PATCH v4 3/8] bpf powerpc: refactor JIT compiler code
@ 2021-10-12 12:30   ` Hari Bathini
  0 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: songliubraving, netdev, john.fastabend, andrii, kpsingh, paulus,
	yhs, bpf, linuxppc-dev, kafai, Hari Bathini

Refactor powerpc LDX JITing code to simplify adding BPF_PROBE_MEM
support.

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

Changes in v4:
* Dropped the default case in the switch statement for bpf size.
* Dropped explicit fallthrough statement for empty switch cases.


 arch/powerpc/net/bpf_jit_comp32.c | 33 ++++++++++++++++++-------------
 arch/powerpc/net/bpf_jit_comp64.c | 31 +++++++++++++++++------------
 2 files changed, 37 insertions(+), 27 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 903f945601c0..8b2ac1c27f1f 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -284,6 +284,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		u32 src_reg = bpf_to_ppc(ctx, insn[i].src_reg);
 		u32 src_reg_h = src_reg - 1;
 		u32 tmp_reg = bpf_to_ppc(ctx, TMP_REG);
+		u32 size = BPF_SIZE(code);
 		s16 off = insn[i].off;
 		s32 imm = insn[i].imm;
 		bool func_addr_fixed;
@@ -812,23 +813,27 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		 * BPF_LDX
 		 */
 		case BPF_LDX | BPF_MEM | BPF_B: /* dst = *(u8 *)(ul) (src + off) */
-			EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
-			if (!fp->aux->verifier_zext)
-				EMIT(PPC_RAW_LI(dst_reg_h, 0));
-			break;
 		case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */
-			EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off));
-			if (!fp->aux->verifier_zext)
-				EMIT(PPC_RAW_LI(dst_reg_h, 0));
-			break;
 		case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */
-			EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off));
-			if (!fp->aux->verifier_zext)
-				EMIT(PPC_RAW_LI(dst_reg_h, 0));
-			break;
 		case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */
-			EMIT(PPC_RAW_LWZ(dst_reg_h, src_reg, off));
-			EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off + 4));
+			switch (size) {
+			case BPF_B:
+				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
+				break;
+			case BPF_H:
+				EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off));
+				break;
+			case BPF_W:
+				EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off));
+				break;
+			case BPF_DW:
+				EMIT(PPC_RAW_LWZ(dst_reg_h, src_reg, off));
+				EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off + 4));
+				break;
+			}
+
+			if (size != BPF_DW && !fp->aux->verifier_zext)
+				EMIT(PPC_RAW_LI(dst_reg_h, 0));
 			break;
 
 		/*
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index b25bf9b11b9d..ad852f15ca61 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -311,6 +311,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		u32 code = insn[i].code;
 		u32 dst_reg = b2p[insn[i].dst_reg];
 		u32 src_reg = b2p[insn[i].src_reg];
+		u32 size = BPF_SIZE(code);
 		s16 off = insn[i].off;
 		s32 imm = insn[i].imm;
 		bool func_addr_fixed;
@@ -778,25 +779,29 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		 */
 		/* dst = *(u8 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_B:
-			EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
-			if (insn_is_zext(&insn[i + 1]))
-				addrs[++i] = ctx->idx * 4;
-			break;
 		/* dst = *(u16 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_H:
-			EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off));
-			if (insn_is_zext(&insn[i + 1]))
-				addrs[++i] = ctx->idx * 4;
-			break;
 		/* dst = *(u32 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_W:
-			EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off));
-			if (insn_is_zext(&insn[i + 1]))
-				addrs[++i] = ctx->idx * 4;
-			break;
 		/* dst = *(u64 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_DW:
-			PPC_BPF_LL(dst_reg, src_reg, off);
+			switch (size) {
+			case BPF_B:
+				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
+				break;
+			case BPF_H:
+				EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off));
+				break;
+			case BPF_W:
+				EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off));
+				break;
+			case BPF_DW:
+				PPC_BPF_LL(dst_reg, src_reg, off);
+				break;
+			}
+
+			if (size != BPF_DW && insn_is_zext(&insn[i + 1]))
+				addrs[++i] = ctx->idx * 4;
 			break;
 
 		/*
-- 
2.31.1


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

* [RESEND PATCH v4 4/8] powerpc/ppc-opcode: introduce PPC_RAW_BRANCH() macro
  2021-10-12 12:30 ` Hari Bathini
@ 2021-10-12 12:30   ` Hari Bathini
  -1 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev, Hari Bathini

Define and use PPC_RAW_BRANCH() macro instead of open coding it. This
macro is used while adding BPF_PROBE_MEM support.

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

* No changes in v4.


 arch/powerpc/include/asm/ppc-opcode.h | 2 ++
 arch/powerpc/net/bpf_jit.h            | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index baea657bc868..f50213e2a3e0 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -566,6 +566,8 @@
 #define PPC_RAW_MTSPR(spr, d)		(0x7c0003a6 | ___PPC_RS(d) | __PPC_SPR(spr))
 #define PPC_RAW_EIEIO()			(0x7c0006ac)
 
+#define PPC_RAW_BRANCH(addr)		(PPC_INST_BRANCH | ((addr) & 0x03fffffc))
+
 /* Deal with instructions that older assemblers aren't aware of */
 #define	PPC_BCCTR_FLUSH		stringify_in_c(.long PPC_INST_BCCTR_FLUSH)
 #define	PPC_CP_ABORT		stringify_in_c(.long PPC_RAW_CP_ABORT)
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 7145b651fc2a..6a945f6211f4 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -31,7 +31,7 @@
 			pr_err_ratelimited("Branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx);			\
 			return -ERANGE;					      \
 		}							      \
-		EMIT(PPC_INST_BRANCH | (offset & 0x03fffffc));		      \
+		EMIT(PPC_RAW_BRANCH(offset));				      \
 	} while (0)
 
 /* blr; (unconditional 'branch' with link) to absolute address */
-- 
2.31.1


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

* [RESEND PATCH v4 4/8] powerpc/ppc-opcode: introduce PPC_RAW_BRANCH() macro
@ 2021-10-12 12:30   ` Hari Bathini
  0 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: songliubraving, netdev, john.fastabend, andrii, kpsingh, paulus,
	yhs, bpf, linuxppc-dev, kafai, Hari Bathini

Define and use PPC_RAW_BRANCH() macro instead of open coding it. This
macro is used while adding BPF_PROBE_MEM support.

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

* No changes in v4.


 arch/powerpc/include/asm/ppc-opcode.h | 2 ++
 arch/powerpc/net/bpf_jit.h            | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index baea657bc868..f50213e2a3e0 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -566,6 +566,8 @@
 #define PPC_RAW_MTSPR(spr, d)		(0x7c0003a6 | ___PPC_RS(d) | __PPC_SPR(spr))
 #define PPC_RAW_EIEIO()			(0x7c0006ac)
 
+#define PPC_RAW_BRANCH(addr)		(PPC_INST_BRANCH | ((addr) & 0x03fffffc))
+
 /* Deal with instructions that older assemblers aren't aware of */
 #define	PPC_BCCTR_FLUSH		stringify_in_c(.long PPC_INST_BCCTR_FLUSH)
 #define	PPC_CP_ABORT		stringify_in_c(.long PPC_RAW_CP_ABORT)
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 7145b651fc2a..6a945f6211f4 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -31,7 +31,7 @@
 			pr_err_ratelimited("Branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx);			\
 			return -ERANGE;					      \
 		}							      \
-		EMIT(PPC_INST_BRANCH | (offset & 0x03fffffc));		      \
+		EMIT(PPC_RAW_BRANCH(offset));				      \
 	} while (0)
 
 /* blr; (unconditional 'branch' with link) to absolute address */
-- 
2.31.1


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

* [RESEND PATCH v4 5/8] bpf ppc64: Add BPF_PROBE_MEM support for JIT
  2021-10-12 12:30 ` Hari Bathini
@ 2021-10-12 12:30   ` Hari Bathini
  -1 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev, Ravi Bangoria, Hari Bathini

From: Ravi Bangoria <ravi.bangoria@linux.ibm.com>

BPF load instruction with BPF_PROBE_MEM mode can cause a fault
inside kernel. Append exception table for such instructions
within BPF program.

Unlike other archs which uses extable 'fixup' field to pass dest_reg
and nip, BPF exception table on PowerPC follows the generic PowerPC
exception table design, where it populates both fixup and extable
sections within BPF program. fixup section contains two instructions,
first instruction clears dest_reg and 2nd jumps to next instruction
in the BPF code. extable 'insn' field contains relative offset of
the instruction and 'fixup' field contains relative offset of the
fixup entry. Example layout of BPF program with extable present:

             +------------------+
             |                  |
             |                  |
   0x4020 -->| ld   r27,4(r3)   |
             |                  |
             |                  |
   0x40ac -->| lwz  r3,0(r4)    |
             |                  |
             |                  |
             |------------------|
   0x4280 -->| li  r27,0        |  \ fixup entry
             | b   0x4024       |  /
   0x4288 -->| li  r3,0         |
             | b   0x40b0       |
             |------------------|
   0x4290 -->| insn=0xfffffd90  |  \ extable entry
             | fixup=0xffffffec |  /
   0x4298 -->| insn=0xfffffe14  |
             | fixup=0xffffffec |
             +------------------+

   (Addresses shown here are chosen random, not real)

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

Changes in v4:
* Dropped explicit fallthrough statement for empty switch cases.


 arch/powerpc/net/bpf_jit.h        |  8 +++-
 arch/powerpc/net/bpf_jit_comp.c   | 66 ++++++++++++++++++++++++++++---
 arch/powerpc/net/bpf_jit_comp32.c |  2 +-
 arch/powerpc/net/bpf_jit_comp64.c | 13 +++++-
 4 files changed, 80 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 6a945f6211f4..444c9debce91 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -150,8 +150,11 @@ struct codegen_context {
 	unsigned int idx;
 	unsigned int stack_size;
 	int b2p[ARRAY_SIZE(b2p)];
+	unsigned int exentry_idx;
 };
 
+#define BPF_FIXUP_LEN	2 /* Two instructions => 8 bytes */
+
 static inline void bpf_flush_icache(void *start, void *end)
 {
 	smp_wmb();	/* smp write barrier */
@@ -175,11 +178,14 @@ static inline void bpf_clear_seen_register(struct codegen_context *ctx, int i)
 
 void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func);
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs);
+		       u32 *addrs, int pass);
 void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx);
 void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx);
 void bpf_jit_realloc_regs(struct codegen_context *ctx);
 
+int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx,
+			  int insn_idx, int jmp_off, int dst_reg);
+
 #endif
 
 #endif
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index f7972b2c21f6..f02457c6b54f 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -101,6 +101,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	struct bpf_prog *tmp_fp;
 	bool bpf_blinded = false;
 	bool extra_pass = false;
+	u32 extable_len;
+	u32 fixup_len;
 
 	if (!fp->jit_requested)
 		return org_fp;
@@ -131,7 +133,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 		image = jit_data->image;
 		bpf_hdr = jit_data->header;
 		proglen = jit_data->proglen;
-		alloclen = proglen + FUNCTION_DESCR_SIZE;
 		extra_pass = true;
 		goto skip_init_ctx;
 	}
@@ -149,7 +150,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	cgctx.stack_size = round_up(fp->aux->stack_depth, 16);
 
 	/* Scouting faux-generate pass 0 */
-	if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) {
+	if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0)) {
 		/* We hit something illegal or unsupported. */
 		fp = org_fp;
 		goto out_addrs;
@@ -162,7 +163,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	 */
 	if (cgctx.seen & SEEN_TAILCALL) {
 		cgctx.idx = 0;
-		if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) {
+		if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0)) {
 			fp = org_fp;
 			goto out_addrs;
 		}
@@ -177,8 +178,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	bpf_jit_build_prologue(0, &cgctx);
 	bpf_jit_build_epilogue(0, &cgctx);
 
+	fixup_len = fp->aux->num_exentries * BPF_FIXUP_LEN * 4;
+	extable_len = fp->aux->num_exentries * sizeof(struct exception_table_entry);
+
 	proglen = cgctx.idx * 4;
-	alloclen = proglen + FUNCTION_DESCR_SIZE;
+	alloclen = proglen + FUNCTION_DESCR_SIZE + fixup_len + extable_len;
 
 	bpf_hdr = bpf_jit_binary_alloc(alloclen, &image, 4, bpf_jit_fill_ill_insns);
 	if (!bpf_hdr) {
@@ -186,6 +190,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 		goto out_addrs;
 	}
 
+	if (extable_len)
+		fp->aux->extable = (void *)image + FUNCTION_DESCR_SIZE + proglen + fixup_len;
+
 skip_init_ctx:
 	code_base = (u32 *)(image + FUNCTION_DESCR_SIZE);
 
@@ -210,7 +217,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 		/* Now build the prologue, body code & epilogue for real. */
 		cgctx.idx = 0;
 		bpf_jit_build_prologue(code_base, &cgctx);
-		if (bpf_jit_build_body(fp, code_base, &cgctx, addrs)) {
+		if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, pass)) {
 			bpf_jit_binary_free(bpf_hdr);
 			fp = org_fp;
 			goto out_addrs;
@@ -238,7 +245,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 
 	fp->bpf_func = (void *)image;
 	fp->jited = 1;
-	fp->jited_len = alloclen;
+	fp->jited_len = proglen + FUNCTION_DESCR_SIZE;
 
 	bpf_flush_icache(bpf_hdr, (u8 *)bpf_hdr + (bpf_hdr->pages * PAGE_SIZE));
 	bpf_jit_binary_lock_ro(bpf_hdr);
@@ -262,3 +269,50 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 
 	return fp;
 }
+
+/*
+ * The caller should check for (BPF_MODE(code) == BPF_PROBE_MEM) before calling
+ * this function, as this only applies to BPF_PROBE_MEM, for now.
+ */
+int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx,
+			  int insn_idx, int jmp_off, int dst_reg)
+{
+	off_t offset;
+	unsigned long pc;
+	struct exception_table_entry *ex;
+	u32 *fixup;
+
+	/* Populate extable entries only in the last pass */
+	if (pass != 2)
+		return 0;
+
+	if (!fp->aux->extable ||
+	    WARN_ON_ONCE(ctx->exentry_idx >= fp->aux->num_exentries))
+		return -EINVAL;
+
+	pc = (unsigned long)&image[insn_idx];
+
+	fixup = (void *)fp->aux->extable -
+		(fp->aux->num_exentries * BPF_FIXUP_LEN * 4) +
+		(ctx->exentry_idx * BPF_FIXUP_LEN * 4);
+
+	fixup[0] = PPC_RAW_LI(dst_reg, 0);
+
+	fixup[BPF_FIXUP_LEN - 1] =
+		PPC_RAW_BRANCH((long)(pc + jmp_off) - (long)&fixup[BPF_FIXUP_LEN - 1]);
+
+	ex = &fp->aux->extable[ctx->exentry_idx];
+
+	offset = pc - (long)&ex->insn;
+	if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN))
+		return -ERANGE;
+	ex->insn = offset;
+
+	offset = (long)fixup - (long)&ex->fixup;
+	if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN))
+		return -ERANGE;
+	ex->fixup = offset;
+
+	ctx->exentry_idx++;
+	return 0;
+}
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 8b2ac1c27f1f..54e7cef3e1f2 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -268,7 +268,7 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
 
 /* Assemble the body code between the prologue & epilogue */
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs)
+		       u32 *addrs, int pass)
 {
 	const struct bpf_insn *insn = fp->insnsi;
 	int flen = fp->len;
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index ad852f15ca61..ede8cb3e453f 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -297,7 +297,7 @@ asm (
 
 /* Assemble the body code between the prologue & epilogue */
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs)
+		       u32 *addrs, int pass)
 {
 	enum stf_barrier_type stf_barrier = stf_barrier_type_get();
 	const struct bpf_insn *insn = fp->insnsi;
@@ -779,12 +779,16 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		 */
 		/* dst = *(u8 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_B:
+		case BPF_LDX | BPF_PROBE_MEM | BPF_B:
 		/* dst = *(u16 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_H:
+		case BPF_LDX | BPF_PROBE_MEM | BPF_H:
 		/* dst = *(u32 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_W:
+		case BPF_LDX | BPF_PROBE_MEM | BPF_W:
 		/* dst = *(u64 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_DW:
+		case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
 			switch (size) {
 			case BPF_B:
 				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
@@ -802,6 +806,13 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 
 			if (size != BPF_DW && insn_is_zext(&insn[i + 1]))
 				addrs[++i] = ctx->idx * 4;
+
+			if (BPF_MODE(code) == BPF_PROBE_MEM) {
+				ret = bpf_add_extable_entry(fp, image, pass, ctx, ctx->idx - 1,
+							    4, dst_reg);
+				if (ret)
+					return ret;
+			}
 			break;
 
 		/*
-- 
2.31.1


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

* [RESEND PATCH v4 5/8] bpf ppc64: Add BPF_PROBE_MEM support for JIT
@ 2021-10-12 12:30   ` Hari Bathini
  0 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: Ravi Bangoria, songliubraving, netdev, john.fastabend, andrii,
	kpsingh, paulus, yhs, bpf, linuxppc-dev, kafai, Hari Bathini

From: Ravi Bangoria <ravi.bangoria@linux.ibm.com>

BPF load instruction with BPF_PROBE_MEM mode can cause a fault
inside kernel. Append exception table for such instructions
within BPF program.

Unlike other archs which uses extable 'fixup' field to pass dest_reg
and nip, BPF exception table on PowerPC follows the generic PowerPC
exception table design, where it populates both fixup and extable
sections within BPF program. fixup section contains two instructions,
first instruction clears dest_reg and 2nd jumps to next instruction
in the BPF code. extable 'insn' field contains relative offset of
the instruction and 'fixup' field contains relative offset of the
fixup entry. Example layout of BPF program with extable present:

             +------------------+
             |                  |
             |                  |
   0x4020 -->| ld   r27,4(r3)   |
             |                  |
             |                  |
   0x40ac -->| lwz  r3,0(r4)    |
             |                  |
             |                  |
             |------------------|
   0x4280 -->| li  r27,0        |  \ fixup entry
             | b   0x4024       |  /
   0x4288 -->| li  r3,0         |
             | b   0x40b0       |
             |------------------|
   0x4290 -->| insn=0xfffffd90  |  \ extable entry
             | fixup=0xffffffec |  /
   0x4298 -->| insn=0xfffffe14  |
             | fixup=0xffffffec |
             +------------------+

   (Addresses shown here are chosen random, not real)

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

Changes in v4:
* Dropped explicit fallthrough statement for empty switch cases.


 arch/powerpc/net/bpf_jit.h        |  8 +++-
 arch/powerpc/net/bpf_jit_comp.c   | 66 ++++++++++++++++++++++++++++---
 arch/powerpc/net/bpf_jit_comp32.c |  2 +-
 arch/powerpc/net/bpf_jit_comp64.c | 13 +++++-
 4 files changed, 80 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 6a945f6211f4..444c9debce91 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -150,8 +150,11 @@ struct codegen_context {
 	unsigned int idx;
 	unsigned int stack_size;
 	int b2p[ARRAY_SIZE(b2p)];
+	unsigned int exentry_idx;
 };
 
+#define BPF_FIXUP_LEN	2 /* Two instructions => 8 bytes */
+
 static inline void bpf_flush_icache(void *start, void *end)
 {
 	smp_wmb();	/* smp write barrier */
@@ -175,11 +178,14 @@ static inline void bpf_clear_seen_register(struct codegen_context *ctx, int i)
 
 void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func);
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs);
+		       u32 *addrs, int pass);
 void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx);
 void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx);
 void bpf_jit_realloc_regs(struct codegen_context *ctx);
 
+int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx,
+			  int insn_idx, int jmp_off, int dst_reg);
+
 #endif
 
 #endif
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index f7972b2c21f6..f02457c6b54f 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -101,6 +101,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	struct bpf_prog *tmp_fp;
 	bool bpf_blinded = false;
 	bool extra_pass = false;
+	u32 extable_len;
+	u32 fixup_len;
 
 	if (!fp->jit_requested)
 		return org_fp;
@@ -131,7 +133,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 		image = jit_data->image;
 		bpf_hdr = jit_data->header;
 		proglen = jit_data->proglen;
-		alloclen = proglen + FUNCTION_DESCR_SIZE;
 		extra_pass = true;
 		goto skip_init_ctx;
 	}
@@ -149,7 +150,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	cgctx.stack_size = round_up(fp->aux->stack_depth, 16);
 
 	/* Scouting faux-generate pass 0 */
-	if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) {
+	if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0)) {
 		/* We hit something illegal or unsupported. */
 		fp = org_fp;
 		goto out_addrs;
@@ -162,7 +163,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	 */
 	if (cgctx.seen & SEEN_TAILCALL) {
 		cgctx.idx = 0;
-		if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) {
+		if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0)) {
 			fp = org_fp;
 			goto out_addrs;
 		}
@@ -177,8 +178,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	bpf_jit_build_prologue(0, &cgctx);
 	bpf_jit_build_epilogue(0, &cgctx);
 
+	fixup_len = fp->aux->num_exentries * BPF_FIXUP_LEN * 4;
+	extable_len = fp->aux->num_exentries * sizeof(struct exception_table_entry);
+
 	proglen = cgctx.idx * 4;
-	alloclen = proglen + FUNCTION_DESCR_SIZE;
+	alloclen = proglen + FUNCTION_DESCR_SIZE + fixup_len + extable_len;
 
 	bpf_hdr = bpf_jit_binary_alloc(alloclen, &image, 4, bpf_jit_fill_ill_insns);
 	if (!bpf_hdr) {
@@ -186,6 +190,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 		goto out_addrs;
 	}
 
+	if (extable_len)
+		fp->aux->extable = (void *)image + FUNCTION_DESCR_SIZE + proglen + fixup_len;
+
 skip_init_ctx:
 	code_base = (u32 *)(image + FUNCTION_DESCR_SIZE);
 
@@ -210,7 +217,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 		/* Now build the prologue, body code & epilogue for real. */
 		cgctx.idx = 0;
 		bpf_jit_build_prologue(code_base, &cgctx);
-		if (bpf_jit_build_body(fp, code_base, &cgctx, addrs)) {
+		if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, pass)) {
 			bpf_jit_binary_free(bpf_hdr);
 			fp = org_fp;
 			goto out_addrs;
@@ -238,7 +245,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 
 	fp->bpf_func = (void *)image;
 	fp->jited = 1;
-	fp->jited_len = alloclen;
+	fp->jited_len = proglen + FUNCTION_DESCR_SIZE;
 
 	bpf_flush_icache(bpf_hdr, (u8 *)bpf_hdr + (bpf_hdr->pages * PAGE_SIZE));
 	bpf_jit_binary_lock_ro(bpf_hdr);
@@ -262,3 +269,50 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 
 	return fp;
 }
+
+/*
+ * The caller should check for (BPF_MODE(code) == BPF_PROBE_MEM) before calling
+ * this function, as this only applies to BPF_PROBE_MEM, for now.
+ */
+int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx,
+			  int insn_idx, int jmp_off, int dst_reg)
+{
+	off_t offset;
+	unsigned long pc;
+	struct exception_table_entry *ex;
+	u32 *fixup;
+
+	/* Populate extable entries only in the last pass */
+	if (pass != 2)
+		return 0;
+
+	if (!fp->aux->extable ||
+	    WARN_ON_ONCE(ctx->exentry_idx >= fp->aux->num_exentries))
+		return -EINVAL;
+
+	pc = (unsigned long)&image[insn_idx];
+
+	fixup = (void *)fp->aux->extable -
+		(fp->aux->num_exentries * BPF_FIXUP_LEN * 4) +
+		(ctx->exentry_idx * BPF_FIXUP_LEN * 4);
+
+	fixup[0] = PPC_RAW_LI(dst_reg, 0);
+
+	fixup[BPF_FIXUP_LEN - 1] =
+		PPC_RAW_BRANCH((long)(pc + jmp_off) - (long)&fixup[BPF_FIXUP_LEN - 1]);
+
+	ex = &fp->aux->extable[ctx->exentry_idx];
+
+	offset = pc - (long)&ex->insn;
+	if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN))
+		return -ERANGE;
+	ex->insn = offset;
+
+	offset = (long)fixup - (long)&ex->fixup;
+	if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN))
+		return -ERANGE;
+	ex->fixup = offset;
+
+	ctx->exentry_idx++;
+	return 0;
+}
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 8b2ac1c27f1f..54e7cef3e1f2 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -268,7 +268,7 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
 
 /* Assemble the body code between the prologue & epilogue */
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs)
+		       u32 *addrs, int pass)
 {
 	const struct bpf_insn *insn = fp->insnsi;
 	int flen = fp->len;
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index ad852f15ca61..ede8cb3e453f 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -297,7 +297,7 @@ asm (
 
 /* Assemble the body code between the prologue & epilogue */
 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
-		       u32 *addrs)
+		       u32 *addrs, int pass)
 {
 	enum stf_barrier_type stf_barrier = stf_barrier_type_get();
 	const struct bpf_insn *insn = fp->insnsi;
@@ -779,12 +779,16 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		 */
 		/* dst = *(u8 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_B:
+		case BPF_LDX | BPF_PROBE_MEM | BPF_B:
 		/* dst = *(u16 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_H:
+		case BPF_LDX | BPF_PROBE_MEM | BPF_H:
 		/* dst = *(u32 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_W:
+		case BPF_LDX | BPF_PROBE_MEM | BPF_W:
 		/* dst = *(u64 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_DW:
+		case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
 			switch (size) {
 			case BPF_B:
 				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
@@ -802,6 +806,13 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 
 			if (size != BPF_DW && insn_is_zext(&insn[i + 1]))
 				addrs[++i] = ctx->idx * 4;
+
+			if (BPF_MODE(code) == BPF_PROBE_MEM) {
+				ret = bpf_add_extable_entry(fp, image, pass, ctx, ctx->idx - 1,
+							    4, dst_reg);
+				if (ret)
+					return ret;
+			}
 			break;
 
 		/*
-- 
2.31.1


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

* [RESEND PATCH v4 6/8] bpf ppc64: Access only if addr is kernel address
  2021-10-12 12:30 ` Hari Bathini
@ 2021-10-12 12:30   ` Hari Bathini
  -1 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev, Ravi Bangoria, Hari Bathini

From: Ravi Bangoria <ravi.bangoria@linux.ibm.com>

On PPC64 with KUAP enabled, any kernel code which wants to
access userspace needs to be surrounded by disable-enable KUAP.
But that is not happening for BPF_PROBE_MEM load instruction.
So, when BPF program tries to access invalid userspace address,
page-fault handler considers it as bad KUAP fault:

  Kernel attempted to read user page (d0000000) - exploit attempt? (uid: 0)

Considering the fact that PTR_TO_BTF_ID (which uses BPF_PROBE_MEM
mode) could either be a valid kernel pointer or NULL but should
never be a pointer to userspace address, execute BPF_PROBE_MEM load
only if addr is kernel address, otherwise set dst_reg=0 and move on.

This will catch NULL, valid or invalid userspace pointers. Only bad
kernel pointer will be handled by BPF exception table.

[Alexei suggested for x86]
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

Changes in v4:
* Used IS_ENABLED() instead of #ifdef.
* Dropped the else case that is not applicable for PPC64.


 arch/powerpc/net/bpf_jit_comp64.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index ede8cb3e453f..472d4a551945 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -789,6 +789,32 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		/* dst = *(u64 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_DW:
 		case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
+			/*
+			 * As PTR_TO_BTF_ID that uses BPF_PROBE_MEM mode could either be a valid
+			 * kernel pointer or NULL but not a userspace address, execute BPF_PROBE_MEM
+			 * load only if addr is kernel address (see is_kernel_addr()), otherwise
+			 * set dst_reg=0 and move on.
+			 */
+			if (BPF_MODE(code) == BPF_PROBE_MEM) {
+				EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], src_reg, off));
+				if (IS_ENABLED(CONFIG_PPC_BOOK3E_64))
+					PPC_LI64(b2p[TMP_REG_2], 0x8000000000000000ul);
+				else /* BOOK3S_64 */
+					PPC_LI64(b2p[TMP_REG_2], PAGE_OFFSET);
+				EMIT(PPC_RAW_CMPLD(b2p[TMP_REG_1], b2p[TMP_REG_2]));
+				PPC_BCC(COND_GT, (ctx->idx + 4) * 4);
+				EMIT(PPC_RAW_LI(dst_reg, 0));
+				/*
+				 * Check if 'off' is word aligned because PPC_BPF_LL()
+				 * (BPF_DW case) generates two instructions if 'off' is not
+				 * word-aligned and one instruction otherwise.
+				 */
+				if (BPF_SIZE(code) == BPF_DW && (off & 3))
+					PPC_JMP((ctx->idx + 3) * 4);
+				else
+					PPC_JMP((ctx->idx + 2) * 4);
+			}
+
 			switch (size) {
 			case BPF_B:
 				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
-- 
2.31.1


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

* [RESEND PATCH v4 6/8] bpf ppc64: Access only if addr is kernel address
@ 2021-10-12 12:30   ` Hari Bathini
  0 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: Ravi Bangoria, songliubraving, netdev, john.fastabend, andrii,
	kpsingh, paulus, yhs, bpf, linuxppc-dev, kafai, Hari Bathini

From: Ravi Bangoria <ravi.bangoria@linux.ibm.com>

On PPC64 with KUAP enabled, any kernel code which wants to
access userspace needs to be surrounded by disable-enable KUAP.
But that is not happening for BPF_PROBE_MEM load instruction.
So, when BPF program tries to access invalid userspace address,
page-fault handler considers it as bad KUAP fault:

  Kernel attempted to read user page (d0000000) - exploit attempt? (uid: 0)

Considering the fact that PTR_TO_BTF_ID (which uses BPF_PROBE_MEM
mode) could either be a valid kernel pointer or NULL but should
never be a pointer to userspace address, execute BPF_PROBE_MEM load
only if addr is kernel address, otherwise set dst_reg=0 and move on.

This will catch NULL, valid or invalid userspace pointers. Only bad
kernel pointer will be handled by BPF exception table.

[Alexei suggested for x86]
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

Changes in v4:
* Used IS_ENABLED() instead of #ifdef.
* Dropped the else case that is not applicable for PPC64.


 arch/powerpc/net/bpf_jit_comp64.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index ede8cb3e453f..472d4a551945 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -789,6 +789,32 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		/* dst = *(u64 *)(ul) (src + off) */
 		case BPF_LDX | BPF_MEM | BPF_DW:
 		case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
+			/*
+			 * As PTR_TO_BTF_ID that uses BPF_PROBE_MEM mode could either be a valid
+			 * kernel pointer or NULL but not a userspace address, execute BPF_PROBE_MEM
+			 * load only if addr is kernel address (see is_kernel_addr()), otherwise
+			 * set dst_reg=0 and move on.
+			 */
+			if (BPF_MODE(code) == BPF_PROBE_MEM) {
+				EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], src_reg, off));
+				if (IS_ENABLED(CONFIG_PPC_BOOK3E_64))
+					PPC_LI64(b2p[TMP_REG_2], 0x8000000000000000ul);
+				else /* BOOK3S_64 */
+					PPC_LI64(b2p[TMP_REG_2], PAGE_OFFSET);
+				EMIT(PPC_RAW_CMPLD(b2p[TMP_REG_1], b2p[TMP_REG_2]));
+				PPC_BCC(COND_GT, (ctx->idx + 4) * 4);
+				EMIT(PPC_RAW_LI(dst_reg, 0));
+				/*
+				 * Check if 'off' is word aligned because PPC_BPF_LL()
+				 * (BPF_DW case) generates two instructions if 'off' is not
+				 * word-aligned and one instruction otherwise.
+				 */
+				if (BPF_SIZE(code) == BPF_DW && (off & 3))
+					PPC_JMP((ctx->idx + 3) * 4);
+				else
+					PPC_JMP((ctx->idx + 2) * 4);
+			}
+
 			switch (size) {
 			case BPF_B:
 				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
-- 
2.31.1


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

* [RESEND PATCH v4 7/8] bpf ppc32: Add BPF_PROBE_MEM support for JIT
  2021-10-12 12:30 ` Hari Bathini
@ 2021-10-12 12:30   ` Hari Bathini
  -1 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev, Hari Bathini

BPF load instruction with BPF_PROBE_MEM mode can cause a fault
inside kernel. Append exception table for such instructions
within BPF program.

Unlike other archs which uses extable 'fixup' field to pass dest_reg
and nip, BPF exception table on PowerPC follows the generic PowerPC
exception table design, where it populates both fixup and extable
sections within BPF program. fixup section contains 3 instructions,
first 2 instructions clear dest_reg (lower & higher 32-bit registers)
and last instruction jumps to next instruction in the BPF code.
extable 'insn' field contains relative offset of the instruction and
'fixup' field contains relative offset of the fixup entry. Example
layout of BPF program with extable present:

             +------------------+
             |                  |
             |                  |
   0x4020 -->| lwz   r28,4(r4)  |
             |                  |
             |                  |
   0x40ac -->| lwz  r3,0(r24)   |
             | lwz  r4,4(r24)   |
             |                  |
             |                  |
             |------------------|
   0x4278 -->| li  r28,0        |  \
             | li  r27,0        |  | fixup entry
             | b   0x4024       |  /
   0x4284 -->| li  r4,0         |
             | li  r3,0         |
             | b   0x40b4       |
             |------------------|
   0x4290 -->| insn=0xfffffd90  |  \ extable entry
             | fixup=0xffffffe4 |  /
   0x4298 -->| insn=0xfffffe14  |
             | fixup=0xffffffe8 |
             +------------------+

   (Addresses shown here are chosen random, not real)

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

Changes in v4:
* Dropped explicit fallthrough statement for empty switch cases.


 arch/powerpc/net/bpf_jit.h        |  4 ++++
 arch/powerpc/net/bpf_jit_comp.c   |  2 ++
 arch/powerpc/net/bpf_jit_comp32.c | 30 ++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 444c9debce91..b20a2a83a6e7 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -153,7 +153,11 @@ struct codegen_context {
 	unsigned int exentry_idx;
 };
 
+#ifdef CONFIG_PPC32
+#define BPF_FIXUP_LEN	3 /* Three instructions => 12 bytes */
+#else
 #define BPF_FIXUP_LEN	2 /* Two instructions => 8 bytes */
+#endif
 
 static inline void bpf_flush_icache(void *start, void *end)
 {
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index f02457c6b54f..1a0041997050 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -297,6 +297,8 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code
 		(ctx->exentry_idx * BPF_FIXUP_LEN * 4);
 
 	fixup[0] = PPC_RAW_LI(dst_reg, 0);
+	if (IS_ENABLED(CONFIG_PPC32))
+		fixup[1] = PPC_RAW_LI(dst_reg - 1, 0); /* clear higher 32-bit register too */
 
 	fixup[BPF_FIXUP_LEN - 1] =
 		PPC_RAW_BRANCH((long)(pc + jmp_off) - (long)&fixup[BPF_FIXUP_LEN - 1]);
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 54e7cef3e1f2..5dc45e393d1d 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -813,9 +813,13 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		 * BPF_LDX
 		 */
 		case BPF_LDX | BPF_MEM | BPF_B: /* dst = *(u8 *)(ul) (src + off) */
+		case BPF_LDX | BPF_PROBE_MEM | BPF_B:
 		case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */
+		case BPF_LDX | BPF_PROBE_MEM | BPF_H:
 		case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */
+		case BPF_LDX | BPF_PROBE_MEM | BPF_W:
 		case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */
+		case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
 			switch (size) {
 			case BPF_B:
 				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
@@ -834,6 +838,32 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 
 			if (size != BPF_DW && !fp->aux->verifier_zext)
 				EMIT(PPC_RAW_LI(dst_reg_h, 0));
+
+			if (BPF_MODE(code) == BPF_PROBE_MEM) {
+				int insn_idx = ctx->idx - 1;
+				int jmp_off = 4;
+
+				/*
+				 * In case of BPF_DW, two lwz instructions are emitted, one
+				 * for higher 32-bit and another for lower 32-bit. So, set
+				 * ex->insn to the first of the two and jump over both
+				 * instructions in fixup.
+				 *
+				 * Similarly, with !verifier_zext, two instructions are
+				 * emitted for BPF_B/H/W case. So, set ex->insn to the
+				 * instruction that could fault and skip over both
+				 * instructions.
+				 */
+				if (size == BPF_DW || !fp->aux->verifier_zext) {
+					insn_idx -= 1;
+					jmp_off += 4;
+				}
+
+				ret = bpf_add_extable_entry(fp, image, pass, ctx, insn_idx,
+							    jmp_off, dst_reg);
+				if (ret)
+					return ret;
+			}
 			break;
 
 		/*
-- 
2.31.1


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

* [RESEND PATCH v4 7/8] bpf ppc32: Add BPF_PROBE_MEM support for JIT
@ 2021-10-12 12:30   ` Hari Bathini
  0 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: songliubraving, netdev, john.fastabend, andrii, kpsingh, paulus,
	yhs, bpf, linuxppc-dev, kafai, Hari Bathini

BPF load instruction with BPF_PROBE_MEM mode can cause a fault
inside kernel. Append exception table for such instructions
within BPF program.

Unlike other archs which uses extable 'fixup' field to pass dest_reg
and nip, BPF exception table on PowerPC follows the generic PowerPC
exception table design, where it populates both fixup and extable
sections within BPF program. fixup section contains 3 instructions,
first 2 instructions clear dest_reg (lower & higher 32-bit registers)
and last instruction jumps to next instruction in the BPF code.
extable 'insn' field contains relative offset of the instruction and
'fixup' field contains relative offset of the fixup entry. Example
layout of BPF program with extable present:

             +------------------+
             |                  |
             |                  |
   0x4020 -->| lwz   r28,4(r4)  |
             |                  |
             |                  |
   0x40ac -->| lwz  r3,0(r24)   |
             | lwz  r4,4(r24)   |
             |                  |
             |                  |
             |------------------|
   0x4278 -->| li  r28,0        |  \
             | li  r27,0        |  | fixup entry
             | b   0x4024       |  /
   0x4284 -->| li  r4,0         |
             | li  r3,0         |
             | b   0x40b4       |
             |------------------|
   0x4290 -->| insn=0xfffffd90  |  \ extable entry
             | fixup=0xffffffe4 |  /
   0x4298 -->| insn=0xfffffe14  |
             | fixup=0xffffffe8 |
             +------------------+

   (Addresses shown here are chosen random, not real)

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

Changes in v4:
* Dropped explicit fallthrough statement for empty switch cases.


 arch/powerpc/net/bpf_jit.h        |  4 ++++
 arch/powerpc/net/bpf_jit_comp.c   |  2 ++
 arch/powerpc/net/bpf_jit_comp32.c | 30 ++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 444c9debce91..b20a2a83a6e7 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -153,7 +153,11 @@ struct codegen_context {
 	unsigned int exentry_idx;
 };
 
+#ifdef CONFIG_PPC32
+#define BPF_FIXUP_LEN	3 /* Three instructions => 12 bytes */
+#else
 #define BPF_FIXUP_LEN	2 /* Two instructions => 8 bytes */
+#endif
 
 static inline void bpf_flush_icache(void *start, void *end)
 {
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index f02457c6b54f..1a0041997050 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -297,6 +297,8 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code
 		(ctx->exentry_idx * BPF_FIXUP_LEN * 4);
 
 	fixup[0] = PPC_RAW_LI(dst_reg, 0);
+	if (IS_ENABLED(CONFIG_PPC32))
+		fixup[1] = PPC_RAW_LI(dst_reg - 1, 0); /* clear higher 32-bit register too */
 
 	fixup[BPF_FIXUP_LEN - 1] =
 		PPC_RAW_BRANCH((long)(pc + jmp_off) - (long)&fixup[BPF_FIXUP_LEN - 1]);
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 54e7cef3e1f2..5dc45e393d1d 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -813,9 +813,13 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		 * BPF_LDX
 		 */
 		case BPF_LDX | BPF_MEM | BPF_B: /* dst = *(u8 *)(ul) (src + off) */
+		case BPF_LDX | BPF_PROBE_MEM | BPF_B:
 		case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */
+		case BPF_LDX | BPF_PROBE_MEM | BPF_H:
 		case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */
+		case BPF_LDX | BPF_PROBE_MEM | BPF_W:
 		case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */
+		case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
 			switch (size) {
 			case BPF_B:
 				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
@@ -834,6 +838,32 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 
 			if (size != BPF_DW && !fp->aux->verifier_zext)
 				EMIT(PPC_RAW_LI(dst_reg_h, 0));
+
+			if (BPF_MODE(code) == BPF_PROBE_MEM) {
+				int insn_idx = ctx->idx - 1;
+				int jmp_off = 4;
+
+				/*
+				 * In case of BPF_DW, two lwz instructions are emitted, one
+				 * for higher 32-bit and another for lower 32-bit. So, set
+				 * ex->insn to the first of the two and jump over both
+				 * instructions in fixup.
+				 *
+				 * Similarly, with !verifier_zext, two instructions are
+				 * emitted for BPF_B/H/W case. So, set ex->insn to the
+				 * instruction that could fault and skip over both
+				 * instructions.
+				 */
+				if (size == BPF_DW || !fp->aux->verifier_zext) {
+					insn_idx -= 1;
+					jmp_off += 4;
+				}
+
+				ret = bpf_add_extable_entry(fp, image, pass, ctx, insn_idx,
+							    jmp_off, dst_reg);
+				if (ret)
+					return ret;
+			}
 			break;
 
 		/*
-- 
2.31.1


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

* [RESEND PATCH v4 8/8] bpf ppc32: Access only if addr is kernel address
  2021-10-12 12:30 ` Hari Bathini
@ 2021-10-12 12:30   ` Hari Bathini
  -1 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev, Hari Bathini

With KUAP enabled, any kernel code which wants to access userspace
needs to be surrounded by disable-enable KUAP. But that is not
happening for BPF_PROBE_MEM load instruction. Though PPC32 does not
support read protection, considering the fact that PTR_TO_BTF_ID
(which uses BPF_PROBE_MEM mode) could either be a valid kernel pointer
or NULL but should never be a pointer to userspace address, execute
BPF_PROBE_MEM load only if addr is kernel address, otherwise set
dst_reg=0 and move on.

This will catch NULL, valid or invalid userspace pointers. Only bad
kernel pointer will be handled by BPF exception table.

[Alexei suggested for x86]
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

Changes in v4:
* Adjusted the emit code to avoid using temporary reg.


 arch/powerpc/net/bpf_jit_comp32.c | 34 +++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 5dc45e393d1d..d3a52cd42f53 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -820,6 +820,40 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		case BPF_LDX | BPF_PROBE_MEM | BPF_W:
 		case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */
 		case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
+			/*
+			 * As PTR_TO_BTF_ID that uses BPF_PROBE_MEM mode could either be a valid
+			 * kernel pointer or NULL but not a userspace address, execute BPF_PROBE_MEM
+			 * load only if addr is kernel address (see is_kernel_addr()), otherwise
+			 * set dst_reg=0 and move on.
+			 */
+			if (BPF_MODE(code) == BPF_PROBE_MEM) {
+				PPC_LI32(_R0, TASK_SIZE - off);
+				EMIT(PPC_RAW_CMPLW(src_reg, _R0));
+				PPC_BCC(COND_GT, (ctx->idx + 5) * 4);
+				EMIT(PPC_RAW_LI(dst_reg, 0));
+				/*
+				 * For BPF_DW case, "li reg_h,0" would be needed when
+				 * !fp->aux->verifier_zext. Emit NOP otherwise.
+				 *
+				 * Note that "li reg_h,0" is emitted for BPF_B/H/W case,
+				 * if necessary. So, jump there insted of emitting an
+				 * additional "li reg_h,0" instruction.
+				 */
+				if (size == BPF_DW && !fp->aux->verifier_zext)
+					EMIT(PPC_RAW_LI(dst_reg_h, 0));
+				else
+					EMIT(PPC_RAW_NOP());
+				/*
+				 * Need to jump two instructions instead of one for BPF_DW case
+				 * as there are two load instructions for dst_reg_h & dst_reg
+				 * respectively.
+				 */
+				if (size == BPF_DW)
+					PPC_JMP((ctx->idx + 3) * 4);
+				else
+					PPC_JMP((ctx->idx + 2) * 4);
+			}
+
 			switch (size) {
 			case BPF_B:
 				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
-- 
2.31.1


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

* [RESEND PATCH v4 8/8] bpf ppc32: Access only if addr is kernel address
@ 2021-10-12 12:30   ` Hari Bathini
  0 siblings, 0 replies; 27+ messages in thread
From: Hari Bathini @ 2021-10-12 12:30 UTC (permalink / raw)
  To: naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: songliubraving, netdev, john.fastabend, andrii, kpsingh, paulus,
	yhs, bpf, linuxppc-dev, kafai, Hari Bathini

With KUAP enabled, any kernel code which wants to access userspace
needs to be surrounded by disable-enable KUAP. But that is not
happening for BPF_PROBE_MEM load instruction. Though PPC32 does not
support read protection, considering the fact that PTR_TO_BTF_ID
(which uses BPF_PROBE_MEM mode) could either be a valid kernel pointer
or NULL but should never be a pointer to userspace address, execute
BPF_PROBE_MEM load only if addr is kernel address, otherwise set
dst_reg=0 and move on.

This will catch NULL, valid or invalid userspace pointers. Only bad
kernel pointer will be handled by BPF exception table.

[Alexei suggested for x86]
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---

Changes in v4:
* Adjusted the emit code to avoid using temporary reg.


 arch/powerpc/net/bpf_jit_comp32.c | 34 +++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 5dc45e393d1d..d3a52cd42f53 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -820,6 +820,40 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 		case BPF_LDX | BPF_PROBE_MEM | BPF_W:
 		case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */
 		case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
+			/*
+			 * As PTR_TO_BTF_ID that uses BPF_PROBE_MEM mode could either be a valid
+			 * kernel pointer or NULL but not a userspace address, execute BPF_PROBE_MEM
+			 * load only if addr is kernel address (see is_kernel_addr()), otherwise
+			 * set dst_reg=0 and move on.
+			 */
+			if (BPF_MODE(code) == BPF_PROBE_MEM) {
+				PPC_LI32(_R0, TASK_SIZE - off);
+				EMIT(PPC_RAW_CMPLW(src_reg, _R0));
+				PPC_BCC(COND_GT, (ctx->idx + 5) * 4);
+				EMIT(PPC_RAW_LI(dst_reg, 0));
+				/*
+				 * For BPF_DW case, "li reg_h,0" would be needed when
+				 * !fp->aux->verifier_zext. Emit NOP otherwise.
+				 *
+				 * Note that "li reg_h,0" is emitted for BPF_B/H/W case,
+				 * if necessary. So, jump there insted of emitting an
+				 * additional "li reg_h,0" instruction.
+				 */
+				if (size == BPF_DW && !fp->aux->verifier_zext)
+					EMIT(PPC_RAW_LI(dst_reg_h, 0));
+				else
+					EMIT(PPC_RAW_NOP());
+				/*
+				 * Need to jump two instructions instead of one for BPF_DW case
+				 * as there are two load instructions for dst_reg_h & dst_reg
+				 * respectively.
+				 */
+				if (size == BPF_DW)
+					PPC_JMP((ctx->idx + 3) * 4);
+				else
+					PPC_JMP((ctx->idx + 2) * 4);
+			}
+
 			switch (size) {
 			case BPF_B:
 				EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off));
-- 
2.31.1


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

* RE: [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler
  2021-10-12 12:30 ` Hari Bathini
@ 2021-10-14  8:15   ` David Laight
  -1 siblings, 0 replies; 27+ messages in thread
From: David Laight @ 2021-10-14  8:15 UTC (permalink / raw)
  To: 'Hari Bathini', naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev

From: Hari Bathini 
> Sent: 12 October 2021 13:31
> 
> Patch #1 & #2 are simple cleanup patches. Patch #3 refactors JIT
> compiler code with the aim to simplify adding BPF_PROBE_MEM support.
> Patch #4 introduces PPC_RAW_BRANCH() macro instead of open coding
> branch instruction. Patch #5 & #7 add BPF_PROBE_MEM support for PPC64
> & PPC32 JIT compilers respectively. Patch #6 & #8 handle bad userspace
> pointers for PPC64 & PPC32 cases respectively.

I thought that BPF was only allowed to do fairly restricted
memory accesses - so WTF does it need a BPF_PROBE_MEM instruction?

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


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

* RE: [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler
@ 2021-10-14  8:15   ` David Laight
  0 siblings, 0 replies; 27+ messages in thread
From: David Laight @ 2021-10-14  8:15 UTC (permalink / raw)
  To: 'Hari Bathini', naveen.n.rao, christophe.leroy, mpe, ast, daniel
  Cc: songliubraving, netdev, john.fastabend, andrii, kpsingh, paulus,
	yhs, bpf, linuxppc-dev, kafai

From: Hari Bathini 
> Sent: 12 October 2021 13:31
> 
> Patch #1 & #2 are simple cleanup patches. Patch #3 refactors JIT
> compiler code with the aim to simplify adding BPF_PROBE_MEM support.
> Patch #4 introduces PPC_RAW_BRANCH() macro instead of open coding
> branch instruction. Patch #5 & #7 add BPF_PROBE_MEM support for PPC64
> & PPC32 JIT compilers respectively. Patch #6 & #8 handle bad userspace
> pointers for PPC64 & PPC32 cases respectively.

I thought that BPF was only allowed to do fairly restricted
memory accesses - so WTF does it need a BPF_PROBE_MEM instruction?

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


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

* Re: [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler
  2021-10-14  8:15   ` David Laight
@ 2021-10-14  8:33     ` Christophe Leroy
  -1 siblings, 0 replies; 27+ messages in thread
From: Christophe Leroy @ 2021-10-14  8:33 UTC (permalink / raw)
  To: David Laight, 'Hari Bathini', naveen.n.rao, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev



Le 14/10/2021 à 10:15, David Laight a écrit :
> From: Hari Bathini
>> Sent: 12 October 2021 13:31
>>
>> Patch #1 & #2 are simple cleanup patches. Patch #3 refactors JIT
>> compiler code with the aim to simplify adding BPF_PROBE_MEM support.
>> Patch #4 introduces PPC_RAW_BRANCH() macro instead of open coding
>> branch instruction. Patch #5 & #7 add BPF_PROBE_MEM support for PPC64
>> & PPC32 JIT compilers respectively. Patch #6 & #8 handle bad userspace
>> pointers for PPC64 & PPC32 cases respectively.
> 
> I thought that BPF was only allowed to do fairly restricted
> memory accesses - so WTF does it need a BPF_PROBE_MEM instruction?
> 


Looks like it's been added by commit 2a02759ef5f8 ("bpf: Add support for 
BTF pointers to interpreter")

They say in the log:

     Pointer to BTF object is a pointer to kernel object or NULL.
     The memory access in the interpreter has to be done via 
probe_kernel_read
     to avoid page faults.

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

* Re: [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler
@ 2021-10-14  8:33     ` Christophe Leroy
  0 siblings, 0 replies; 27+ messages in thread
From: Christophe Leroy @ 2021-10-14  8:33 UTC (permalink / raw)
  To: David Laight, 'Hari Bathini', naveen.n.rao, mpe, ast, daniel
  Cc: songliubraving, netdev, john.fastabend, andrii, kpsingh, paulus,
	yhs, bpf, linuxppc-dev, kafai



Le 14/10/2021 à 10:15, David Laight a écrit :
> From: Hari Bathini
>> Sent: 12 October 2021 13:31
>>
>> Patch #1 & #2 are simple cleanup patches. Patch #3 refactors JIT
>> compiler code with the aim to simplify adding BPF_PROBE_MEM support.
>> Patch #4 introduces PPC_RAW_BRANCH() macro instead of open coding
>> branch instruction. Patch #5 & #7 add BPF_PROBE_MEM support for PPC64
>> & PPC32 JIT compilers respectively. Patch #6 & #8 handle bad userspace
>> pointers for PPC64 & PPC32 cases respectively.
> 
> I thought that BPF was only allowed to do fairly restricted
> memory accesses - so WTF does it need a BPF_PROBE_MEM instruction?
> 


Looks like it's been added by commit 2a02759ef5f8 ("bpf: Add support for 
BTF pointers to interpreter")

They say in the log:

     Pointer to BTF object is a pointer to kernel object or NULL.
     The memory access in the interpreter has to be done via 
probe_kernel_read
     to avoid page faults.

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

* RE: [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler
  2021-10-14  8:33     ` Christophe Leroy
@ 2021-10-14  9:52       ` David Laight
  -1 siblings, 0 replies; 27+ messages in thread
From: David Laight @ 2021-10-14  9:52 UTC (permalink / raw)
  To: 'Christophe Leroy', 'Hari Bathini',
	naveen.n.rao, mpe, ast, daniel
  Cc: paulus, andrii, kafai, songliubraving, yhs, john.fastabend,
	kpsingh, netdev, bpf, linuxppc-dev

From: Christophe Leroy
> Sent: 14 October 2021 09:34
> 
> Le 14/10/2021 à 10:15, David Laight a écrit :
> > From: Hari Bathini
> >> Sent: 12 October 2021 13:31
> >>
> >> Patch #1 & #2 are simple cleanup patches. Patch #3 refactors JIT
> >> compiler code with the aim to simplify adding BPF_PROBE_MEM support.
> >> Patch #4 introduces PPC_RAW_BRANCH() macro instead of open coding
> >> branch instruction. Patch #5 & #7 add BPF_PROBE_MEM support for PPC64
> >> & PPC32 JIT compilers respectively. Patch #6 & #8 handle bad userspace
> >> pointers for PPC64 & PPC32 cases respectively.
> >
> > I thought that BPF was only allowed to do fairly restricted
> > memory accesses - so WTF does it need a BPF_PROBE_MEM instruction?
> >
> 
> 
> Looks like it's been added by commit 2a02759ef5f8 ("bpf: Add support for
> BTF pointers to interpreter")
> 
> They say in the log:
> 
>      Pointer to BTF object is a pointer to kernel object or NULL.
>      The memory access in the interpreter has to be done via
>      probe_kernel_read to avoid page faults.

Hmmm....

Either the pointer should be valid (if not NULL) or they should
verify that it is the address of an interpreter.
If the value is being passed to/from userspace then they
are leaking kernel address - and that needs to be squashed.

They should be using an opaque identifier for the interpreter.

My gut feeling is that a lot of the changes to bpf over the last
few years means that it is no longer a verifiably safe simple
filter engine.
As such the you might as well load a normal kernel module.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

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

* RE: [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler
@ 2021-10-14  9:52       ` David Laight
  0 siblings, 0 replies; 27+ messages in thread
From: David Laight @ 2021-10-14  9:52 UTC (permalink / raw)
  To: 'Christophe Leroy', 'Hari Bathini',
	naveen.n.rao, mpe, ast, daniel
  Cc: songliubraving, netdev, john.fastabend, andrii, kpsingh, paulus,
	yhs, bpf, linuxppc-dev, kafai

From: Christophe Leroy
> Sent: 14 October 2021 09:34
> 
> Le 14/10/2021 à 10:15, David Laight a écrit :
> > From: Hari Bathini
> >> Sent: 12 October 2021 13:31
> >>
> >> Patch #1 & #2 are simple cleanup patches. Patch #3 refactors JIT
> >> compiler code with the aim to simplify adding BPF_PROBE_MEM support.
> >> Patch #4 introduces PPC_RAW_BRANCH() macro instead of open coding
> >> branch instruction. Patch #5 & #7 add BPF_PROBE_MEM support for PPC64
> >> & PPC32 JIT compilers respectively. Patch #6 & #8 handle bad userspace
> >> pointers for PPC64 & PPC32 cases respectively.
> >
> > I thought that BPF was only allowed to do fairly restricted
> > memory accesses - so WTF does it need a BPF_PROBE_MEM instruction?
> >
> 
> 
> Looks like it's been added by commit 2a02759ef5f8 ("bpf: Add support for
> BTF pointers to interpreter")
> 
> They say in the log:
> 
>      Pointer to BTF object is a pointer to kernel object or NULL.
>      The memory access in the interpreter has to be done via
>      probe_kernel_read to avoid page faults.

Hmmm....

Either the pointer should be valid (if not NULL) or they should
verify that it is the address of an interpreter.
If the value is being passed to/from userspace then they
are leaking kernel address - and that needs to be squashed.

They should be using an opaque identifier for the interpreter.

My gut feeling is that a lot of the changes to bpf over the last
few years means that it is no longer a verifiably safe simple
filter engine.
As such the you might as well load a normal kernel module.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

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

* Re: [RESEND PATCH v4 6/8] bpf ppc64: Access only if addr is kernel address
  2021-10-12 12:30   ` Hari Bathini
  (?)
@ 2021-11-08 13:04   ` kernel test robot
  -1 siblings, 0 replies; 27+ messages in thread
From: kernel test robot @ 2021-11-08 13:04 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 23158 bytes --]

Hi Hari,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on v5.15-rc5]
[also build test WARNING on next-20211108]
[cannot apply to powerpc/next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Hari-Bathini/bpf-powerpc-Add-BPF_PROBE_MEM-support-in-powerpc-JIT-compiler/20211012-205813
base:   DEBUG invalid remote for branch v5.15-rc5 64570fbc14f8d7cb3fe3995f20e26bc25ce4b2cc
config: powerpc64-randconfig-s031-20211016 (attached as .config)
compiler: powerpc64-linux-gcc (GCC) 11.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-dirty
        # https://github.com/0day-ci/linux/commit/be6c692c4b1d002a5511309c5cfd2b555dec4af8
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Hari-Bathini/bpf-powerpc-Add-BPF_PROBE_MEM-support-in-powerpc-JIT-compiler/20211012-205813
        git checkout be6c692c4b1d002a5511309c5cfd2b555dec4af8
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=powerpc SHELL=/bin/bash arch/powerpc/mm/nohash/ arch/powerpc/net/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
>> arch/powerpc/net/bpf_jit_comp64.c:801:41: sparse: sparse: cast truncates bits from constant value (8000000000000000 becomes 0)
>> arch/powerpc/net/bpf_jit_comp64.c:801:41: sparse: sparse: cast truncates bits from constant value (8000000000000000 becomes 0)
>> arch/powerpc/net/bpf_jit_comp64.c:803:41: sparse: sparse: cast truncates bits from constant value (c000000000000000 becomes 0)
>> arch/powerpc/net/bpf_jit_comp64.c:803:41: sparse: sparse: cast truncates bits from constant value (c000000000000000 becomes 0)

vim +801 arch/powerpc/net/bpf_jit_comp64.c

   297	
   298	/* Assemble the body code between the prologue & epilogue */
   299	int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
   300			       u32 *addrs, int pass)
   301	{
   302		enum stf_barrier_type stf_barrier = stf_barrier_type_get();
   303		const struct bpf_insn *insn = fp->insnsi;
   304		int flen = fp->len;
   305		int i, ret;
   306	
   307		/* Start of epilogue code - will only be valid 2nd pass onwards */
   308		u32 exit_addr = addrs[flen];
   309	
   310		for (i = 0; i < flen; i++) {
   311			u32 code = insn[i].code;
   312			u32 dst_reg = b2p[insn[i].dst_reg];
   313			u32 src_reg = b2p[insn[i].src_reg];
   314			u32 size = BPF_SIZE(code);
   315			s16 off = insn[i].off;
   316			s32 imm = insn[i].imm;
   317			bool func_addr_fixed;
   318			u64 func_addr;
   319			u64 imm64;
   320			u32 true_cond;
   321			u32 tmp_idx;
   322	
   323			/*
   324			 * addrs[] maps a BPF bytecode address into a real offset from
   325			 * the start of the body code.
   326			 */
   327			addrs[i] = ctx->idx * 4;
   328	
   329			/*
   330			 * As an optimization, we note down which non-volatile registers
   331			 * are used so that we can only save/restore those in our
   332			 * prologue and epilogue. We do this here regardless of whether
   333			 * the actual BPF instruction uses src/dst registers or not
   334			 * (for instance, BPF_CALL does not use them). The expectation
   335			 * is that those instructions will have src_reg/dst_reg set to
   336			 * 0. Even otherwise, we just lose some prologue/epilogue
   337			 * optimization but everything else should work without
   338			 * any issues.
   339			 */
   340			if (dst_reg >= BPF_PPC_NVR_MIN && dst_reg < 32)
   341				bpf_set_seen_register(ctx, dst_reg);
   342			if (src_reg >= BPF_PPC_NVR_MIN && src_reg < 32)
   343				bpf_set_seen_register(ctx, src_reg);
   344	
   345			switch (code) {
   346			/*
   347			 * Arithmetic operations: ADD/SUB/MUL/DIV/MOD/NEG
   348			 */
   349			case BPF_ALU | BPF_ADD | BPF_X: /* (u32) dst += (u32) src */
   350			case BPF_ALU64 | BPF_ADD | BPF_X: /* dst += src */
   351				EMIT(PPC_RAW_ADD(dst_reg, dst_reg, src_reg));
   352				goto bpf_alu32_trunc;
   353			case BPF_ALU | BPF_SUB | BPF_X: /* (u32) dst -= (u32) src */
   354			case BPF_ALU64 | BPF_SUB | BPF_X: /* dst -= src */
   355				EMIT(PPC_RAW_SUB(dst_reg, dst_reg, src_reg));
   356				goto bpf_alu32_trunc;
   357			case BPF_ALU | BPF_ADD | BPF_K: /* (u32) dst += (u32) imm */
   358			case BPF_ALU64 | BPF_ADD | BPF_K: /* dst += imm */
   359				if (!imm) {
   360					goto bpf_alu32_trunc;
   361				} else if (imm >= -32768 && imm < 32768) {
   362					EMIT(PPC_RAW_ADDI(dst_reg, dst_reg, IMM_L(imm)));
   363				} else {
   364					PPC_LI32(b2p[TMP_REG_1], imm);
   365					EMIT(PPC_RAW_ADD(dst_reg, dst_reg, b2p[TMP_REG_1]));
   366				}
   367				goto bpf_alu32_trunc;
   368			case BPF_ALU | BPF_SUB | BPF_K: /* (u32) dst -= (u32) imm */
   369			case BPF_ALU64 | BPF_SUB | BPF_K: /* dst -= imm */
   370				if (!imm) {
   371					goto bpf_alu32_trunc;
   372				} else if (imm > -32768 && imm <= 32768) {
   373					EMIT(PPC_RAW_ADDI(dst_reg, dst_reg, IMM_L(-imm)));
   374				} else {
   375					PPC_LI32(b2p[TMP_REG_1], imm);
   376					EMIT(PPC_RAW_SUB(dst_reg, dst_reg, b2p[TMP_REG_1]));
   377				}
   378				goto bpf_alu32_trunc;
   379			case BPF_ALU | BPF_MUL | BPF_X: /* (u32) dst *= (u32) src */
   380			case BPF_ALU64 | BPF_MUL | BPF_X: /* dst *= src */
   381				if (BPF_CLASS(code) == BPF_ALU)
   382					EMIT(PPC_RAW_MULW(dst_reg, dst_reg, src_reg));
   383				else
   384					EMIT(PPC_RAW_MULD(dst_reg, dst_reg, src_reg));
   385				goto bpf_alu32_trunc;
   386			case BPF_ALU | BPF_MUL | BPF_K: /* (u32) dst *= (u32) imm */
   387			case BPF_ALU64 | BPF_MUL | BPF_K: /* dst *= imm */
   388				if (imm >= -32768 && imm < 32768)
   389					EMIT(PPC_RAW_MULI(dst_reg, dst_reg, IMM_L(imm)));
   390				else {
   391					PPC_LI32(b2p[TMP_REG_1], imm);
   392					if (BPF_CLASS(code) == BPF_ALU)
   393						EMIT(PPC_RAW_MULW(dst_reg, dst_reg,
   394								b2p[TMP_REG_1]));
   395					else
   396						EMIT(PPC_RAW_MULD(dst_reg, dst_reg,
   397								b2p[TMP_REG_1]));
   398				}
   399				goto bpf_alu32_trunc;
   400			case BPF_ALU | BPF_DIV | BPF_X: /* (u32) dst /= (u32) src */
   401			case BPF_ALU | BPF_MOD | BPF_X: /* (u32) dst %= (u32) src */
   402				if (BPF_OP(code) == BPF_MOD) {
   403					EMIT(PPC_RAW_DIVWU(b2p[TMP_REG_1], dst_reg, src_reg));
   404					EMIT(PPC_RAW_MULW(b2p[TMP_REG_1], src_reg,
   405							b2p[TMP_REG_1]));
   406					EMIT(PPC_RAW_SUB(dst_reg, dst_reg, b2p[TMP_REG_1]));
   407				} else
   408					EMIT(PPC_RAW_DIVWU(dst_reg, dst_reg, src_reg));
   409				goto bpf_alu32_trunc;
   410			case BPF_ALU64 | BPF_DIV | BPF_X: /* dst /= src */
   411			case BPF_ALU64 | BPF_MOD | BPF_X: /* dst %= src */
   412				if (BPF_OP(code) == BPF_MOD) {
   413					EMIT(PPC_RAW_DIVDU(b2p[TMP_REG_1], dst_reg, src_reg));
   414					EMIT(PPC_RAW_MULD(b2p[TMP_REG_1], src_reg,
   415							b2p[TMP_REG_1]));
   416					EMIT(PPC_RAW_SUB(dst_reg, dst_reg, b2p[TMP_REG_1]));
   417				} else
   418					EMIT(PPC_RAW_DIVDU(dst_reg, dst_reg, src_reg));
   419				break;
   420			case BPF_ALU | BPF_MOD | BPF_K: /* (u32) dst %= (u32) imm */
   421			case BPF_ALU | BPF_DIV | BPF_K: /* (u32) dst /= (u32) imm */
   422			case BPF_ALU64 | BPF_MOD | BPF_K: /* dst %= imm */
   423			case BPF_ALU64 | BPF_DIV | BPF_K: /* dst /= imm */
   424				if (imm == 0)
   425					return -EINVAL;
   426				if (imm == 1) {
   427					if (BPF_OP(code) == BPF_DIV) {
   428						goto bpf_alu32_trunc;
   429					} else {
   430						EMIT(PPC_RAW_LI(dst_reg, 0));
   431						break;
   432					}
   433				}
   434	
   435				PPC_LI32(b2p[TMP_REG_1], imm);
   436				switch (BPF_CLASS(code)) {
   437				case BPF_ALU:
   438					if (BPF_OP(code) == BPF_MOD) {
   439						EMIT(PPC_RAW_DIVWU(b2p[TMP_REG_2],
   440								dst_reg,
   441								b2p[TMP_REG_1]));
   442						EMIT(PPC_RAW_MULW(b2p[TMP_REG_1],
   443								b2p[TMP_REG_1],
   444								b2p[TMP_REG_2]));
   445						EMIT(PPC_RAW_SUB(dst_reg, dst_reg,
   446								b2p[TMP_REG_1]));
   447					} else
   448						EMIT(PPC_RAW_DIVWU(dst_reg, dst_reg,
   449								b2p[TMP_REG_1]));
   450					break;
   451				case BPF_ALU64:
   452					if (BPF_OP(code) == BPF_MOD) {
   453						EMIT(PPC_RAW_DIVDU(b2p[TMP_REG_2],
   454								dst_reg,
   455								b2p[TMP_REG_1]));
   456						EMIT(PPC_RAW_MULD(b2p[TMP_REG_1],
   457								b2p[TMP_REG_1],
   458								b2p[TMP_REG_2]));
   459						EMIT(PPC_RAW_SUB(dst_reg, dst_reg,
   460								b2p[TMP_REG_1]));
   461					} else
   462						EMIT(PPC_RAW_DIVDU(dst_reg, dst_reg,
   463								b2p[TMP_REG_1]));
   464					break;
   465				}
   466				goto bpf_alu32_trunc;
   467			case BPF_ALU | BPF_NEG: /* (u32) dst = -dst */
   468			case BPF_ALU64 | BPF_NEG: /* dst = -dst */
   469				EMIT(PPC_RAW_NEG(dst_reg, dst_reg));
   470				goto bpf_alu32_trunc;
   471	
   472			/*
   473			 * Logical operations: AND/OR/XOR/[A]LSH/[A]RSH
   474			 */
   475			case BPF_ALU | BPF_AND | BPF_X: /* (u32) dst = dst & src */
   476			case BPF_ALU64 | BPF_AND | BPF_X: /* dst = dst & src */
   477				EMIT(PPC_RAW_AND(dst_reg, dst_reg, src_reg));
   478				goto bpf_alu32_trunc;
   479			case BPF_ALU | BPF_AND | BPF_K: /* (u32) dst = dst & imm */
   480			case BPF_ALU64 | BPF_AND | BPF_K: /* dst = dst & imm */
   481				if (!IMM_H(imm))
   482					EMIT(PPC_RAW_ANDI(dst_reg, dst_reg, IMM_L(imm)));
   483				else {
   484					/* Sign-extended */
   485					PPC_LI32(b2p[TMP_REG_1], imm);
   486					EMIT(PPC_RAW_AND(dst_reg, dst_reg, b2p[TMP_REG_1]));
   487				}
   488				goto bpf_alu32_trunc;
   489			case BPF_ALU | BPF_OR | BPF_X: /* dst = (u32) dst | (u32) src */
   490			case BPF_ALU64 | BPF_OR | BPF_X: /* dst = dst | src */
   491				EMIT(PPC_RAW_OR(dst_reg, dst_reg, src_reg));
   492				goto bpf_alu32_trunc;
   493			case BPF_ALU | BPF_OR | BPF_K:/* dst = (u32) dst | (u32) imm */
   494			case BPF_ALU64 | BPF_OR | BPF_K:/* dst = dst | imm */
   495				if (imm < 0 && BPF_CLASS(code) == BPF_ALU64) {
   496					/* Sign-extended */
   497					PPC_LI32(b2p[TMP_REG_1], imm);
   498					EMIT(PPC_RAW_OR(dst_reg, dst_reg, b2p[TMP_REG_1]));
   499				} else {
   500					if (IMM_L(imm))
   501						EMIT(PPC_RAW_ORI(dst_reg, dst_reg, IMM_L(imm)));
   502					if (IMM_H(imm))
   503						EMIT(PPC_RAW_ORIS(dst_reg, dst_reg, IMM_H(imm)));
   504				}
   505				goto bpf_alu32_trunc;
   506			case BPF_ALU | BPF_XOR | BPF_X: /* (u32) dst ^= src */
   507			case BPF_ALU64 | BPF_XOR | BPF_X: /* dst ^= src */
   508				EMIT(PPC_RAW_XOR(dst_reg, dst_reg, src_reg));
   509				goto bpf_alu32_trunc;
   510			case BPF_ALU | BPF_XOR | BPF_K: /* (u32) dst ^= (u32) imm */
   511			case BPF_ALU64 | BPF_XOR | BPF_K: /* dst ^= imm */
   512				if (imm < 0 && BPF_CLASS(code) == BPF_ALU64) {
   513					/* Sign-extended */
   514					PPC_LI32(b2p[TMP_REG_1], imm);
   515					EMIT(PPC_RAW_XOR(dst_reg, dst_reg, b2p[TMP_REG_1]));
   516				} else {
   517					if (IMM_L(imm))
   518						EMIT(PPC_RAW_XORI(dst_reg, dst_reg, IMM_L(imm)));
   519					if (IMM_H(imm))
   520						EMIT(PPC_RAW_XORIS(dst_reg, dst_reg, IMM_H(imm)));
   521				}
   522				goto bpf_alu32_trunc;
   523			case BPF_ALU | BPF_LSH | BPF_X: /* (u32) dst <<= (u32) src */
   524				/* slw clears top 32 bits */
   525				EMIT(PPC_RAW_SLW(dst_reg, dst_reg, src_reg));
   526				/* skip zero extension move, but set address map. */
   527				if (insn_is_zext(&insn[i + 1]))
   528					addrs[++i] = ctx->idx * 4;
   529				break;
   530			case BPF_ALU64 | BPF_LSH | BPF_X: /* dst <<= src; */
   531				EMIT(PPC_RAW_SLD(dst_reg, dst_reg, src_reg));
   532				break;
   533			case BPF_ALU | BPF_LSH | BPF_K: /* (u32) dst <<== (u32) imm */
   534				/* with imm 0, we still need to clear top 32 bits */
   535				EMIT(PPC_RAW_SLWI(dst_reg, dst_reg, imm));
   536				if (insn_is_zext(&insn[i + 1]))
   537					addrs[++i] = ctx->idx * 4;
   538				break;
   539			case BPF_ALU64 | BPF_LSH | BPF_K: /* dst <<== imm */
   540				if (imm != 0)
   541					EMIT(PPC_RAW_SLDI(dst_reg, dst_reg, imm));
   542				break;
   543			case BPF_ALU | BPF_RSH | BPF_X: /* (u32) dst >>= (u32) src */
   544				EMIT(PPC_RAW_SRW(dst_reg, dst_reg, src_reg));
   545				if (insn_is_zext(&insn[i + 1]))
   546					addrs[++i] = ctx->idx * 4;
   547				break;
   548			case BPF_ALU64 | BPF_RSH | BPF_X: /* dst >>= src */
   549				EMIT(PPC_RAW_SRD(dst_reg, dst_reg, src_reg));
   550				break;
   551			case BPF_ALU | BPF_RSH | BPF_K: /* (u32) dst >>= (u32) imm */
   552				EMIT(PPC_RAW_SRWI(dst_reg, dst_reg, imm));
   553				if (insn_is_zext(&insn[i + 1]))
   554					addrs[++i] = ctx->idx * 4;
   555				break;
   556			case BPF_ALU64 | BPF_RSH | BPF_K: /* dst >>= imm */
   557				if (imm != 0)
   558					EMIT(PPC_RAW_SRDI(dst_reg, dst_reg, imm));
   559				break;
   560			case BPF_ALU | BPF_ARSH | BPF_X: /* (s32) dst >>= src */
   561				EMIT(PPC_RAW_SRAW(dst_reg, dst_reg, src_reg));
   562				goto bpf_alu32_trunc;
   563			case BPF_ALU64 | BPF_ARSH | BPF_X: /* (s64) dst >>= src */
   564				EMIT(PPC_RAW_SRAD(dst_reg, dst_reg, src_reg));
   565				break;
   566			case BPF_ALU | BPF_ARSH | BPF_K: /* (s32) dst >>= imm */
   567				EMIT(PPC_RAW_SRAWI(dst_reg, dst_reg, imm));
   568				goto bpf_alu32_trunc;
   569			case BPF_ALU64 | BPF_ARSH | BPF_K: /* (s64) dst >>= imm */
   570				if (imm != 0)
   571					EMIT(PPC_RAW_SRADI(dst_reg, dst_reg, imm));
   572				break;
   573	
   574			/*
   575			 * MOV
   576			 */
   577			case BPF_ALU | BPF_MOV | BPF_X: /* (u32) dst = src */
   578			case BPF_ALU64 | BPF_MOV | BPF_X: /* dst = src */
   579				if (imm == 1) {
   580					/* special mov32 for zext */
   581					EMIT(PPC_RAW_RLWINM(dst_reg, dst_reg, 0, 0, 31));
   582					break;
   583				}
   584				EMIT(PPC_RAW_MR(dst_reg, src_reg));
   585				goto bpf_alu32_trunc;
   586			case BPF_ALU | BPF_MOV | BPF_K: /* (u32) dst = imm */
   587			case BPF_ALU64 | BPF_MOV | BPF_K: /* dst = (s64) imm */
   588				PPC_LI32(dst_reg, imm);
   589				if (imm < 0)
   590					goto bpf_alu32_trunc;
   591				else if (insn_is_zext(&insn[i + 1]))
   592					addrs[++i] = ctx->idx * 4;
   593				break;
   594	
   595	bpf_alu32_trunc:
   596			/* Truncate to 32-bits */
   597			if (BPF_CLASS(code) == BPF_ALU && !fp->aux->verifier_zext)
   598				EMIT(PPC_RAW_RLWINM(dst_reg, dst_reg, 0, 0, 31));
   599			break;
   600	
   601			/*
   602			 * BPF_FROM_BE/LE
   603			 */
   604			case BPF_ALU | BPF_END | BPF_FROM_LE:
   605			case BPF_ALU | BPF_END | BPF_FROM_BE:
   606	#ifdef __BIG_ENDIAN__
   607				if (BPF_SRC(code) == BPF_FROM_BE)
   608					goto emit_clear;
   609	#else /* !__BIG_ENDIAN__ */
   610				if (BPF_SRC(code) == BPF_FROM_LE)
   611					goto emit_clear;
   612	#endif
   613				switch (imm) {
   614				case 16:
   615					/* Rotate 8 bits left & mask with 0x0000ff00 */
   616					EMIT(PPC_RAW_RLWINM(b2p[TMP_REG_1], dst_reg, 8, 16, 23));
   617					/* Rotate 8 bits right & insert LSB to reg */
   618					EMIT(PPC_RAW_RLWIMI(b2p[TMP_REG_1], dst_reg, 24, 24, 31));
   619					/* Move result back to dst_reg */
   620					EMIT(PPC_RAW_MR(dst_reg, b2p[TMP_REG_1]));
   621					break;
   622				case 32:
   623					/*
   624					 * Rotate word left by 8 bits:
   625					 * 2 bytes are already in their final position
   626					 * -- byte 2 and 4 (of bytes 1, 2, 3 and 4)
   627					 */
   628					EMIT(PPC_RAW_RLWINM(b2p[TMP_REG_1], dst_reg, 8, 0, 31));
   629					/* Rotate 24 bits and insert byte 1 */
   630					EMIT(PPC_RAW_RLWIMI(b2p[TMP_REG_1], dst_reg, 24, 0, 7));
   631					/* Rotate 24 bits and insert byte 3 */
   632					EMIT(PPC_RAW_RLWIMI(b2p[TMP_REG_1], dst_reg, 24, 16, 23));
   633					EMIT(PPC_RAW_MR(dst_reg, b2p[TMP_REG_1]));
   634					break;
   635				case 64:
   636					/*
   637					 * Way easier and faster(?) to store the value
   638					 * into stack and then use ldbrx
   639					 *
   640					 * ctx->seen will be reliable in pass2, but
   641					 * the instructions generated will remain the
   642					 * same across all passes
   643					 */
   644					PPC_BPF_STL(dst_reg, 1, bpf_jit_stack_local(ctx));
   645					EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], 1, bpf_jit_stack_local(ctx)));
   646					EMIT(PPC_RAW_LDBRX(dst_reg, 0, b2p[TMP_REG_1]));
   647					break;
   648				}
   649				break;
   650	
   651	emit_clear:
   652				switch (imm) {
   653				case 16:
   654					/* zero-extend 16 bits into 64 bits */
   655					EMIT(PPC_RAW_RLDICL(dst_reg, dst_reg, 0, 48));
   656					if (insn_is_zext(&insn[i + 1]))
   657						addrs[++i] = ctx->idx * 4;
   658					break;
   659				case 32:
   660					if (!fp->aux->verifier_zext)
   661						/* zero-extend 32 bits into 64 bits */
   662						EMIT(PPC_RAW_RLDICL(dst_reg, dst_reg, 0, 32));
   663					break;
   664				case 64:
   665					/* nop */
   666					break;
   667				}
   668				break;
   669	
   670			/*
   671			 * BPF_ST NOSPEC (speculation barrier)
   672			 */
   673			case BPF_ST | BPF_NOSPEC:
   674				if (!security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) ||
   675						!security_ftr_enabled(SEC_FTR_STF_BARRIER))
   676					break;
   677	
   678				switch (stf_barrier) {
   679				case STF_BARRIER_EIEIO:
   680					EMIT(PPC_RAW_EIEIO() | 0x02000000);
   681					break;
   682				case STF_BARRIER_SYNC_ORI:
   683					EMIT(PPC_RAW_SYNC());
   684					EMIT(PPC_RAW_LD(b2p[TMP_REG_1], _R13, 0));
   685					EMIT(PPC_RAW_ORI(_R31, _R31, 0));
   686					break;
   687				case STF_BARRIER_FALLBACK:
   688					EMIT(PPC_RAW_MFLR(b2p[TMP_REG_1]));
   689					PPC_LI64(12, dereference_kernel_function_descriptor(bpf_stf_barrier));
   690					EMIT(PPC_RAW_MTCTR(12));
   691					EMIT(PPC_RAW_BCTRL());
   692					EMIT(PPC_RAW_MTLR(b2p[TMP_REG_1]));
   693					break;
   694				case STF_BARRIER_NONE:
   695					break;
   696				}
   697				break;
   698	
   699			/*
   700			 * BPF_ST(X)
   701			 */
   702			case BPF_STX | BPF_MEM | BPF_B: /* *(u8 *)(dst + off) = src */
   703			case BPF_ST | BPF_MEM | BPF_B: /* *(u8 *)(dst + off) = imm */
   704				if (BPF_CLASS(code) == BPF_ST) {
   705					EMIT(PPC_RAW_LI(b2p[TMP_REG_1], imm));
   706					src_reg = b2p[TMP_REG_1];
   707				}
   708				EMIT(PPC_RAW_STB(src_reg, dst_reg, off));
   709				break;
   710			case BPF_STX | BPF_MEM | BPF_H: /* (u16 *)(dst + off) = src */
   711			case BPF_ST | BPF_MEM | BPF_H: /* (u16 *)(dst + off) = imm */
   712				if (BPF_CLASS(code) == BPF_ST) {
   713					EMIT(PPC_RAW_LI(b2p[TMP_REG_1], imm));
   714					src_reg = b2p[TMP_REG_1];
   715				}
   716				EMIT(PPC_RAW_STH(src_reg, dst_reg, off));
   717				break;
   718			case BPF_STX | BPF_MEM | BPF_W: /* *(u32 *)(dst + off) = src */
   719			case BPF_ST | BPF_MEM | BPF_W: /* *(u32 *)(dst + off) = imm */
   720				if (BPF_CLASS(code) == BPF_ST) {
   721					PPC_LI32(b2p[TMP_REG_1], imm);
   722					src_reg = b2p[TMP_REG_1];
   723				}
   724				EMIT(PPC_RAW_STW(src_reg, dst_reg, off));
   725				break;
   726			case BPF_STX | BPF_MEM | BPF_DW: /* (u64 *)(dst + off) = src */
   727			case BPF_ST | BPF_MEM | BPF_DW: /* *(u64 *)(dst + off) = imm */
   728				if (BPF_CLASS(code) == BPF_ST) {
   729					PPC_LI32(b2p[TMP_REG_1], imm);
   730					src_reg = b2p[TMP_REG_1];
   731				}
   732				PPC_BPF_STL(src_reg, dst_reg, off);
   733				break;
   734	
   735			/*
   736			 * BPF_STX ATOMIC (atomic ops)
   737			 */
   738			case BPF_STX | BPF_ATOMIC | BPF_W:
   739				if (imm != BPF_ADD) {
   740					pr_err_ratelimited(
   741						"eBPF filter atomic op code %02x (@%d) unsupported\n",
   742						code, i);
   743					return -ENOTSUPP;
   744				}
   745	
   746				/* *(u32 *)(dst + off) += src */
   747	
   748				/* Get EA into TMP_REG_1 */
   749				EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], dst_reg, off));
   750				tmp_idx = ctx->idx * 4;
   751				/* load value from memory into TMP_REG_2 */
   752				EMIT(PPC_RAW_LWARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0));
   753				/* add value from src_reg into this */
   754				EMIT(PPC_RAW_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg));
   755				/* store result back */
   756				EMIT(PPC_RAW_STWCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]));
   757				/* we're done if this succeeded */
   758				PPC_BCC_SHORT(COND_NE, tmp_idx);
   759				break;
   760			case BPF_STX | BPF_ATOMIC | BPF_DW:
   761				if (imm != BPF_ADD) {
   762					pr_err_ratelimited(
   763						"eBPF filter atomic op code %02x (@%d) unsupported\n",
   764						code, i);
   765					return -ENOTSUPP;
   766				}
   767				/* *(u64 *)(dst + off) += src */
   768	
   769				EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], dst_reg, off));
   770				tmp_idx = ctx->idx * 4;
   771				EMIT(PPC_RAW_LDARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0));
   772				EMIT(PPC_RAW_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg));
   773				EMIT(PPC_RAW_STDCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]));
   774				PPC_BCC_SHORT(COND_NE, tmp_idx);
   775				break;
   776	
   777			/*
   778			 * BPF_LDX
   779			 */
   780			/* dst = *(u8 *)(ul) (src + off) */
   781			case BPF_LDX | BPF_MEM | BPF_B:
   782			case BPF_LDX | BPF_PROBE_MEM | BPF_B:
   783			/* dst = *(u16 *)(ul) (src + off) */
   784			case BPF_LDX | BPF_MEM | BPF_H:
   785			case BPF_LDX | BPF_PROBE_MEM | BPF_H:
   786			/* dst = *(u32 *)(ul) (src + off) */
   787			case BPF_LDX | BPF_MEM | BPF_W:
   788			case BPF_LDX | BPF_PROBE_MEM | BPF_W:
   789			/* dst = *(u64 *)(ul) (src + off) */
   790			case BPF_LDX | BPF_MEM | BPF_DW:
   791			case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
   792				/*
   793				 * As PTR_TO_BTF_ID that uses BPF_PROBE_MEM mode could either be a valid
   794				 * kernel pointer or NULL but not a userspace address, execute BPF_PROBE_MEM
   795				 * load only if addr is kernel address (see is_kernel_addr()), otherwise
   796				 * set dst_reg=0 and move on.
   797				 */
   798				if (BPF_MODE(code) == BPF_PROBE_MEM) {
   799					EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], src_reg, off));
   800					if (IS_ENABLED(CONFIG_PPC_BOOK3E_64))
 > 801						PPC_LI64(b2p[TMP_REG_2], 0x8000000000000000ul);
   802					else /* BOOK3S_64 */
 > 803						PPC_LI64(b2p[TMP_REG_2], PAGE_OFFSET);

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 37979 bytes --]

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

* Re: [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler
  2021-10-12 12:30 ` Hari Bathini
@ 2021-11-25  9:36   ` Michael Ellerman
  -1 siblings, 0 replies; 27+ messages in thread
From: Michael Ellerman @ 2021-11-25  9:36 UTC (permalink / raw)
  To: ast, daniel, naveen.n.rao, mpe, christophe.leroy, Hari Bathini
  Cc: songliubraving, netdev, john.fastabend, andrii, kpsingh, paulus,
	yhs, bpf, linuxppc-dev, kafai

On Tue, 12 Oct 2021 18:00:48 +0530, Hari Bathini wrote:
> Patch #1 & #2 are simple cleanup patches. Patch #3 refactors JIT
> compiler code with the aim to simplify adding BPF_PROBE_MEM support.
> Patch #4 introduces PPC_RAW_BRANCH() macro instead of open coding
> branch instruction. Patch #5 & #7 add BPF_PROBE_MEM support for PPC64
> & PPC32 JIT compilers respectively. Patch #6 & #8 handle bad userspace
> pointers for PPC64 & PPC32 cases respectively.
> 
> [...]

Applied to powerpc/next.

[1/8] bpf powerpc: Remove unused SEEN_STACK
      https://git.kernel.org/powerpc/c/c9ce7c36e4870bd307101ba7a00a39d9aad270f3
[2/8] bpf powerpc: Remove extra_pass from bpf_jit_build_body()
      https://git.kernel.org/powerpc/c/04c04205bc35d0ecdc57146995ca9eb957d4f379
[3/8] bpf powerpc: refactor JIT compiler code
      https://git.kernel.org/powerpc/c/efa95f031bf38c85cf865413335a3dc044e3194e
[4/8] powerpc/ppc-opcode: introduce PPC_RAW_BRANCH() macro
      https://git.kernel.org/powerpc/c/f15a71b3880bf07b40810644e5ac6f177c2a7c8f
[5/8] bpf ppc64: Add BPF_PROBE_MEM support for JIT
      https://git.kernel.org/powerpc/c/983bdc0245a29cdefcd30d9d484d3edbc4b6d787
[6/8] bpf ppc64: Access only if addr is kernel address
      https://git.kernel.org/powerpc/c/9c70c7147ffec31de67d33243570a533b29f9759
[7/8] bpf ppc32: Add BPF_PROBE_MEM support for JIT
      https://git.kernel.org/powerpc/c/23b51916ee129833453d8a3d6bde0ff392f82fce
[8/8] bpf ppc32: Access only if addr is kernel address
      https://git.kernel.org/powerpc/c/e919c0b2323bedec00e1ecc6280498ff81f59b15

cheers

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

* Re: [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler
@ 2021-11-25  9:36   ` Michael Ellerman
  0 siblings, 0 replies; 27+ messages in thread
From: Michael Ellerman @ 2021-11-25  9:36 UTC (permalink / raw)
  To: ast, daniel, naveen.n.rao, mpe, christophe.leroy, Hari Bathini
  Cc: songliubraving, yhs, andrii, john.fastabend, bpf, paulus,
	kpsingh, kafai, netdev, linuxppc-dev

On Tue, 12 Oct 2021 18:00:48 +0530, Hari Bathini wrote:
> Patch #1 & #2 are simple cleanup patches. Patch #3 refactors JIT
> compiler code with the aim to simplify adding BPF_PROBE_MEM support.
> Patch #4 introduces PPC_RAW_BRANCH() macro instead of open coding
> branch instruction. Patch #5 & #7 add BPF_PROBE_MEM support for PPC64
> & PPC32 JIT compilers respectively. Patch #6 & #8 handle bad userspace
> pointers for PPC64 & PPC32 cases respectively.
> 
> [...]

Applied to powerpc/next.

[1/8] bpf powerpc: Remove unused SEEN_STACK
      https://git.kernel.org/powerpc/c/c9ce7c36e4870bd307101ba7a00a39d9aad270f3
[2/8] bpf powerpc: Remove extra_pass from bpf_jit_build_body()
      https://git.kernel.org/powerpc/c/04c04205bc35d0ecdc57146995ca9eb957d4f379
[3/8] bpf powerpc: refactor JIT compiler code
      https://git.kernel.org/powerpc/c/efa95f031bf38c85cf865413335a3dc044e3194e
[4/8] powerpc/ppc-opcode: introduce PPC_RAW_BRANCH() macro
      https://git.kernel.org/powerpc/c/f15a71b3880bf07b40810644e5ac6f177c2a7c8f
[5/8] bpf ppc64: Add BPF_PROBE_MEM support for JIT
      https://git.kernel.org/powerpc/c/983bdc0245a29cdefcd30d9d484d3edbc4b6d787
[6/8] bpf ppc64: Access only if addr is kernel address
      https://git.kernel.org/powerpc/c/9c70c7147ffec31de67d33243570a533b29f9759
[7/8] bpf ppc32: Add BPF_PROBE_MEM support for JIT
      https://git.kernel.org/powerpc/c/23b51916ee129833453d8a3d6bde0ff392f82fce
[8/8] bpf ppc32: Access only if addr is kernel address
      https://git.kernel.org/powerpc/c/e919c0b2323bedec00e1ecc6280498ff81f59b15

cheers

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

end of thread, other threads:[~2021-11-25  9:49 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-12 12:30 [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler Hari Bathini
2021-10-12 12:30 ` Hari Bathini
2021-10-12 12:30 ` [RESEND PATCH v4 1/8] bpf powerpc: Remove unused SEEN_STACK Hari Bathini
2021-10-12 12:30   ` Hari Bathini
2021-10-12 12:30 ` [RESEND PATCH v4 2/8] bpf powerpc: Remove extra_pass from bpf_jit_build_body() Hari Bathini
2021-10-12 12:30   ` Hari Bathini
2021-10-12 12:30 ` [RESEND PATCH v4 3/8] bpf powerpc: refactor JIT compiler code Hari Bathini
2021-10-12 12:30   ` Hari Bathini
2021-10-12 12:30 ` [RESEND PATCH v4 4/8] powerpc/ppc-opcode: introduce PPC_RAW_BRANCH() macro Hari Bathini
2021-10-12 12:30   ` Hari Bathini
2021-10-12 12:30 ` [RESEND PATCH v4 5/8] bpf ppc64: Add BPF_PROBE_MEM support for JIT Hari Bathini
2021-10-12 12:30   ` Hari Bathini
2021-10-12 12:30 ` [RESEND PATCH v4 6/8] bpf ppc64: Access only if addr is kernel address Hari Bathini
2021-10-12 12:30   ` Hari Bathini
2021-11-08 13:04   ` kernel test robot
2021-10-12 12:30 ` [RESEND PATCH v4 7/8] bpf ppc32: Add BPF_PROBE_MEM support for JIT Hari Bathini
2021-10-12 12:30   ` Hari Bathini
2021-10-12 12:30 ` [RESEND PATCH v4 8/8] bpf ppc32: Access only if addr is kernel address Hari Bathini
2021-10-12 12:30   ` Hari Bathini
2021-10-14  8:15 ` [RESEND PATCH v4 0/8] bpf powerpc: Add BPF_PROBE_MEM support in powerpc JIT compiler David Laight
2021-10-14  8:15   ` David Laight
2021-10-14  8:33   ` Christophe Leroy
2021-10-14  8:33     ` Christophe Leroy
2021-10-14  9:52     ` David Laight
2021-10-14  9:52       ` David Laight
2021-11-25  9:36 ` Michael Ellerman
2021-11-25  9:36   ` Michael Ellerman

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.