MIPS: BPF: Free up some callee-saved registers

Move the two scratch registers from s0 and s1 to t4 and t5 in order
to free up some callee-saved registers. We will use these callee-saved
registers to store some permanent data on them in a subsequent patch.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Cc: netdev@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Daniel Borkmann <dborkman@redhat.com>
Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
Patchwork: http://patchwork.linux-mips.org/patch/10525/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
Markos Chandras 2015-06-04 11:56:11 +01:00 committed by Ralf Baechle
parent de5792a4ec
commit ad152bd698
2 changed files with 17 additions and 20 deletions

View file

@ -29,9 +29,6 @@
/* ABI /* ABI
* *
* s0 1st scratch register
* s1 2nd scratch register
* s2 offset register
* s3 BPF register A * s3 BPF register A
* s4 BPF register X * s4 BPF register X
* s5 *skb * s5 *skb
@ -88,13 +85,13 @@
* any of the $s0-$s6 registers will only be preserved if * any of the $s0-$s6 registers will only be preserved if
* they are going to actually be used. * they are going to actually be used.
*/ */
#define r_s0 MIPS_R_S0 /* scratch reg 1 */
#define r_s1 MIPS_R_S1 /* scratch reg 2 */
#define r_off MIPS_R_S2 #define r_off MIPS_R_S2
#define r_A MIPS_R_S3 #define r_A MIPS_R_S3
#define r_X MIPS_R_S4 #define r_X MIPS_R_S4
#define r_skb MIPS_R_S5 #define r_skb MIPS_R_S5
#define r_M MIPS_R_S6 #define r_M MIPS_R_S6
#define r_s0 MIPS_R_T4 /* scratch reg 1 */
#define r_s1 MIPS_R_T5 /* scratch reg 2 */
#define r_tmp_imm MIPS_R_T6 /* No need to preserve this */ #define r_tmp_imm MIPS_R_T6 /* No need to preserve this */
#define r_tmp MIPS_R_T7 /* No need to preserve this */ #define r_tmp MIPS_R_T7 /* No need to preserve this */
#define r_zero MIPS_R_ZERO #define r_zero MIPS_R_ZERO
@ -108,8 +105,6 @@
#define SEEN_SREG_SFT (BPF_MEMWORDS + 1) #define SEEN_SREG_SFT (BPF_MEMWORDS + 1)
#define SEEN_SREG_BASE (1 << SEEN_SREG_SFT) #define SEEN_SREG_BASE (1 << SEEN_SREG_SFT)
#define SEEN_SREG(x) (SEEN_SREG_BASE << (x)) #define SEEN_SREG(x) (SEEN_SREG_BASE << (x))
#define SEEN_S0 SEEN_SREG(0)
#define SEEN_S1 SEEN_SREG(1)
#define SEEN_OFF SEEN_SREG(2) #define SEEN_OFF SEEN_SREG(2)
#define SEEN_A SEEN_SREG(3) #define SEEN_A SEEN_SREG(3)
#define SEEN_X SEEN_SREG(4) #define SEEN_X SEEN_SREG(4)
@ -813,7 +808,7 @@ static int build_body(struct jit_ctx *ctx)
b_imm(prog->len, ctx), ctx); b_imm(prog->len, ctx), ctx);
emit_reg_move(r_ret, r_zero, ctx); emit_reg_move(r_ret, r_zero, ctx);
ctx->flags |= SEEN_CALL | SEEN_OFF | SEEN_S0 | ctx->flags |= SEEN_CALL | SEEN_OFF |
SEEN_SKB | SEEN_A; SEEN_SKB | SEEN_A;
emit_load_func(r_s0, (ptr)load_func[load_order], emit_load_func(r_s0, (ptr)load_func[load_order],
@ -879,7 +874,7 @@ static int build_body(struct jit_ctx *ctx)
return -ENOTSUPP; return -ENOTSUPP;
/* X <- 4 * (P[k:1] & 0xf) */ /* X <- 4 * (P[k:1] & 0xf) */
ctx->flags |= SEEN_X | SEEN_CALL | SEEN_S0 | SEEN_SKB; ctx->flags |= SEEN_X | SEEN_CALL | SEEN_SKB;
/* Load offset to a1 */ /* Load offset to a1 */
emit_load_func(r_s0, (ptr)jit_get_skb_b, ctx); emit_load_func(r_s0, (ptr)jit_get_skb_b, ctx);
/* /*
@ -943,7 +938,7 @@ static int build_body(struct jit_ctx *ctx)
case BPF_ALU | BPF_MUL | BPF_K: case BPF_ALU | BPF_MUL | BPF_K:
/* A *= K */ /* A *= K */
/* Load K to scratch register before MUL */ /* Load K to scratch register before MUL */
ctx->flags |= SEEN_A | SEEN_S0; ctx->flags |= SEEN_A;
emit_load_imm(r_s0, k, ctx); emit_load_imm(r_s0, k, ctx);
emit_mul(r_A, r_A, r_s0, ctx); emit_mul(r_A, r_A, r_s0, ctx);
break; break;
@ -961,7 +956,7 @@ static int build_body(struct jit_ctx *ctx)
emit_srl(r_A, r_A, k, ctx); emit_srl(r_A, r_A, k, ctx);
break; break;
} }
ctx->flags |= SEEN_A | SEEN_S0; ctx->flags |= SEEN_A;
emit_load_imm(r_s0, k, ctx); emit_load_imm(r_s0, k, ctx);
emit_div(r_A, r_s0, ctx); emit_div(r_A, r_s0, ctx);
break; break;
@ -971,7 +966,7 @@ static int build_body(struct jit_ctx *ctx)
ctx->flags |= SEEN_A; ctx->flags |= SEEN_A;
emit_jit_reg_move(r_A, r_zero, ctx); emit_jit_reg_move(r_A, r_zero, ctx);
} else { } else {
ctx->flags |= SEEN_A | SEEN_S0; ctx->flags |= SEEN_A;
emit_load_imm(r_s0, k, ctx); emit_load_imm(r_s0, k, ctx);
emit_mod(r_A, r_s0, ctx); emit_mod(r_A, r_s0, ctx);
} }
@ -1085,10 +1080,10 @@ static int build_body(struct jit_ctx *ctx)
if ((condt & MIPS_COND_GE) || if ((condt & MIPS_COND_GE) ||
(condt & MIPS_COND_GT)) { (condt & MIPS_COND_GT)) {
if (condt & MIPS_COND_K) { /* K */ if (condt & MIPS_COND_K) { /* K */
ctx->flags |= SEEN_S0 | SEEN_A; ctx->flags |= SEEN_A;
emit_sltiu(r_s0, r_A, k, ctx); emit_sltiu(r_s0, r_A, k, ctx);
} else { /* X */ } else { /* X */
ctx->flags |= SEEN_S0 | SEEN_A | ctx->flags |= SEEN_A |
SEEN_X; SEEN_X;
emit_sltu(r_s0, r_A, r_X, ctx); emit_sltu(r_s0, r_A, r_X, ctx);
} }
@ -1100,7 +1095,7 @@ static int build_body(struct jit_ctx *ctx)
/* A > (K|X) ? scratch = 0 */ /* A > (K|X) ? scratch = 0 */
if (condt & MIPS_COND_GT) { if (condt & MIPS_COND_GT) {
/* Checking for equality */ /* Checking for equality */
ctx->flags |= SEEN_S0 | SEEN_A | SEEN_X; ctx->flags |= SEEN_A | SEEN_X;
if (condt & MIPS_COND_K) if (condt & MIPS_COND_K)
emit_load_imm(r_s0, k, ctx); emit_load_imm(r_s0, k, ctx);
else else
@ -1123,7 +1118,7 @@ static int build_body(struct jit_ctx *ctx)
} else { } else {
/* A == K|X */ /* A == K|X */
if (condt & MIPS_COND_K) { /* K */ if (condt & MIPS_COND_K) { /* K */
ctx->flags |= SEEN_S0 | SEEN_A; ctx->flags |= SEEN_A;
emit_load_imm(r_s0, k, ctx); emit_load_imm(r_s0, k, ctx);
/* jump true */ /* jump true */
b_off = b_imm(i + inst->jt + 1, ctx); b_off = b_imm(i + inst->jt + 1, ctx);
@ -1153,7 +1148,7 @@ static int build_body(struct jit_ctx *ctx)
} }
break; break;
case BPF_JMP | BPF_JSET | BPF_K: case BPF_JMP | BPF_JSET | BPF_K:
ctx->flags |= SEEN_S0 | SEEN_S1 | SEEN_A; ctx->flags |= SEEN_A;
/* pc += (A & K) ? pc -> jt : pc -> jf */ /* pc += (A & K) ? pc -> jt : pc -> jf */
emit_load_imm(r_s1, k, ctx); emit_load_imm(r_s1, k, ctx);
emit_and(r_s0, r_A, r_s1, ctx); emit_and(r_s0, r_A, r_s1, ctx);
@ -1167,7 +1162,7 @@ static int build_body(struct jit_ctx *ctx)
emit_nop(ctx); emit_nop(ctx);
break; break;
case BPF_JMP | BPF_JSET | BPF_X: case BPF_JMP | BPF_JSET | BPF_X:
ctx->flags |= SEEN_S0 | SEEN_X | SEEN_A; ctx->flags |= SEEN_X | SEEN_A;
/* pc += (A & X) ? pc -> jt : pc -> jf */ /* pc += (A & X) ? pc -> jt : pc -> jf */
emit_and(r_s0, r_A, r_X, ctx); emit_and(r_s0, r_A, r_X, ctx);
/* jump true */ /* jump true */
@ -1251,7 +1246,7 @@ static int build_body(struct jit_ctx *ctx)
break; break;
case BPF_ANC | SKF_AD_IFINDEX: case BPF_ANC | SKF_AD_IFINDEX:
/* A = skb->dev->ifindex */ /* A = skb->dev->ifindex */
ctx->flags |= SEEN_SKB | SEEN_A | SEEN_S0; ctx->flags |= SEEN_SKB | SEEN_A;
off = offsetof(struct sk_buff, dev); off = offsetof(struct sk_buff, dev);
/* Load *dev pointer */ /* Load *dev pointer */
emit_load_ptr(r_s0, r_skb, off, ctx); emit_load_ptr(r_s0, r_skb, off, ctx);
@ -1278,7 +1273,7 @@ static int build_body(struct jit_ctx *ctx)
break; break;
case BPF_ANC | SKF_AD_VLAN_TAG: case BPF_ANC | SKF_AD_VLAN_TAG:
case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT: case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
ctx->flags |= SEEN_SKB | SEEN_S0 | SEEN_A; ctx->flags |= SEEN_SKB | SEEN_A;
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
vlan_tci) != 2); vlan_tci) != 2);
off = offsetof(struct sk_buff, vlan_tci); off = offsetof(struct sk_buff, vlan_tci);

View file

@ -18,6 +18,8 @@
#define MIPS_R_V1 3 #define MIPS_R_V1 3
#define MIPS_R_A0 4 #define MIPS_R_A0 4
#define MIPS_R_A1 5 #define MIPS_R_A1 5
#define MIPS_R_T4 12
#define MIPS_R_T5 13
#define MIPS_R_T6 14 #define MIPS_R_T6 14
#define MIPS_R_T7 15 #define MIPS_R_T7 15
#define MIPS_R_S0 16 #define MIPS_R_S0 16