* Re: [PATCH v2 04/10] powerpc/bpf: Fix BPF_SUB when imm == 0x80000000
From: Christophe Leroy @ 2021-10-06 4:55 UTC (permalink / raw)
To: Naveen N. Rao, Michael Ellerman, Nicholas Piggin, Jordan Niethe,
Daniel Borkmann, Alexei Starovoitov, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <fc4b1276eb10761fd7ce0814c8dd089da2815251.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Le 05/10/2021 à 22:25, Naveen N. Rao a écrit :
> We aren't handling subtraction involving an immediate value of
> 0x80000000 properly. Fix the same.
>
> Fixes: 156d0e290e969c ("powerpc/ebpf/jit: Implement JIT compiler for extended BPF")
> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
> ---
> Changelog:
> - Split up BPF_ADD and BPF_SUB cases per Christophe's comments
>
> arch/powerpc/net/bpf_jit_comp64.c | 27 +++++++++++++++++----------
> 1 file changed, 17 insertions(+), 10 deletions(-)
>
> diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
> index d67f6d62e2e1ff..6626e6c17d4ed2 100644
> --- a/arch/powerpc/net/bpf_jit_comp64.c
> +++ b/arch/powerpc/net/bpf_jit_comp64.c
> @@ -330,18 +330,25 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
> EMIT(PPC_RAW_SUB(dst_reg, dst_reg, src_reg));
> goto bpf_alu32_trunc;
> case BPF_ALU | BPF_ADD | BPF_K: /* (u32) dst += (u32) imm */
> - case BPF_ALU | BPF_SUB | BPF_K: /* (u32) dst -= (u32) imm */
> case BPF_ALU64 | BPF_ADD | BPF_K: /* dst += imm */
> + if (!imm) {
> + goto bpf_alu32_trunc;
> + } else if (imm >= -32768 && imm < 32768) {
> + EMIT(PPC_RAW_ADDI(dst_reg, dst_reg, IMM_L(imm)));
> + } else {
> + PPC_LI32(b2p[TMP_REG_1], imm);
> + EMIT(PPC_RAW_ADD(dst_reg, dst_reg, b2p[TMP_REG_1]));
> + }
> + goto bpf_alu32_trunc;
> + case BPF_ALU | BPF_SUB | BPF_K: /* (u32) dst -= (u32) imm */
> case BPF_ALU64 | BPF_SUB | BPF_K: /* dst -= imm */
> - if (BPF_OP(code) == BPF_SUB)
> - imm = -imm;
> - if (imm) {
> - if (imm >= -32768 && imm < 32768)
> - EMIT(PPC_RAW_ADDI(dst_reg, dst_reg, IMM_L(imm)));
> - else {
> - PPC_LI32(b2p[TMP_REG_1], imm);
> - EMIT(PPC_RAW_ADD(dst_reg, dst_reg, b2p[TMP_REG_1]));
> - }
> + if (!imm) {
> + goto bpf_alu32_trunc;
> + } else if (imm > -32768 && imm < 32768) {
Why do you exclude imm == 32768 ?
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
> + EMIT(PPC_RAW_ADDI(dst_reg, dst_reg, IMM_L(-imm)));
> + } else {
> + PPC_LI32(b2p[TMP_REG_1], imm);
> + EMIT(PPC_RAW_SUB(dst_reg, dst_reg, b2p[TMP_REG_1]));
> }
> goto bpf_alu32_trunc;
> case BPF_ALU | BPF_MUL | BPF_X: /* (u32) dst *= (u32) src */
>
^ permalink raw reply
* Re: [PATCH v2 03/10] powerpc/bpf: Fix BPF_MOD when imm == 1
From: Christophe Leroy @ 2021-10-06 4:52 UTC (permalink / raw)
To: Naveen N. Rao, Michael Ellerman, Nicholas Piggin, Jordan Niethe,
Daniel Borkmann, Alexei Starovoitov, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <c674ca18c3046885602caebb326213731c675d06.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Le 05/10/2021 à 22:25, Naveen N. Rao a écrit :
> Only ignore the operation if dividing by 1.
>
> Acked-by: Song Liu <songliubraving@fb.com>
> Acked-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
> Tested-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
> Fixes: 156d0e290e969c ("powerpc/ebpf/jit: Implement JIT compiler for extended BPF")
> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
> ---
> arch/powerpc/net/bpf_jit_comp64.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
> index f06c62089b1457..d67f6d62e2e1ff 100644
> --- a/arch/powerpc/net/bpf_jit_comp64.c
> +++ b/arch/powerpc/net/bpf_jit_comp64.c
> @@ -391,8 +391,14 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
> case BPF_ALU64 | BPF_DIV | BPF_K: /* dst /= imm */
> if (imm == 0)
> return -EINVAL;
> - else if (imm == 1)
> - goto bpf_alu32_trunc;
> + if (imm == 1) {
> + if (BPF_OP(code) == BPF_DIV) {
> + goto bpf_alu32_trunc;
> + } else {
> + EMIT(PPC_RAW_LI(dst_reg, 0));
> + break;
> + }
> + }
>
> PPC_LI32(b2p[TMP_REG_1], imm);
> switch (BPF_CLASS(code)) {
>
^ permalink raw reply
* Re: [PATCH v2 02/10] powerpc/bpf: Validate branch ranges
From: LEROY Christophe @ 2021-10-06 4:51 UTC (permalink / raw)
To: Naveen N. Rao, Michael Ellerman, Nicholas Piggin, Jordan Niethe,
Daniel Borkmann, Alexei Starovoitov, Johan Almbladh, Song Liu
Cc: bpf@vger.kernel.org, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <71d33a6b7603ec1013c9734dd8bdd4ff5e929142.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Le 05/10/2021 à 22:25, Naveen N. Rao a écrit :
> Add checks to ensure that we never emit branch instructions with
> truncated branch offsets.
>
> Acked-by: Song Liu <songliubraving@fb.com>
> Acked-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
> Tested-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
> Suggested-by: Michael Ellerman <mpe@ellerman.id.au>
> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
> ---
> arch/powerpc/net/bpf_jit.h | 26 ++++++++++++++++++++------
> arch/powerpc/net/bpf_jit_comp.c | 6 +++++-
> arch/powerpc/net/bpf_jit_comp32.c | 8 ++++++--
> arch/powerpc/net/bpf_jit_comp64.c | 8 ++++++--
> 4 files changed, 37 insertions(+), 11 deletions(-)
>
> diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
> index 935ea95b66359e..7e9b978b768ed9 100644
> --- a/arch/powerpc/net/bpf_jit.h
> +++ b/arch/powerpc/net/bpf_jit.h
> @@ -24,16 +24,30 @@
> #define EMIT(instr) PLANT_INSTR(image, ctx->idx, instr)
>
> /* Long jump; (unconditional 'branch') */
> -#define PPC_JMP(dest) EMIT(PPC_INST_BRANCH | \
> - (((dest) - (ctx->idx * 4)) & 0x03fffffc))
> +#define PPC_JMP(dest) \
> + do { \
> + long offset = (long)(dest) - (ctx->idx * 4); \
> + if (!is_offset_in_branch_range(offset)) { \
> + pr_err_ratelimited("Branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx); \
> + return -ERANGE; \
> + } \
> + EMIT(PPC_INST_BRANCH | (offset & 0x03fffffc)); \
> + } while (0)
> +
> /* blr; (unconditional 'branch' with link) to absolute address */
> #define PPC_BL_ABS(dest) EMIT(PPC_INST_BL | \
> (((dest) - (unsigned long)(image + ctx->idx)) & 0x03fffffc))
> /* "cond" here covers BO:BI fields. */
> -#define PPC_BCC_SHORT(cond, dest) EMIT(PPC_INST_BRANCH_COND | \
> - (((cond) & 0x3ff) << 16) | \
> - (((dest) - (ctx->idx * 4)) & \
> - 0xfffc))
> +#define PPC_BCC_SHORT(cond, dest) \
> + do { \
> + long offset = (long)(dest) - (ctx->idx * 4); \
> + if (!is_offset_in_cond_branch_range(offset)) { \
> + pr_err_ratelimited("Conditional branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx); \
> + return -ERANGE; \
> + } \
> + EMIT(PPC_INST_BRANCH_COND | (((cond) & 0x3ff) << 16) | (offset & 0xfffc)); \
> + } while (0)
> +
> /* Sign-extended 32-bit immediate load */
> #define PPC_LI32(d, i) do { \
> if ((int)(uintptr_t)(i) >= -32768 && \
> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> index 53aefee3fe70be..fcbf7a917c566e 100644
> --- a/arch/powerpc/net/bpf_jit_comp.c
> +++ b/arch/powerpc/net/bpf_jit_comp.c
> @@ -210,7 +210,11 @@ 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);
> - bpf_jit_build_body(fp, code_base, &cgctx, addrs, extra_pass);
> + if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, extra_pass)) {
> + bpf_jit_binary_free(bpf_hdr);
> + fp = org_fp;
> + goto out_addrs;
> + }
> bpf_jit_build_epilogue(code_base, &cgctx);
>
> if (bpf_jit_enable > 1)
> diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
> index beb12cbc8c2994..a74d52204f8da2 100644
> --- a/arch/powerpc/net/bpf_jit_comp32.c
> +++ b/arch/powerpc/net/bpf_jit_comp32.c
> @@ -200,7 +200,7 @@ void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 fun
> }
> }
>
> -static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
> +static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
> {
> /*
> * By now, the eBPF program has already setup parameters in r3-r6
> @@ -261,7 +261,9 @@ static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32
> bpf_jit_emit_common_epilogue(image, ctx);
>
> EMIT(PPC_RAW_BCTR());
> +
> /* out: */
> + return 0;
> }
>
> /* Assemble the body code between the prologue & epilogue */
> @@ -1090,7 +1092,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
> */
> case BPF_JMP | BPF_TAIL_CALL:
> ctx->seen |= SEEN_TAILCALL;
> - bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
> + ret = bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
> + if (ret < 0)
> + return ret;
> break;
>
> default:
> diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
> index b87a63dba9c8fb..f06c62089b1457 100644
> --- a/arch/powerpc/net/bpf_jit_comp64.c
> +++ b/arch/powerpc/net/bpf_jit_comp64.c
> @@ -206,7 +206,7 @@ void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 fun
> EMIT(PPC_RAW_BCTRL());
> }
>
> -static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
> +static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
> {
> /*
> * By now, the eBPF program has already setup parameters in r3, r4 and r5
> @@ -267,7 +267,9 @@ static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32
> bpf_jit_emit_common_epilogue(image, ctx);
>
> EMIT(PPC_RAW_BCTR());
> +
> /* out: */
> + return 0;
> }
>
> /* Assemble the body code between the prologue & epilogue */
> @@ -993,7 +995,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
> */
> case BPF_JMP | BPF_TAIL_CALL:
> ctx->seen |= SEEN_TAILCALL;
> - bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
> + ret = bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
> + if (ret < 0)
> + return ret;
> break;
>
> default:
>
^ permalink raw reply
* Re: [PATCH v2 02/10] powerpc/bpf: Validate branch ranges
From: Christophe Leroy @ 2021-10-06 4:51 UTC (permalink / raw)
To: Naveen N. Rao, Michael Ellerman, Nicholas Piggin, Jordan Niethe,
Daniel Borkmann, Alexei Starovoitov, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <71d33a6b7603ec1013c9734dd8bdd4ff5e929142.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Le 05/10/2021 à 22:25, Naveen N. Rao a écrit :
> Add checks to ensure that we never emit branch instructions with
> truncated branch offsets.
>
> Acked-by: Song Liu <songliubraving@fb.com>
> Acked-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
> Tested-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
> Suggested-by: Michael Ellerman <mpe@ellerman.id.au>
> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
> ---
> arch/powerpc/net/bpf_jit.h | 26 ++++++++++++++++++++------
> arch/powerpc/net/bpf_jit_comp.c | 6 +++++-
> arch/powerpc/net/bpf_jit_comp32.c | 8 ++++++--
> arch/powerpc/net/bpf_jit_comp64.c | 8 ++++++--
> 4 files changed, 37 insertions(+), 11 deletions(-)
>
> diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
> index 935ea95b66359e..7e9b978b768ed9 100644
> --- a/arch/powerpc/net/bpf_jit.h
> +++ b/arch/powerpc/net/bpf_jit.h
> @@ -24,16 +24,30 @@
> #define EMIT(instr) PLANT_INSTR(image, ctx->idx, instr)
>
> /* Long jump; (unconditional 'branch') */
> -#define PPC_JMP(dest) EMIT(PPC_INST_BRANCH | \
> - (((dest) - (ctx->idx * 4)) & 0x03fffffc))
> +#define PPC_JMP(dest) \
> + do { \
> + long offset = (long)(dest) - (ctx->idx * 4); \
> + if (!is_offset_in_branch_range(offset)) { \
> + pr_err_ratelimited("Branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx); \
> + return -ERANGE; \
> + } \
> + EMIT(PPC_INST_BRANCH | (offset & 0x03fffffc)); \
> + } while (0)
> +
> /* blr; (unconditional 'branch' with link) to absolute address */
> #define PPC_BL_ABS(dest) EMIT(PPC_INST_BL | \
> (((dest) - (unsigned long)(image + ctx->idx)) & 0x03fffffc))
> /* "cond" here covers BO:BI fields. */
> -#define PPC_BCC_SHORT(cond, dest) EMIT(PPC_INST_BRANCH_COND | \
> - (((cond) & 0x3ff) << 16) | \
> - (((dest) - (ctx->idx * 4)) & \
> - 0xfffc))
> +#define PPC_BCC_SHORT(cond, dest) \
> + do { \
> + long offset = (long)(dest) - (ctx->idx * 4); \
> + if (!is_offset_in_cond_branch_range(offset)) { \
> + pr_err_ratelimited("Conditional branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx); \
> + return -ERANGE; \
> + } \
> + EMIT(PPC_INST_BRANCH_COND | (((cond) & 0x3ff) << 16) | (offset & 0xfffc)); \
> + } while (0)
> +
> /* Sign-extended 32-bit immediate load */
> #define PPC_LI32(d, i) do { \
> if ((int)(uintptr_t)(i) >= -32768 && \
> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> index 53aefee3fe70be..fcbf7a917c566e 100644
> --- a/arch/powerpc/net/bpf_jit_comp.c
> +++ b/arch/powerpc/net/bpf_jit_comp.c
> @@ -210,7 +210,11 @@ 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);
> - bpf_jit_build_body(fp, code_base, &cgctx, addrs, extra_pass);
> + if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, extra_pass)) {
> + bpf_jit_binary_free(bpf_hdr);
> + fp = org_fp;
> + goto out_addrs;
> + }
> bpf_jit_build_epilogue(code_base, &cgctx);
>
> if (bpf_jit_enable > 1)
> diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
> index beb12cbc8c2994..a74d52204f8da2 100644
> --- a/arch/powerpc/net/bpf_jit_comp32.c
> +++ b/arch/powerpc/net/bpf_jit_comp32.c
> @@ -200,7 +200,7 @@ void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 fun
> }
> }
>
> -static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
> +static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
> {
> /*
> * By now, the eBPF program has already setup parameters in r3-r6
> @@ -261,7 +261,9 @@ static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32
> bpf_jit_emit_common_epilogue(image, ctx);
>
> EMIT(PPC_RAW_BCTR());
> +
> /* out: */
> + return 0;
> }
>
> /* Assemble the body code between the prologue & epilogue */
> @@ -1090,7 +1092,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
> */
> case BPF_JMP | BPF_TAIL_CALL:
> ctx->seen |= SEEN_TAILCALL;
> - bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
> + ret = bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
> + if (ret < 0)
> + return ret;
> break;
>
> default:
> diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
> index b87a63dba9c8fb..f06c62089b1457 100644
> --- a/arch/powerpc/net/bpf_jit_comp64.c
> +++ b/arch/powerpc/net/bpf_jit_comp64.c
> @@ -206,7 +206,7 @@ void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 fun
> EMIT(PPC_RAW_BCTRL());
> }
>
> -static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
> +static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
> {
> /*
> * By now, the eBPF program has already setup parameters in r3, r4 and r5
> @@ -267,7 +267,9 @@ static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32
> bpf_jit_emit_common_epilogue(image, ctx);
>
> EMIT(PPC_RAW_BCTR());
> +
> /* out: */
> + return 0;
> }
>
> /* Assemble the body code between the prologue & epilogue */
> @@ -993,7 +995,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
> */
> case BPF_JMP | BPF_TAIL_CALL:
> ctx->seen |= SEEN_TAILCALL;
> - bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
> + ret = bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
> + if (ret < 0)
> + return ret;
> break;
>
> default:
>
^ permalink raw reply
* Re: [PATCH v2 01/10] powerpc/lib: Add helper to check if offset is within conditional branch range
From: Christophe Leroy @ 2021-10-06 4:50 UTC (permalink / raw)
To: Naveen N. Rao, Michael Ellerman, Nicholas Piggin, Jordan Niethe,
Daniel Borkmann, Alexei Starovoitov, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <442b69a34ced32ca346a0d9a855f3f6cfdbbbd41.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Le 05/10/2021 à 22:25, Naveen N. Rao a écrit :
> Add a helper to check if a given offset is within the branch range for a
> powerpc conditional branch instruction, and update some sites to use the
> new helper.
>
> Acked-by: Song Liu <songliubraving@fb.com>
> Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
> ---
> Changelog:
> - Change 0x7FFF to 0x7fff, per Christophe
>
>
> arch/powerpc/include/asm/code-patching.h | 1 +
> arch/powerpc/lib/code-patching.c | 7 ++++++-
> arch/powerpc/net/bpf_jit.h | 7 +------
> 3 files changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
> index a95f63788c6b14..4ba834599c4d4c 100644
> --- a/arch/powerpc/include/asm/code-patching.h
> +++ b/arch/powerpc/include/asm/code-patching.h
> @@ -23,6 +23,7 @@
> #define BRANCH_ABSOLUTE 0x2
>
> bool is_offset_in_branch_range(long offset);
> +bool is_offset_in_cond_branch_range(long offset);
> int create_branch(struct ppc_inst *instr, const u32 *addr,
> unsigned long target, int flags);
> int create_cond_branch(struct ppc_inst *instr, const u32 *addr,
> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
> index f9a3019e37b43c..c5ed9882383521 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -228,6 +228,11 @@ bool is_offset_in_branch_range(long offset)
> return (offset >= -0x2000000 && offset <= 0x1fffffc && !(offset & 0x3));
> }
>
> +bool is_offset_in_cond_branch_range(long offset)
> +{
> + return offset >= -0x8000 && offset <= 0x7fff && !(offset & 0x3);
> +}
> +
> /*
> * Helper to check if a given instruction is a conditional branch
> * Derived from the conditional checks in analyse_instr()
> @@ -280,7 +285,7 @@ int create_cond_branch(struct ppc_inst *instr, const u32 *addr,
> offset = offset - (unsigned long)addr;
>
> /* Check we can represent the target in the instruction format */
> - if (offset < -0x8000 || offset > 0x7FFF || offset & 0x3)
> + if (!is_offset_in_cond_branch_range(offset))
> return 1;
>
> /* Mask out the flags and target, so they don't step on each other. */
> diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
> index 99fad093f43ec1..935ea95b66359e 100644
> --- a/arch/powerpc/net/bpf_jit.h
> +++ b/arch/powerpc/net/bpf_jit.h
> @@ -78,11 +78,6 @@
> #define PPC_FUNC_ADDR(d,i) do { PPC_LI32(d, i); } while(0)
> #endif
>
> -static inline bool is_nearbranch(int offset)
> -{
> - return (offset < 32768) && (offset >= -32768);
> -}
> -
> /*
> * The fly in the ointment of code size changing from pass to pass is
> * avoided by padding the short branch case with a NOP. If code size differs
> @@ -91,7 +86,7 @@ static inline bool is_nearbranch(int offset)
> * state.
> */
> #define PPC_BCC(cond, dest) do { \
> - if (is_nearbranch((dest) - (ctx->idx * 4))) { \
> + if (is_offset_in_cond_branch_range((long)(dest) - (ctx->idx * 4))) { \
> PPC_BCC_SHORT(cond, dest); \
> EMIT(PPC_RAW_NOP()); \
> } else { \
>
^ permalink raw reply
* [PATCH kernel v2] powerps/pseries/dma: Add support for 2M IOMMU page size
From: Alexey Kardashevskiy @ 2021-10-06 4:47 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Frederic Barrat, Leonardo Bras
The upcoming PAPR spec adds a 2M page size, bit 23 right after 16G page
size in the "ibm,query-pe-dma-window" call.
This adds support for the new page size. Since the new page size is out
of sorted order, this changes the loop to not assume that shift[] is
sorted.
This has now been tested and is known to work on a pre-release version
of phyp.
Reviewed-by: Leonardo Bras <leobras.c@gmail.com>
Reviewed-by: Frederic Barrat <fbarrat@linux.ibm.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
Changes:
v2:
* adjusted the commit log about testing
---
arch/powerpc/platforms/pseries/iommu.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index dab5c56ffd0e..269f61d519c2 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -1159,14 +1159,15 @@ static void reset_dma_window(struct pci_dev *dev, struct device_node *par_dn)
/* Return largest page shift based on "IO Page Sizes" output of ibm,query-pe-dma-window. */
static int iommu_get_page_shift(u32 query_page_size)
{
- /* Supported IO page-sizes according to LoPAR */
+ /* Supported IO page-sizes according to LoPAR, note that 2M is out of order */
const int shift[] = {
__builtin_ctzll(SZ_4K), __builtin_ctzll(SZ_64K), __builtin_ctzll(SZ_16M),
__builtin_ctzll(SZ_32M), __builtin_ctzll(SZ_64M), __builtin_ctzll(SZ_128M),
- __builtin_ctzll(SZ_256M), __builtin_ctzll(SZ_16G)
+ __builtin_ctzll(SZ_256M), __builtin_ctzll(SZ_16G), __builtin_ctzll(SZ_2M)
};
int i = ARRAY_SIZE(shift) - 1;
+ int ret = 0;
/*
* On LoPAR, ibm,query-pe-dma-window outputs "IO Page Sizes" using a bit field:
@@ -1176,11 +1177,10 @@ static int iommu_get_page_shift(u32 query_page_size)
*/
for (; i >= 0 ; i--) {
if (query_page_size & (1 << i))
- return shift[i];
+ ret = max(ret, shift[i]);
}
- /* No valid page size found. */
- return 0;
+ return ret;
}
static struct property *ddw_property_create(const char *propname, u32 liobn, u64 dma_addr,
--
2.30.2
^ permalink raw reply related
* Re: [RFC 5/5] ipmi:bt-bmc: Add Microwatt
From: Anton Blanchard @ 2021-10-06 3:06 UTC (permalink / raw)
To: Joel Stanley
Cc: Michael Neuling, Andrew Jeffery, Alistair Popple,
Cédric Le Goater, Jeremy Kerr, linuxppc-dev
In-Reply-To: <CACPK8XetfycURqsznmA1dMZ5h5=uJb6xrzg-ihsZH9Xft=phdA@mail.gmail.com>
Hi Joel,
> The series looks good.
>
> I've got a couple of patches on the ipmi list that this will conflict
> with:
>
> https://sourceforge.net/p/openipmi/mailman/message/37345391/
> https://lore.kernel.org/all/20210903015314.177987-1-joel@jms.id.au/
>
> If there's no feedback from others I suggest basing your series on top
> of those, and sending them to Corey on the ipmi list to merge.
Looks good, will do.
Thanks,
Anton
> Cheers,
>
> Joel
>
> >
> > Signed-off-by: Anton Blanchard <anton@ozlabs.org>
> > ---
> > .../devicetree/bindings/ipmi/ibt-bmc.txt | 1 +
> > drivers/char/ipmi/Kconfig | 8 ++-
> > drivers/char/ipmi/bt-bmc.c | 69
> > +++++++++++++++++++ 3 files changed, 75 insertions(+), 3
> > deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
> > b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt index
> > 78ee716a950e..1b661daf0193 100644 ---
> > a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt +++
> > b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt @@ -9,6 +9,7
> > @@ Required properties:
> > - compatible : should be one of
> > "aspeed,ast2400-ibt-bmc"
> > "aspeed,ast2500-ibt-bmc"
> > + "ibm,microwatt-ibt-bmc"
> > - reg: physical address and size of the registers
> >
> > Optional properties:
> > diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
> > index 8b2f0f675e5f..079302f4eef2 100644
> > --- a/drivers/char/ipmi/Kconfig
> > +++ b/drivers/char/ipmi/Kconfig
> > @@ -152,13 +152,15 @@ config IPMI_KCS_BMC_SERIO
> > called kcs_bmc_serio.
> >
> > config BT_IPMI_BMC
> > - depends on ARCH_ASPEED || COMPILE_TEST
> > + depends on ARCH_ASPEED || PPC_MICROWATT || COMPILE_TEST
> > depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
> > tristate "BT IPMI bmc driver"
> > help
> > Provides a driver for the BT (Block Transfer) IPMI
> > interface
> > - found on Aspeed SOCs (AST2400 and AST2500). The driver
> > - implements the BMC side of the BT interface.
> > + found on Aspeed SOCs (AST2400 and AST2500) as well as the
> > OpenPOWER
> > + LPC peripheral macro at
> > + <https://github.com/OpenPOWERFoundation/lpcperipheral>
> > + The driver implements the BMC side of the BT interface.
> >
> > config IPMB_DEVICE_INTERFACE
> > tristate 'IPMB Interface handler'
> > diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
> > index b48e04405ac4..24327b57c60b 100644
> > --- a/drivers/char/ipmi/bt-bmc.c
> > +++ b/drivers/char/ipmi/bt-bmc.c
> > @@ -41,6 +41,11 @@
> > #define BT_CR2_IRQ_HBUSY 0x40
> > #define ASPEED_BT_CR3 0xc
> >
> > +#define MICROWATT_IRQ_MASK 0x0
> > +#define MICROWATT_IRQ_STATUS 0x4
> > +#define IRQ_HOST_TO_BMC_ATTN 0x1
> > +#define IRQ_HOST_NOT_BUSY 0x2
> > +
> > #define BT_CTRL 0x10
> > #define BT_CTRL_B_BUSY 0x80
> > #define BT_CTRL_H_BUSY 0x40
> > @@ -395,6 +400,27 @@ static irqreturn_t aspeed_bt_bmc_irq(int irq,
> > void *arg) return IRQ_HANDLED;
> > }
> >
> > +static irqreturn_t microwatt_bt_bmc_irq(int irq, void *arg)
> > +{
> > + struct bt_bmc *bt_bmc = arg;
> > + u32 reg;
> > + int rc;
> > +
> > + rc = regmap_read(bt_bmc->map, bt_bmc->offset +
> > MICROWATT_IRQ_STATUS, ®);
> > + if (rc)
> > + return IRQ_NONE;
> > +
> > + /* Interrupt wasn't something we knew about */
> > + if (!(reg & (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY)))
> > + return IRQ_NONE;
> > +
> > + /* ack all pending IRQs */
> > + regmap_write(bt_bmc->map, bt_bmc->offset +
> > MICROWATT_IRQ_STATUS, 0); +
> > + wake_up(&bt_bmc->queue);
> > + return IRQ_HANDLED;
> > +}
> > +
> > static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
> > struct platform_device *pdev)
> > {
> > @@ -446,6 +472,48 @@ static const struct bt_bmc_ops
> > aspeed_bt_bmc_ops = { .enable_bt = aspeed_enable_bt,
> > };
> >
> > +static int microwatt_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
> > + struct platform_device *pdev)
> > +{
> > + struct device *dev = &pdev->dev;
> > + int rc;
> > +
> > + bt_bmc->irq = platform_get_irq_optional(pdev, 0);
> > + if (bt_bmc->irq < 0)
> > + return bt_bmc->irq;
> > +
> > + rc = devm_request_irq(dev, bt_bmc->irq,
> > microwatt_bt_bmc_irq, IRQF_SHARED,
> > + DEVICE_NAME, bt_bmc);
> > + if (rc < 0) {
> > + dev_warn(dev, "Unable to request IRQ %d\n",
> > bt_bmc->irq);
> > + bt_bmc->irq = rc;
> > + return rc;
> > + }
> > +
> > + /*
> > + * Configure the hardware to give us an interrupt whenever
> > the H2B
> > + * bit is set or the HBUSY bit is cleared.
> > + *
> > + * H2B will be asserted when the bmc has data for us; HBUSY
> > + * will be cleared (along with B2H) when we can write the
> > next
> > + * message to the BT buffer
> > + */
> > + rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset +
> > MICROWATT_IRQ_MASK,
> > + (IRQ_HOST_TO_BMC_ATTN |
> > IRQ_HOST_NOT_BUSY),
> > + (IRQ_HOST_TO_BMC_ATTN |
> > IRQ_HOST_NOT_BUSY)); +
> > + return rc;
> > +}
> > +
> > +static void microwatt_enable_bt(struct bt_bmc *bt_bmc)
> > +{
> > +}
> > +
> > +static const struct bt_bmc_ops microwatt_bt_bmc_ops = {
> > + .config_irq = microwatt_bt_bmc_config_irq,
> > + .enable_bt = microwatt_enable_bt,
> > +};
> > +
> > static int bt_bmc_probe(struct platform_device *pdev)
> > {
> > struct bt_bmc *bt_bmc;
> > @@ -530,6 +598,7 @@ static int bt_bmc_remove(struct platform_device
> > *pdev) static const struct of_device_id bt_bmc_match[] = {
> > { .compatible = "aspeed,ast2400-ibt-bmc", .data =
> > &aspeed_bt_bmc_ops }, { .compatible = "aspeed,ast2500-ibt-bmc",
> > .data = &aspeed_bt_bmc_ops },
> > + { .compatible = "ibm,microwatt-ibt-bmc", .data =
> > µwatt_bt_bmc_ops }, { },
> > };
> >
> > --
> > 2.31.1
> >
>
^ permalink raw reply
* Re: [RFC 5/5] ipmi:bt-bmc: Add Microwatt
From: Joel Stanley @ 2021-10-06 2:35 UTC (permalink / raw)
To: Anton Blanchard
Cc: Michael Neuling, Andrew Jeffery, Alistair Popple,
Cédric Le Goater, Jeremy Kerr, linuxppc-dev
In-Reply-To: <20211006021205.2579057-5-anton@ozlabs.org>
Hi Anton,
On Wed, 6 Oct 2021 at 02:12, Anton Blanchard <anton@ozlabs.org> wrote:
>
> This adds the Microwatt specific bits, including interrupt support.
The series looks good.
I've got a couple of patches on the ipmi list that this will conflict with:
https://sourceforge.net/p/openipmi/mailman/message/37345391/
https://lore.kernel.org/all/20210903015314.177987-1-joel@jms.id.au/
If there's no feedback from others I suggest basing your series on top
of those, and sending them to Corey on the ipmi list to merge.
Cheers,
Joel
>
> Signed-off-by: Anton Blanchard <anton@ozlabs.org>
> ---
> .../devicetree/bindings/ipmi/ibt-bmc.txt | 1 +
> drivers/char/ipmi/Kconfig | 8 ++-
> drivers/char/ipmi/bt-bmc.c | 69 +++++++++++++++++++
> 3 files changed, 75 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
> index 78ee716a950e..1b661daf0193 100644
> --- a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
> +++ b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
> @@ -9,6 +9,7 @@ Required properties:
> - compatible : should be one of
> "aspeed,ast2400-ibt-bmc"
> "aspeed,ast2500-ibt-bmc"
> + "ibm,microwatt-ibt-bmc"
> - reg: physical address and size of the registers
>
> Optional properties:
> diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
> index 8b2f0f675e5f..079302f4eef2 100644
> --- a/drivers/char/ipmi/Kconfig
> +++ b/drivers/char/ipmi/Kconfig
> @@ -152,13 +152,15 @@ config IPMI_KCS_BMC_SERIO
> called kcs_bmc_serio.
>
> config BT_IPMI_BMC
> - depends on ARCH_ASPEED || COMPILE_TEST
> + depends on ARCH_ASPEED || PPC_MICROWATT || COMPILE_TEST
> depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
> tristate "BT IPMI bmc driver"
> help
> Provides a driver for the BT (Block Transfer) IPMI interface
> - found on Aspeed SOCs (AST2400 and AST2500). The driver
> - implements the BMC side of the BT interface.
> + found on Aspeed SOCs (AST2400 and AST2500) as well as the OpenPOWER
> + LPC peripheral macro at
> + <https://github.com/OpenPOWERFoundation/lpcperipheral>
> + The driver implements the BMC side of the BT interface.
>
> config IPMB_DEVICE_INTERFACE
> tristate 'IPMB Interface handler'
> diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
> index b48e04405ac4..24327b57c60b 100644
> --- a/drivers/char/ipmi/bt-bmc.c
> +++ b/drivers/char/ipmi/bt-bmc.c
> @@ -41,6 +41,11 @@
> #define BT_CR2_IRQ_HBUSY 0x40
> #define ASPEED_BT_CR3 0xc
>
> +#define MICROWATT_IRQ_MASK 0x0
> +#define MICROWATT_IRQ_STATUS 0x4
> +#define IRQ_HOST_TO_BMC_ATTN 0x1
> +#define IRQ_HOST_NOT_BUSY 0x2
> +
> #define BT_CTRL 0x10
> #define BT_CTRL_B_BUSY 0x80
> #define BT_CTRL_H_BUSY 0x40
> @@ -395,6 +400,27 @@ static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
> return IRQ_HANDLED;
> }
>
> +static irqreturn_t microwatt_bt_bmc_irq(int irq, void *arg)
> +{
> + struct bt_bmc *bt_bmc = arg;
> + u32 reg;
> + int rc;
> +
> + rc = regmap_read(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_STATUS, ®);
> + if (rc)
> + return IRQ_NONE;
> +
> + /* Interrupt wasn't something we knew about */
> + if (!(reg & (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY)))
> + return IRQ_NONE;
> +
> + /* ack all pending IRQs */
> + regmap_write(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_STATUS, 0);
> +
> + wake_up(&bt_bmc->queue);
> + return IRQ_HANDLED;
> +}
> +
> static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
> struct platform_device *pdev)
> {
> @@ -446,6 +472,48 @@ static const struct bt_bmc_ops aspeed_bt_bmc_ops = {
> .enable_bt = aspeed_enable_bt,
> };
>
> +static int microwatt_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
> + struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + int rc;
> +
> + bt_bmc->irq = platform_get_irq_optional(pdev, 0);
> + if (bt_bmc->irq < 0)
> + return bt_bmc->irq;
> +
> + rc = devm_request_irq(dev, bt_bmc->irq, microwatt_bt_bmc_irq, IRQF_SHARED,
> + DEVICE_NAME, bt_bmc);
> + if (rc < 0) {
> + dev_warn(dev, "Unable to request IRQ %d\n", bt_bmc->irq);
> + bt_bmc->irq = rc;
> + return rc;
> + }
> +
> + /*
> + * Configure the hardware to give us an interrupt whenever the H2B
> + * bit is set or the HBUSY bit is cleared.
> + *
> + * H2B will be asserted when the bmc has data for us; HBUSY
> + * will be cleared (along with B2H) when we can write the next
> + * message to the BT buffer
> + */
> + rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_MASK,
> + (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY),
> + (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY));
> +
> + return rc;
> +}
> +
> +static void microwatt_enable_bt(struct bt_bmc *bt_bmc)
> +{
> +}
> +
> +static const struct bt_bmc_ops microwatt_bt_bmc_ops = {
> + .config_irq = microwatt_bt_bmc_config_irq,
> + .enable_bt = microwatt_enable_bt,
> +};
> +
> static int bt_bmc_probe(struct platform_device *pdev)
> {
> struct bt_bmc *bt_bmc;
> @@ -530,6 +598,7 @@ static int bt_bmc_remove(struct platform_device *pdev)
> static const struct of_device_id bt_bmc_match[] = {
> { .compatible = "aspeed,ast2400-ibt-bmc", .data = &aspeed_bt_bmc_ops },
> { .compatible = "aspeed,ast2500-ibt-bmc", .data = &aspeed_bt_bmc_ops },
> + { .compatible = "ibm,microwatt-ibt-bmc", .data = µwatt_bt_bmc_ops },
> { },
> };
>
> --
> 2.31.1
>
^ permalink raw reply
* [RFC 5/5] ipmi:bt-bmc: Add Microwatt
From: Anton Blanchard @ 2021-10-06 2:12 UTC (permalink / raw)
To: alistair, joel, andrew, clg, mikey, jk; +Cc: linuxppc-dev
In-Reply-To: <20211006021205.2579057-1-anton@ozlabs.org>
This adds the Microwatt specific bits, including interrupt support.
Signed-off-by: Anton Blanchard <anton@ozlabs.org>
---
.../devicetree/bindings/ipmi/ibt-bmc.txt | 1 +
drivers/char/ipmi/Kconfig | 8 ++-
drivers/char/ipmi/bt-bmc.c | 69 +++++++++++++++++++
3 files changed, 75 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
index 78ee716a950e..1b661daf0193 100644
--- a/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
+++ b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
@@ -9,6 +9,7 @@ Required properties:
- compatible : should be one of
"aspeed,ast2400-ibt-bmc"
"aspeed,ast2500-ibt-bmc"
+ "ibm,microwatt-ibt-bmc"
- reg: physical address and size of the registers
Optional properties:
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index 8b2f0f675e5f..079302f4eef2 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -152,13 +152,15 @@ config IPMI_KCS_BMC_SERIO
called kcs_bmc_serio.
config BT_IPMI_BMC
- depends on ARCH_ASPEED || COMPILE_TEST
+ depends on ARCH_ASPEED || PPC_MICROWATT || COMPILE_TEST
depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
tristate "BT IPMI bmc driver"
help
Provides a driver for the BT (Block Transfer) IPMI interface
- found on Aspeed SOCs (AST2400 and AST2500). The driver
- implements the BMC side of the BT interface.
+ found on Aspeed SOCs (AST2400 and AST2500) as well as the OpenPOWER
+ LPC peripheral macro at
+ <https://github.com/OpenPOWERFoundation/lpcperipheral>
+ The driver implements the BMC side of the BT interface.
config IPMB_DEVICE_INTERFACE
tristate 'IPMB Interface handler'
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index b48e04405ac4..24327b57c60b 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -41,6 +41,11 @@
#define BT_CR2_IRQ_HBUSY 0x40
#define ASPEED_BT_CR3 0xc
+#define MICROWATT_IRQ_MASK 0x0
+#define MICROWATT_IRQ_STATUS 0x4
+#define IRQ_HOST_TO_BMC_ATTN 0x1
+#define IRQ_HOST_NOT_BUSY 0x2
+
#define BT_CTRL 0x10
#define BT_CTRL_B_BUSY 0x80
#define BT_CTRL_H_BUSY 0x40
@@ -395,6 +400,27 @@ static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
return IRQ_HANDLED;
}
+static irqreturn_t microwatt_bt_bmc_irq(int irq, void *arg)
+{
+ struct bt_bmc *bt_bmc = arg;
+ u32 reg;
+ int rc;
+
+ rc = regmap_read(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_STATUS, ®);
+ if (rc)
+ return IRQ_NONE;
+
+ /* Interrupt wasn't something we knew about */
+ if (!(reg & (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY)))
+ return IRQ_NONE;
+
+ /* ack all pending IRQs */
+ regmap_write(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_STATUS, 0);
+
+ wake_up(&bt_bmc->queue);
+ return IRQ_HANDLED;
+}
+
static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
struct platform_device *pdev)
{
@@ -446,6 +472,48 @@ static const struct bt_bmc_ops aspeed_bt_bmc_ops = {
.enable_bt = aspeed_enable_bt,
};
+static int microwatt_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
+ struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ int rc;
+
+ bt_bmc->irq = platform_get_irq_optional(pdev, 0);
+ if (bt_bmc->irq < 0)
+ return bt_bmc->irq;
+
+ rc = devm_request_irq(dev, bt_bmc->irq, microwatt_bt_bmc_irq, IRQF_SHARED,
+ DEVICE_NAME, bt_bmc);
+ if (rc < 0) {
+ dev_warn(dev, "Unable to request IRQ %d\n", bt_bmc->irq);
+ bt_bmc->irq = rc;
+ return rc;
+ }
+
+ /*
+ * Configure the hardware to give us an interrupt whenever the H2B
+ * bit is set or the HBUSY bit is cleared.
+ *
+ * H2B will be asserted when the bmc has data for us; HBUSY
+ * will be cleared (along with B2H) when we can write the next
+ * message to the BT buffer
+ */
+ rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset + MICROWATT_IRQ_MASK,
+ (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY),
+ (IRQ_HOST_TO_BMC_ATTN | IRQ_HOST_NOT_BUSY));
+
+ return rc;
+}
+
+static void microwatt_enable_bt(struct bt_bmc *bt_bmc)
+{
+}
+
+static const struct bt_bmc_ops microwatt_bt_bmc_ops = {
+ .config_irq = microwatt_bt_bmc_config_irq,
+ .enable_bt = microwatt_enable_bt,
+};
+
static int bt_bmc_probe(struct platform_device *pdev)
{
struct bt_bmc *bt_bmc;
@@ -530,6 +598,7 @@ static int bt_bmc_remove(struct platform_device *pdev)
static const struct of_device_id bt_bmc_match[] = {
{ .compatible = "aspeed,ast2400-ibt-bmc", .data = &aspeed_bt_bmc_ops },
{ .compatible = "aspeed,ast2500-ibt-bmc", .data = &aspeed_bt_bmc_ops },
+ { .compatible = "ibm,microwatt-ibt-bmc", .data = µwatt_bt_bmc_ops },
{ },
};
--
2.31.1
^ permalink raw reply related
* [RFC 4/5] ipmi:bt-bmc: No longer ASPEED specific
From: Anton Blanchard @ 2021-10-06 2:12 UTC (permalink / raw)
To: alistair, joel, andrew, clg, mikey, jk; +Cc: linuxppc-dev
In-Reply-To: <20211006021205.2579057-1-anton@ozlabs.org>
The driver is no longer specific to ASPEED, so rename the config option
and remove the dependency on ARCH_ASPEED.
Signed-off-by: Anton Blanchard <anton@ozlabs.org>
---
.../bindings/ipmi/{aspeed,ast2400-ibt-bmc.txt => ibt-bmc.txt} | 2 +-
arch/arm/configs/aspeed_g4_defconfig | 2 +-
arch/arm/configs/aspeed_g5_defconfig | 2 +-
arch/arm/configs/multi_v5_defconfig | 2 +-
arch/arm/configs/multi_v7_defconfig | 2 +-
drivers/char/ipmi/Kconfig | 2 +-
drivers/char/ipmi/Makefile | 2 +-
7 files changed, 7 insertions(+), 7 deletions(-)
rename Documentation/devicetree/bindings/ipmi/{aspeed,ast2400-ibt-bmc.txt => ibt-bmc.txt} (93%)
diff --git a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
similarity index 93%
rename from Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt
rename to Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
index 028268fd99ee..78ee716a950e 100644
--- a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt
+++ b/Documentation/devicetree/bindings/ipmi/ibt-bmc.txt
@@ -1,4 +1,4 @@
-* Aspeed BT (Block Transfer) IPMI interface
+* BT (Block Transfer) IPMI interface
The Aspeed SOCs (AST2400 and AST2500) are commonly used as BMCs
(BaseBoard Management Controllers) and the BT interface can be used to
diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig
index acaafa351d08..51696ba49c80 100644
--- a/arch/arm/configs/aspeed_g4_defconfig
+++ b/arch/arm/configs/aspeed_g4_defconfig
@@ -124,7 +124,7 @@ CONFIG_SERIAL_8250_ASPEED_VUART=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_ASPEED_KCS_IPMI_BMC=y
-CONFIG_ASPEED_BT_IPMI_BMC=y
+CONFIG_BT_IPMI_BMC=y
CONFIG_HW_RANDOM_TIMERIOMEM=y
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
index 480dbbb4ff91..758dac62f34f 100644
--- a/arch/arm/configs/aspeed_g5_defconfig
+++ b/arch/arm/configs/aspeed_g5_defconfig
@@ -141,7 +141,7 @@ CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_ASPEED_KCS_IPMI_BMC=y
CONFIG_IPMI_KCS_BMC_SERIO=y
-CONFIG_ASPEED_BT_IPMI_BMC=y
+CONFIG_BT_IPMI_BMC=y
CONFIG_HW_RANDOM_TIMERIOMEM=y
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C_CHARDEV=y
diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/multi_v5_defconfig
index 80a3ae02d759..f3ed5da74dfa 100644
--- a/arch/arm/configs/multi_v5_defconfig
+++ b/arch/arm/configs/multi_v5_defconfig
@@ -150,7 +150,7 @@ CONFIG_SERIAL_ATMEL_TTYAT=y
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
CONFIG_ASPEED_KCS_IPMI_BMC=m
-CONFIG_ASPEED_BT_IPMI_BMC=m
+CONFIG_BT_IPMI_BMC=m
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_TIMERIOMEM=m
# CONFIG_I2C_COMPAT is not set
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index ba67c4717dcc..03e97d95c251 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -384,7 +384,7 @@ CONFIG_SERIAL_OWL_CONSOLE=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_ASPEED_KCS_IPMI_BMC=m
-CONFIG_ASPEED_BT_IPMI_BMC=m
+CONFIG_BT_IPMI_BMC=m
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_ST=y
CONFIG_TCG_TPM=m
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index 249b31197eea..8b2f0f675e5f 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -151,7 +151,7 @@ config IPMI_KCS_BMC_SERIO
This support is also available as a module. The module will be
called kcs_bmc_serio.
-config ASPEED_BT_IPMI_BMC
+config BT_IPMI_BMC
depends on ARCH_ASPEED || COMPILE_TEST
depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
tristate "BT IPMI bmc driver"
diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile
index 84f47d18007f..75c71cbd568b 100644
--- a/drivers/char/ipmi/Makefile
+++ b/drivers/char/ipmi/Makefile
@@ -25,7 +25,7 @@ obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o
obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o
obj-$(CONFIG_IPMI_KCS_BMC_SERIO) += kcs_bmc_serio.o
obj-$(CONFIG_IPMI_KCS_BMC_CDEV_IPMI) += kcs_bmc_cdev_ipmi.o
-obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o
+obj-$(CONFIG_BT_IPMI_BMC) += bt-bmc.o
obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o
obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o
obj-$(CONFIG_IPMB_DEVICE_INTERFACE) += ipmb_dev_int.o
--
2.31.1
^ permalink raw reply related
* [RFC 3/5] ipmi:bt-bmc: Put arch specific function into bt_bmc_ops
From: Anton Blanchard @ 2021-10-06 2:12 UTC (permalink / raw)
To: alistair, joel, andrew, clg, mikey, jk; +Cc: linuxppc-dev
In-Reply-To: <20211006021205.2579057-1-anton@ozlabs.org>
While most of the driver is arch agnostic, setting up and handling
interrupts, and enabling the hardware is not. Create bt_bmc_ops to
handle these functions.
Signed-off-by: Anton Blanchard <anton@ozlabs.org>
---
drivers/char/ipmi/bt-bmc.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index 2b0fe1255026..b48e04405ac4 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -17,6 +17,7 @@
#include <linux/regmap.h>
#include <linux/sched.h>
#include <linux/timer.h>
+#include <linux/of_device.h>
/*
* This is a BMC device used to communicate to the host
@@ -435,15 +436,30 @@ static void aspeed_enable_bt(struct bt_bmc *bt_bmc)
BT_CR0_ENABLE_IBT);
}
+struct bt_bmc_ops {
+ int (*config_irq)(struct bt_bmc *bt_bmc, struct platform_device *pdev);
+ void (*enable_bt)(struct bt_bmc *bt_bmc);
+};
+
+static const struct bt_bmc_ops aspeed_bt_bmc_ops = {
+ .config_irq = aspeed_bt_bmc_config_irq,
+ .enable_bt = aspeed_enable_bt,
+};
+
static int bt_bmc_probe(struct platform_device *pdev)
{
struct bt_bmc *bt_bmc;
struct device *dev;
int rc;
+ const struct bt_bmc_ops *ops;
dev = &pdev->dev;
dev_info(dev, "Found bt bmc device\n");
+ ops = of_device_get_match_data(&pdev->dev);
+ if (!ops)
+ return -ENODEV;
+
bt_bmc = devm_kzalloc(dev, sizeof(*bt_bmc), GFP_KERNEL);
if (!bt_bmc)
return -ENOMEM;
@@ -483,7 +499,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
return rc;
}
- aspeed_bt_bmc_config_irq(bt_bmc, pdev);
+ ops->config_irq(bt_bmc, pdev);
if (bt_bmc->irq >= 0) {
dev_info(dev, "Using IRQ %d\n", bt_bmc->irq);
@@ -494,7 +510,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
add_timer(&bt_bmc->poll_timer);
}
- aspeed_enable_bt(bt_bmc);
+ ops->enable_bt(bt_bmc);
clr_b_busy(bt_bmc);
@@ -512,8 +528,8 @@ static int bt_bmc_remove(struct platform_device *pdev)
}
static const struct of_device_id bt_bmc_match[] = {
- { .compatible = "aspeed,ast2400-ibt-bmc" },
- { .compatible = "aspeed,ast2500-ibt-bmc" },
+ { .compatible = "aspeed,ast2400-ibt-bmc", .data = &aspeed_bt_bmc_ops },
+ { .compatible = "aspeed,ast2500-ibt-bmc", .data = &aspeed_bt_bmc_ops },
{ },
};
--
2.31.1
^ permalink raw reply related
* [RFC 2/5] ipmi:bt-bmc: Prefix ASPEED specific registers with ASPEED_
From: Anton Blanchard @ 2021-10-06 2:12 UTC (permalink / raw)
To: alistair, joel, andrew, clg, mikey, jk; +Cc: linuxppc-dev
In-Reply-To: <20211006021205.2579057-1-anton@ozlabs.org>
Signed-off-by: Anton Blanchard <anton@ozlabs.org>
---
drivers/char/ipmi/bt-bmc.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index f85fafc96ef6..2b0fe1255026 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -26,19 +26,19 @@
#define BT_IO_BASE 0xe4
#define BT_IRQ 10
-#define BT_CR0 0x0
+#define ASPEED_BT_CR0 0x0
#define BT_CR0_IO_BASE 16
#define BT_CR0_IRQ 12
#define BT_CR0_EN_CLR_SLV_RDP 0x8
#define BT_CR0_EN_CLR_SLV_WRP 0x4
#define BT_CR0_ENABLE_IBT 0x1
-#define BT_CR1 0x4
+#define ASPEED_BT_CR1 0x4
#define BT_CR1_IRQ_H2B 0x01
#define BT_CR1_IRQ_HBUSY 0x40
-#define BT_CR2 0x8
+#define ASPEED_BT_CR2 0x8
#define BT_CR2_IRQ_H2B 0x01
#define BT_CR2_IRQ_HBUSY 0x40
-#define BT_CR3 0xc
+#define ASPEED_BT_CR3 0xc
#define BT_CTRL 0x10
#define BT_CTRL_B_BUSY 0x80
@@ -379,7 +379,7 @@ static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
u32 reg;
int rc;
- rc = regmap_read(bt_bmc->map, bt_bmc->offset + BT_CR2, ®);
+ rc = regmap_read(bt_bmc->map, bt_bmc->offset + ASPEED_BT_CR2, ®);
if (rc)
return IRQ_NONE;
@@ -388,7 +388,7 @@ static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
return IRQ_NONE;
/* ack pending IRQs */
- regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR2, reg);
+ regmap_write(bt_bmc->map, bt_bmc->offset + ASPEED_BT_CR2, reg);
wake_up(&bt_bmc->queue);
return IRQ_HANDLED;
@@ -418,7 +418,7 @@ static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
* will be cleared (along with B2H) when we can write the next
* message to the BT buffer
*/
- rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset + BT_CR1,
+ rc = regmap_update_bits(bt_bmc->map, bt_bmc->offset + ASPEED_BT_CR1,
(BT_CR1_IRQ_H2B | BT_CR1_IRQ_HBUSY),
(BT_CR1_IRQ_H2B | BT_CR1_IRQ_HBUSY));
@@ -427,7 +427,7 @@ static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
static void aspeed_enable_bt(struct bt_bmc *bt_bmc)
{
- regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR0,
+ regmap_write(bt_bmc->map, bt_bmc->offset + ASPEED_BT_CR0,
(BT_IO_BASE << BT_CR0_IO_BASE) |
(BT_IRQ << BT_CR0_IRQ) |
BT_CR0_EN_CLR_SLV_RDP |
--
2.31.1
^ permalink raw reply related
* [RFC 1/5] ipmi:bt-bmc: Separate out ASPEED specific bits
From: Anton Blanchard @ 2021-10-06 2:12 UTC (permalink / raw)
To: alistair, joel, andrew, clg, mikey, jk; +Cc: linuxppc-dev
Most of the IPMI BT BMC driver is architecture agnostic - it deals with
architected registers and behaviour in the IPMI specification.
Separate out the few ASPEED specific bits into their own functions
so we can use this driver on other architectures.
Signed-off-by: Anton Blanchard <anton@ozlabs.org>
---
drivers/char/ipmi/bt-bmc.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index 6e3d247b55d1..f85fafc96ef6 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -39,6 +39,7 @@
#define BT_CR2_IRQ_H2B 0x01
#define BT_CR2_IRQ_HBUSY 0x40
#define BT_CR3 0xc
+
#define BT_CTRL 0x10
#define BT_CTRL_B_BUSY 0x80
#define BT_CTRL_H_BUSY 0x40
@@ -372,7 +373,7 @@ static void poll_timer(struct timer_list *t)
add_timer(&bt_bmc->poll_timer);
}
-static irqreturn_t bt_bmc_irq(int irq, void *arg)
+static irqreturn_t aspeed_bt_bmc_irq(int irq, void *arg)
{
struct bt_bmc *bt_bmc = arg;
u32 reg;
@@ -393,7 +394,7 @@ static irqreturn_t bt_bmc_irq(int irq, void *arg)
return IRQ_HANDLED;
}
-static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
+static int aspeed_bt_bmc_config_irq(struct bt_bmc *bt_bmc,
struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -403,7 +404,7 @@ static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
if (bt_bmc->irq < 0)
return bt_bmc->irq;
- rc = devm_request_irq(dev, bt_bmc->irq, bt_bmc_irq, IRQF_SHARED,
+ rc = devm_request_irq(dev, bt_bmc->irq, aspeed_bt_bmc_irq, IRQF_SHARED,
DEVICE_NAME, bt_bmc);
if (rc < 0) {
dev_warn(dev, "Unable to request IRQ %d\n", bt_bmc->irq);
@@ -424,6 +425,16 @@ static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
return rc;
}
+static void aspeed_enable_bt(struct bt_bmc *bt_bmc)
+{
+ regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR0,
+ (BT_IO_BASE << BT_CR0_IO_BASE) |
+ (BT_IRQ << BT_CR0_IRQ) |
+ BT_CR0_EN_CLR_SLV_RDP |
+ BT_CR0_EN_CLR_SLV_WRP |
+ BT_CR0_ENABLE_IBT);
+}
+
static int bt_bmc_probe(struct platform_device *pdev)
{
struct bt_bmc *bt_bmc;
@@ -472,7 +483,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
return rc;
}
- bt_bmc_config_irq(bt_bmc, pdev);
+ aspeed_bt_bmc_config_irq(bt_bmc, pdev);
if (bt_bmc->irq >= 0) {
dev_info(dev, "Using IRQ %d\n", bt_bmc->irq);
@@ -483,12 +494,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
add_timer(&bt_bmc->poll_timer);
}
- regmap_write(bt_bmc->map, bt_bmc->offset + BT_CR0,
- (BT_IO_BASE << BT_CR0_IO_BASE) |
- (BT_IRQ << BT_CR0_IRQ) |
- BT_CR0_EN_CLR_SLV_RDP |
- BT_CR0_EN_CLR_SLV_WRP |
- BT_CR0_ENABLE_IBT);
+ aspeed_enable_bt(bt_bmc);
clr_b_busy(bt_bmc);
--
2.31.1
^ permalink raw reply related
* [PATCH v2 09/10] powerpc/bpf ppc32: Do not emit zero extend instruction for 64-bit BPF_END
From: Naveen N. Rao @ 2021-10-05 20:25 UTC (permalink / raw)
To: Michael Ellerman, Nicholas Piggin, Jordan Niethe, Daniel Borkmann,
Alexei Starovoitov, Christophe Leroy, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Suppress emitting zero extend instruction for 64-bit BPF_END_FROM_[L|B]E
operation.
Fixes: 51c66ad849a703 ("powerpc/bpf: Implement extended BPF on PPC32")
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
arch/powerpc/net/bpf_jit_comp32.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 7c65de9ed4fa64..68dc8a8231de04 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -1107,7 +1107,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
return -EOPNOTSUPP;
}
if (BPF_CLASS(code) == BPF_ALU && !fp->aux->verifier_zext &&
- !insn_is_zext(&insn[i + 1]))
+ !insn_is_zext(&insn[i + 1]) && !(BPF_OP(code) == BPF_END && imm == 64))
EMIT(PPC_RAW_LI(dst_reg_h, 0));
}
--
2.33.0
^ permalink raw reply related
* [PATCH v2 10/10] powerpc/bpf ppc32: Fix BPF_SUB when imm == 0x80000000
From: Naveen N. Rao @ 2021-10-05 20:25 UTC (permalink / raw)
To: Michael Ellerman, Nicholas Piggin, Jordan Niethe, Daniel Borkmann,
Alexei Starovoitov, Christophe Leroy, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Special case handling of the smallest 32-bit negative number for BPF_SUB.
Fixes: 51c66ad849a703 ("powerpc/bpf: Implement extended BPF on PPC32")
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
arch/powerpc/net/bpf_jit_comp32.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 68dc8a8231de04..0da31d41d41310 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -357,7 +357,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
PPC_LI32(_R0, imm);
EMIT(PPC_RAW_ADDC(dst_reg, dst_reg, _R0));
}
- if (imm >= 0)
+ if (imm >= 0 || (BPF_OP(code) == BPF_SUB && imm == 0x80000000))
EMIT(PPC_RAW_ADDZE(dst_reg_h, dst_reg_h));
else
EMIT(PPC_RAW_ADDME(dst_reg_h, dst_reg_h));
--
2.33.0
^ permalink raw reply related
* [PATCH v2 08/10] powerpc/bpf ppc32: Fix JMP32_JSET_K
From: Naveen N. Rao @ 2021-10-05 20:25 UTC (permalink / raw)
To: Michael Ellerman, Nicholas Piggin, Jordan Niethe, Daniel Borkmann,
Alexei Starovoitov, Christophe Leroy, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
'andi' only takes an unsigned 16-bit value. Correct the imm range used
when emitting andi.
Fixes: 51c66ad849a703 ("powerpc/bpf: Implement extended BPF on PPC32")
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
arch/powerpc/net/bpf_jit_comp32.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 519ecb9ab67266..7c65de9ed4fa64 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -1075,7 +1075,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
break;
case BPF_JMP32 | BPF_JSET | BPF_K:
/* andi does not sign-extend the immediate */
- if (imm >= -32768 && imm < 32768) {
+ if (imm >= 0 && imm < 32768) {
/* PPC_ANDI is _only/always_ dot-form */
EMIT(PPC_RAW_ANDI(_R0, dst_reg, imm));
} else {
--
2.33.0
^ permalink raw reply related
* [PATCH v2 07/10] powerpc/bpf ppc32: Fix ALU32 BPF_ARSH operation
From: Naveen N. Rao @ 2021-10-05 20:25 UTC (permalink / raw)
To: Michael Ellerman, Nicholas Piggin, Jordan Niethe, Daniel Borkmann,
Alexei Starovoitov, Christophe Leroy, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Correct the destination register used for ALU32 BPF_ARSH operation.
Fixes: 51c66ad849a703 ("powerpc/bpf: Implement extended BPF on PPC32")
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
arch/powerpc/net/bpf_jit_comp32.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index a74d52204f8da2..519ecb9ab67266 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -625,7 +625,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
EMIT(PPC_RAW_LI(dst_reg_h, 0));
break;
case BPF_ALU | BPF_ARSH | BPF_X: /* (s32) dst >>= src */
- EMIT(PPC_RAW_SRAW(dst_reg_h, dst_reg, src_reg));
+ EMIT(PPC_RAW_SRAW(dst_reg, dst_reg, src_reg));
break;
case BPF_ALU64 | BPF_ARSH | BPF_X: /* (s64) dst >>= src */
bpf_set_seen_register(ctx, tmp_reg);
--
2.33.0
^ permalink raw reply related
* [PATCH v2 06/10] powerpc/bpf: Emit stf barrier instruction sequences for BPF_NOSPEC
From: Naveen N. Rao @ 2021-10-05 20:25 UTC (permalink / raw)
To: Michael Ellerman, Nicholas Piggin, Jordan Niethe, Daniel Borkmann,
Alexei Starovoitov, Christophe Leroy, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Emit similar instruction sequences to commit a048a07d7f4535
("powerpc/64s: Add support for a store forwarding barrier at kernel
entry/exit") when encountering BPF_NOSPEC.
Mitigations are enabled depending on what the firmware advertises. In
particular, we do not gate these mitigations based on current settings,
just like in x86. Due to this, we don't need to take any action if
mitigations are enabled or disabled at runtime.
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
arch/powerpc/net/bpf_jit64.h | 8 ++---
arch/powerpc/net/bpf_jit_comp64.c | 55 ++++++++++++++++++++++++++++---
2 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/net/bpf_jit64.h b/arch/powerpc/net/bpf_jit64.h
index 7b713edfa7e261..b63b35e45e558c 100644
--- a/arch/powerpc/net/bpf_jit64.h
+++ b/arch/powerpc/net/bpf_jit64.h
@@ -16,18 +16,18 @@
* with our redzone usage.
*
* [ prev sp ] <-------------
- * [ nv gpr save area ] 6*8 |
+ * [ nv gpr save area ] 5*8 |
* [ tail_call_cnt ] 8 |
- * [ local_tmp_var ] 8 |
+ * [ local_tmp_var ] 16 |
* fp (r31) --> [ ebpf stack space ] upto 512 |
* [ frame header ] 32/112 |
* sp (r1) ---> [ stack pointer ] --------------
*/
/* for gpr non volatile registers BPG_REG_6 to 10 */
-#define BPF_PPC_STACK_SAVE (6*8)
+#define BPF_PPC_STACK_SAVE (5*8)
/* for bpf JIT code internal usage */
-#define BPF_PPC_STACK_LOCALS 16
+#define BPF_PPC_STACK_LOCALS 24
/* stack frame excluding BPF stack, ensure this is quadword aligned */
#define BPF_PPC_STACKFRAME (STACK_FRAME_MIN_SIZE + \
BPF_PPC_STACK_LOCALS + BPF_PPC_STACK_SAVE)
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index 6626e6c17d4ed2..51c7f6cd9a0a10 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -15,6 +15,7 @@
#include <linux/if_vlan.h>
#include <asm/kprobes.h>
#include <linux/bpf.h>
+#include <asm/security_features.h>
#include "bpf_jit64.h"
@@ -35,9 +36,9 @@ static inline bool bpf_has_stack_frame(struct codegen_context *ctx)
* [ prev sp ] <-------------
* [ ... ] |
* sp (r1) ---> [ stack pointer ] --------------
- * [ nv gpr save area ] 6*8
+ * [ nv gpr save area ] 5*8
* [ tail_call_cnt ] 8
- * [ local_tmp_var ] 8
+ * [ local_tmp_var ] 16
* [ unused red zone ] 208 bytes protected
*/
static int bpf_jit_stack_local(struct codegen_context *ctx)
@@ -45,12 +46,12 @@ static int bpf_jit_stack_local(struct codegen_context *ctx)
if (bpf_has_stack_frame(ctx))
return STACK_FRAME_MIN_SIZE + ctx->stack_size;
else
- return -(BPF_PPC_STACK_SAVE + 16);
+ return -(BPF_PPC_STACK_SAVE + 24);
}
static int bpf_jit_stack_tailcallcnt(struct codegen_context *ctx)
{
- return bpf_jit_stack_local(ctx) + 8;
+ return bpf_jit_stack_local(ctx) + 16;
}
static int bpf_jit_stack_offsetof(struct codegen_context *ctx, int reg)
@@ -272,10 +273,33 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
return 0;
}
+/*
+ * We spill into the redzone always, even if the bpf program has its own stackframe.
+ * Offsets hardcoded based on BPF_PPC_STACK_SAVE -- see bpf_jit_stack_local()
+ */
+void bpf_stf_barrier(void);
+
+asm (
+" .global bpf_stf_barrier ;"
+" bpf_stf_barrier: ;"
+" std 21,-64(1) ;"
+" std 22,-56(1) ;"
+" sync ;"
+" ld 21,-64(1) ;"
+" ld 22,-56(1) ;"
+" ori 31,31,0 ;"
+" .rept 14 ;"
+" b 1f ;"
+" 1: ;"
+" .endr ;"
+" blr ;"
+);
+
/* 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)
{
+ enum stf_barrier_type stf_barrier = stf_barrier_type_get();
const struct bpf_insn *insn = fp->insnsi;
int flen = fp->len;
int i, ret;
@@ -646,6 +670,29 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
* BPF_ST NOSPEC (speculation barrier)
*/
case BPF_ST | BPF_NOSPEC:
+ if (!security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) ||
+ !security_ftr_enabled(SEC_FTR_STF_BARRIER))
+ break;
+
+ switch (stf_barrier) {
+ case STF_BARRIER_EIEIO:
+ EMIT(PPC_RAW_EIEIO() | 0x02000000);
+ break;
+ case STF_BARRIER_SYNC_ORI:
+ EMIT(PPC_RAW_SYNC());
+ EMIT(PPC_RAW_LD(b2p[TMP_REG_1], _R13, 0));
+ EMIT(PPC_RAW_ORI(_R31, _R31, 0));
+ break;
+ case STF_BARRIER_FALLBACK:
+ EMIT(PPC_RAW_MFLR(b2p[TMP_REG_1]));
+ PPC_LI64(12, dereference_kernel_function_descriptor(bpf_stf_barrier));
+ EMIT(PPC_RAW_MTCTR(12));
+ EMIT(PPC_RAW_BCTRL());
+ EMIT(PPC_RAW_MTLR(b2p[TMP_REG_1]));
+ break;
+ case STF_BARRIER_NONE:
+ break;
+ }
break;
/*
--
2.33.0
^ permalink raw reply related
* [PATCH v2 05/10] powerpc/security: Add a helper to query stf_barrier type
From: Naveen N. Rao @ 2021-10-05 20:25 UTC (permalink / raw)
To: Michael Ellerman, Nicholas Piggin, Jordan Niethe, Daniel Borkmann,
Alexei Starovoitov, Christophe Leroy, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Add a helper to return the stf_barrier type for the current processor.
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/security_features.h | 5 +++++
arch/powerpc/kernel/security.c | 5 +++++
2 files changed, 10 insertions(+)
diff --git a/arch/powerpc/include/asm/security_features.h b/arch/powerpc/include/asm/security_features.h
index 792eefaf230b80..27574f218b371f 100644
--- a/arch/powerpc/include/asm/security_features.h
+++ b/arch/powerpc/include/asm/security_features.h
@@ -39,6 +39,11 @@ static inline bool security_ftr_enabled(u64 feature)
return !!(powerpc_security_features & feature);
}
+#ifdef CONFIG_PPC_BOOK3S_64
+enum stf_barrier_type stf_barrier_type_get(void);
+#else
+static inline enum stf_barrier_type stf_barrier_type_get(void) { return STF_BARRIER_NONE; }
+#endif
// Features indicating support for Spectre/Meltdown mitigations
diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c
index 1a998490fe60f0..15fb5ea1b9eafa 100644
--- a/arch/powerpc/kernel/security.c
+++ b/arch/powerpc/kernel/security.c
@@ -263,6 +263,11 @@ static int __init handle_no_stf_barrier(char *p)
early_param("no_stf_barrier", handle_no_stf_barrier);
+enum stf_barrier_type stf_barrier_type_get(void)
+{
+ return stf_enabled_flush_types;
+}
+
/* This is the generic flag used by other architectures */
static int __init handle_ssbd(char *p)
{
--
2.33.0
^ permalink raw reply related
* [PATCH v2 04/10] powerpc/bpf: Fix BPF_SUB when imm == 0x80000000
From: Naveen N. Rao @ 2021-10-05 20:25 UTC (permalink / raw)
To: Michael Ellerman, Nicholas Piggin, Jordan Niethe, Daniel Borkmann,
Alexei Starovoitov, Christophe Leroy, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
We aren't handling subtraction involving an immediate value of
0x80000000 properly. Fix the same.
Fixes: 156d0e290e969c ("powerpc/ebpf/jit: Implement JIT compiler for extended BPF")
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
Changelog:
- Split up BPF_ADD and BPF_SUB cases per Christophe's comments
arch/powerpc/net/bpf_jit_comp64.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index d67f6d62e2e1ff..6626e6c17d4ed2 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -330,18 +330,25 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
EMIT(PPC_RAW_SUB(dst_reg, dst_reg, src_reg));
goto bpf_alu32_trunc;
case BPF_ALU | BPF_ADD | BPF_K: /* (u32) dst += (u32) imm */
- case BPF_ALU | BPF_SUB | BPF_K: /* (u32) dst -= (u32) imm */
case BPF_ALU64 | BPF_ADD | BPF_K: /* dst += imm */
+ if (!imm) {
+ goto bpf_alu32_trunc;
+ } else if (imm >= -32768 && imm < 32768) {
+ EMIT(PPC_RAW_ADDI(dst_reg, dst_reg, IMM_L(imm)));
+ } else {
+ PPC_LI32(b2p[TMP_REG_1], imm);
+ EMIT(PPC_RAW_ADD(dst_reg, dst_reg, b2p[TMP_REG_1]));
+ }
+ goto bpf_alu32_trunc;
+ case BPF_ALU | BPF_SUB | BPF_K: /* (u32) dst -= (u32) imm */
case BPF_ALU64 | BPF_SUB | BPF_K: /* dst -= imm */
- if (BPF_OP(code) == BPF_SUB)
- imm = -imm;
- if (imm) {
- if (imm >= -32768 && imm < 32768)
- EMIT(PPC_RAW_ADDI(dst_reg, dst_reg, IMM_L(imm)));
- else {
- PPC_LI32(b2p[TMP_REG_1], imm);
- EMIT(PPC_RAW_ADD(dst_reg, dst_reg, b2p[TMP_REG_1]));
- }
+ if (!imm) {
+ goto bpf_alu32_trunc;
+ } else if (imm > -32768 && imm < 32768) {
+ EMIT(PPC_RAW_ADDI(dst_reg, dst_reg, IMM_L(-imm)));
+ } else {
+ PPC_LI32(b2p[TMP_REG_1], imm);
+ EMIT(PPC_RAW_SUB(dst_reg, dst_reg, b2p[TMP_REG_1]));
}
goto bpf_alu32_trunc;
case BPF_ALU | BPF_MUL | BPF_X: /* (u32) dst *= (u32) src */
--
2.33.0
^ permalink raw reply related
* [PATCH v2 03/10] powerpc/bpf: Fix BPF_MOD when imm == 1
From: Naveen N. Rao @ 2021-10-05 20:25 UTC (permalink / raw)
To: Michael Ellerman, Nicholas Piggin, Jordan Niethe, Daniel Borkmann,
Alexei Starovoitov, Christophe Leroy, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Only ignore the operation if dividing by 1.
Acked-by: Song Liu <songliubraving@fb.com>
Acked-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
Tested-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
Fixes: 156d0e290e969c ("powerpc/ebpf/jit: Implement JIT compiler for extended BPF")
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
arch/powerpc/net/bpf_jit_comp64.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index f06c62089b1457..d67f6d62e2e1ff 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -391,8 +391,14 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
case BPF_ALU64 | BPF_DIV | BPF_K: /* dst /= imm */
if (imm == 0)
return -EINVAL;
- else if (imm == 1)
- goto bpf_alu32_trunc;
+ if (imm == 1) {
+ if (BPF_OP(code) == BPF_DIV) {
+ goto bpf_alu32_trunc;
+ } else {
+ EMIT(PPC_RAW_LI(dst_reg, 0));
+ break;
+ }
+ }
PPC_LI32(b2p[TMP_REG_1], imm);
switch (BPF_CLASS(code)) {
--
2.33.0
^ permalink raw reply related
* [PATCH v2 02/10] powerpc/bpf: Validate branch ranges
From: Naveen N. Rao @ 2021-10-05 20:25 UTC (permalink / raw)
To: Michael Ellerman, Nicholas Piggin, Jordan Niethe, Daniel Borkmann,
Alexei Starovoitov, Christophe Leroy, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Add checks to ensure that we never emit branch instructions with
truncated branch offsets.
Acked-by: Song Liu <songliubraving@fb.com>
Acked-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
Tested-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
Suggested-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
arch/powerpc/net/bpf_jit.h | 26 ++++++++++++++++++++------
arch/powerpc/net/bpf_jit_comp.c | 6 +++++-
arch/powerpc/net/bpf_jit_comp32.c | 8 ++++++--
arch/powerpc/net/bpf_jit_comp64.c | 8 ++++++--
4 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 935ea95b66359e..7e9b978b768ed9 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -24,16 +24,30 @@
#define EMIT(instr) PLANT_INSTR(image, ctx->idx, instr)
/* Long jump; (unconditional 'branch') */
-#define PPC_JMP(dest) EMIT(PPC_INST_BRANCH | \
- (((dest) - (ctx->idx * 4)) & 0x03fffffc))
+#define PPC_JMP(dest) \
+ do { \
+ long offset = (long)(dest) - (ctx->idx * 4); \
+ if (!is_offset_in_branch_range(offset)) { \
+ pr_err_ratelimited("Branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx); \
+ return -ERANGE; \
+ } \
+ EMIT(PPC_INST_BRANCH | (offset & 0x03fffffc)); \
+ } while (0)
+
/* blr; (unconditional 'branch' with link) to absolute address */
#define PPC_BL_ABS(dest) EMIT(PPC_INST_BL | \
(((dest) - (unsigned long)(image + ctx->idx)) & 0x03fffffc))
/* "cond" here covers BO:BI fields. */
-#define PPC_BCC_SHORT(cond, dest) EMIT(PPC_INST_BRANCH_COND | \
- (((cond) & 0x3ff) << 16) | \
- (((dest) - (ctx->idx * 4)) & \
- 0xfffc))
+#define PPC_BCC_SHORT(cond, dest) \
+ do { \
+ long offset = (long)(dest) - (ctx->idx * 4); \
+ if (!is_offset_in_cond_branch_range(offset)) { \
+ pr_err_ratelimited("Conditional branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx); \
+ return -ERANGE; \
+ } \
+ EMIT(PPC_INST_BRANCH_COND | (((cond) & 0x3ff) << 16) | (offset & 0xfffc)); \
+ } while (0)
+
/* Sign-extended 32-bit immediate load */
#define PPC_LI32(d, i) do { \
if ((int)(uintptr_t)(i) >= -32768 && \
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 53aefee3fe70be..fcbf7a917c566e 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -210,7 +210,11 @@ 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);
- bpf_jit_build_body(fp, code_base, &cgctx, addrs, extra_pass);
+ if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, extra_pass)) {
+ bpf_jit_binary_free(bpf_hdr);
+ fp = org_fp;
+ goto out_addrs;
+ }
bpf_jit_build_epilogue(code_base, &cgctx);
if (bpf_jit_enable > 1)
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index beb12cbc8c2994..a74d52204f8da2 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -200,7 +200,7 @@ void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 fun
}
}
-static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
+static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
{
/*
* By now, the eBPF program has already setup parameters in r3-r6
@@ -261,7 +261,9 @@ static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32
bpf_jit_emit_common_epilogue(image, ctx);
EMIT(PPC_RAW_BCTR());
+
/* out: */
+ return 0;
}
/* Assemble the body code between the prologue & epilogue */
@@ -1090,7 +1092,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
*/
case BPF_JMP | BPF_TAIL_CALL:
ctx->seen |= SEEN_TAILCALL;
- bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
+ ret = bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
+ if (ret < 0)
+ return ret;
break;
default:
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index b87a63dba9c8fb..f06c62089b1457 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -206,7 +206,7 @@ void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 fun
EMIT(PPC_RAW_BCTRL());
}
-static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
+static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
{
/*
* By now, the eBPF program has already setup parameters in r3, r4 and r5
@@ -267,7 +267,9 @@ static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32
bpf_jit_emit_common_epilogue(image, ctx);
EMIT(PPC_RAW_BCTR());
+
/* out: */
+ return 0;
}
/* Assemble the body code between the prologue & epilogue */
@@ -993,7 +995,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
*/
case BPF_JMP | BPF_TAIL_CALL:
ctx->seen |= SEEN_TAILCALL;
- bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
+ ret = bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
+ if (ret < 0)
+ return ret;
break;
default:
--
2.33.0
^ permalink raw reply related
* [PATCH v2 01/10] powerpc/lib: Add helper to check if offset is within conditional branch range
From: Naveen N. Rao @ 2021-10-05 20:25 UTC (permalink / raw)
To: Michael Ellerman, Nicholas Piggin, Jordan Niethe, Daniel Borkmann,
Alexei Starovoitov, Christophe Leroy, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
In-Reply-To: <cover.1633464148.git.naveen.n.rao@linux.vnet.ibm.com>
Add a helper to check if a given offset is within the branch range for a
powerpc conditional branch instruction, and update some sites to use the
new helper.
Acked-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
Changelog:
- Change 0x7FFF to 0x7fff, per Christophe
arch/powerpc/include/asm/code-patching.h | 1 +
arch/powerpc/lib/code-patching.c | 7 ++++++-
arch/powerpc/net/bpf_jit.h | 7 +------
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index a95f63788c6b14..4ba834599c4d4c 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -23,6 +23,7 @@
#define BRANCH_ABSOLUTE 0x2
bool is_offset_in_branch_range(long offset);
+bool is_offset_in_cond_branch_range(long offset);
int create_branch(struct ppc_inst *instr, const u32 *addr,
unsigned long target, int flags);
int create_cond_branch(struct ppc_inst *instr, const u32 *addr,
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index f9a3019e37b43c..c5ed9882383521 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -228,6 +228,11 @@ bool is_offset_in_branch_range(long offset)
return (offset >= -0x2000000 && offset <= 0x1fffffc && !(offset & 0x3));
}
+bool is_offset_in_cond_branch_range(long offset)
+{
+ return offset >= -0x8000 && offset <= 0x7fff && !(offset & 0x3);
+}
+
/*
* Helper to check if a given instruction is a conditional branch
* Derived from the conditional checks in analyse_instr()
@@ -280,7 +285,7 @@ int create_cond_branch(struct ppc_inst *instr, const u32 *addr,
offset = offset - (unsigned long)addr;
/* Check we can represent the target in the instruction format */
- if (offset < -0x8000 || offset > 0x7FFF || offset & 0x3)
+ if (!is_offset_in_cond_branch_range(offset))
return 1;
/* Mask out the flags and target, so they don't step on each other. */
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 99fad093f43ec1..935ea95b66359e 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -78,11 +78,6 @@
#define PPC_FUNC_ADDR(d,i) do { PPC_LI32(d, i); } while(0)
#endif
-static inline bool is_nearbranch(int offset)
-{
- return (offset < 32768) && (offset >= -32768);
-}
-
/*
* The fly in the ointment of code size changing from pass to pass is
* avoided by padding the short branch case with a NOP. If code size differs
@@ -91,7 +86,7 @@ static inline bool is_nearbranch(int offset)
* state.
*/
#define PPC_BCC(cond, dest) do { \
- if (is_nearbranch((dest) - (ctx->idx * 4))) { \
+ if (is_offset_in_cond_branch_range((long)(dest) - (ctx->idx * 4))) { \
PPC_BCC_SHORT(cond, dest); \
EMIT(PPC_RAW_NOP()); \
} else { \
--
2.33.0
^ permalink raw reply related
* [PATCH v2 00/10] powerpc/bpf: Various fixes
From: Naveen N. Rao @ 2021-10-05 20:25 UTC (permalink / raw)
To: Michael Ellerman, Nicholas Piggin, Jordan Niethe, Daniel Borkmann,
Alexei Starovoitov, Christophe Leroy, Johan Almbladh, Song Liu
Cc: bpf, linuxppc-dev
This is v2 of the series posted at:
http://lkml.kernel.org/r/cover.1633104510.git.naveen.n.rao@linux.vnet.ibm.com
Only patches from v1 that need to go into powerpc/fixes are included.
Other patches will be posted as a separate series for inclusion into
powerpc/next.
Patches 7 to 10 are new and fix issues in ppc32.
- Naveen
Naveen N. Rao (10):
powerpc/lib: Add helper to check if offset is within conditional
branch range
powerpc/bpf: Validate branch ranges
powerpc/bpf: Fix BPF_MOD when imm == 1
powerpc/bpf: Fix BPF_SUB when imm == 0x80000000
powerpc/security: Add a helper to query stf_barrier type
powerpc/bpf: Emit stf barrier instruction sequences for BPF_NOSPEC
powerpc/bpf ppc32: Fix ALU32 BPF_ARSH operation
powerpc/bpf ppc32: Fix JMP32_JSET_K
powerpc/bpf ppc32: Do not emit zero extend instruction for 64-bit
BPF_END
powerpc/bpf ppc32: Fix BPF_SUB when imm == 0x80000000
arch/powerpc/include/asm/code-patching.h | 1 +
arch/powerpc/include/asm/security_features.h | 5 +
arch/powerpc/kernel/security.c | 5 +
arch/powerpc/lib/code-patching.c | 7 +-
arch/powerpc/net/bpf_jit.h | 33 +++---
arch/powerpc/net/bpf_jit64.h | 8 +-
arch/powerpc/net/bpf_jit_comp.c | 6 +-
arch/powerpc/net/bpf_jit_comp32.c | 16 +--
arch/powerpc/net/bpf_jit_comp64.c | 100 +++++++++++++++----
9 files changed, 139 insertions(+), 42 deletions(-)
base-commit: cdcb1396e357bd198f81dc7fa4f5d819063abe44
--
2.33.0
^ permalink raw reply
* Re: [PATCH 3/9] powerpc/bpf: Remove unused SEEN_STACK
From: Naveen N. Rao @ 2021-10-05 20:22 UTC (permalink / raw)
To: Alexei Starovoitov, Christophe Leroy, Daniel Borkmann,
Johan Almbladh, Michael Ellerman, Nicholas Piggin
Cc: bpf, linuxppc-dev
In-Reply-To: <a9904ed3-c9fc-d86f-a720-de0a7e7a8938@csgroup.eu>
Christophe Leroy wrote:
>
>
> Le 04/10/2021 à 20:11, Naveen N. Rao a écrit :
>> Christophe Leroy wrote:
>>>
>>>
>>> Le 01/10/2021 à 23:14, Naveen N. Rao a écrit :
>>>> From: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
>>>>
>>>> SEEN_STACK is unused on PowerPC. Remove it. Also, have
>>>> SEEN_TAILCALL use 0x40000000.
>>>
>>> Why change SEEN_TAILCALL ? Would it be a problem to leave it as is ?
>>>
>>>>
>>>> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
>>>> Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
>>
>> I prefer the bit usage to be contiguous. Changing SEEN_TAILCALL isn't a
>> problem either.
>>
>
> Well you are adding SEEN_BIG_PROG in following patch so it would still
> be contiguous at the end.
>
> I don't really mind but I thought it would be less churn to just leave
> SEEN_TAILCALL as is and re-use 0x40000000 for SEEN_BIG_PROG.
Ah ok. This patch was from a different series and it made more sense to
change the bit number there. I have reused the patch here as-is since
the change is fairly trivial.
- Naveen
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox