static void bpf_jit_build_prologue(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx) { int i; const struct sock_filter *filter = fp->insns; if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) { /* Make stackframe */ if (ctx->seen & SEEN_DATAREF) { /* If we call any helpers (for loads), save LR */ EMIT(PPC_INST_MFLR | __PPC_RT(R0)); PPC_BPF_STL(0, 1, PPC_LR_STKOFF); /* Back up non-volatile regs. */ PPC_BPF_STL(r_D, 1, -(REG_SZ*(32-r_D))); PPC_BPF_STL(r_HL, 1, -(REG_SZ*(32-r_HL))); } if (ctx->seen & SEEN_MEM) { /* * Conditionally save regs r15-r31 as some will be used * for M[] data. */ for (i = r_M; i < (r_M+16); i++) { if (ctx->seen & (1 << (i-r_M))) PPC_BPF_STL(i, 1, -(REG_SZ*(32-i))); } } PPC_BPF_STLU(1, 1, -BPF_PPC_STACKFRAME); } if (ctx->seen & SEEN_DATAREF) { /* * If this filter needs to access skb data, * prepare r_D and r_HL: * r_HL = skb->len - skb->data_len * r_D = skb->data */ PPC_LWZ_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff, data_len)); PPC_LWZ_OFFS(r_HL, r_skb, offsetof(struct sk_buff, len)); PPC_SUB(r_HL, r_HL, r_scratch1); PPC_LL_OFFS(r_D, r_skb, offsetof(struct sk_buff, data)); } if (ctx->seen & SEEN_XREG) { /* * TODO: Could also detect whether first instr. sets X and * avoid this (as below, with A). */ PPC_LI(r_X, 0); } /* make sure we dont leak kernel information to user */ if (bpf_needs_clear_a(&filter[0])) PPC_LI(r_A, 0); }
static void kvm_patch_ins_wrtee(u32 *inst, u32 rt, int imm_one) { u32 *p; int distance_start; int distance_end; ulong next_inst; p = kvm_alloc(kvm_emulate_wrtee_len * 4); if (!p) return; /* Find out where we are and put everything there */ distance_start = (ulong)p - (ulong)inst; next_inst = ((ulong)inst + 4); distance_end = next_inst - (ulong)&p[kvm_emulate_wrtee_branch_offs]; /* Make sure we only write valid b instructions */ if (distance_start > KVM_INST_B_MAX) { kvm_patching_worked = false; return; } /* Modify the chunk to fit the invocation */ memcpy(p, kvm_emulate_wrtee, kvm_emulate_wrtee_len * 4); p[kvm_emulate_wrtee_branch_offs] |= distance_end & KVM_INST_B_MASK; if (imm_one) { p[kvm_emulate_wrtee_reg_offs] = KVM_INST_LI | __PPC_RT(R30) | MSR_EE; } else { /* Make clobbered registers work too */ switch (get_rt(rt)) { case 30: kvm_patch_ins_ll(&p[kvm_emulate_wrtee_reg_offs], magic_var(scratch2), KVM_RT_30); break; case 31: kvm_patch_ins_ll(&p[kvm_emulate_wrtee_reg_offs], magic_var(scratch1), KVM_RT_30); break; default: p[kvm_emulate_wrtee_reg_offs] |= rt; break; } } p[kvm_emulate_wrtee_orig_ins_offs] = *inst; flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrtee_len * 4); /* Patch the invocation */ kvm_patch_ins_b(inst, distance_start); }
static void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx) { int i; /* * Initialize tail_call_cnt if we do tail calls. * Otherwise, put in NOPs so that it can be skipped when we are * invoked through a tail call. */ if (ctx->seen & SEEN_TAILCALL) { PPC_LI(b2p[TMP_REG_1], 0); /* this goes in the redzone */ PPC_BPF_STL(b2p[TMP_REG_1], 1, -(BPF_PPC_STACK_SAVE + 8)); } else { PPC_NOP(); PPC_NOP(); } #define BPF_TAILCALL_PROLOGUE_SIZE 8 if (bpf_has_stack_frame(ctx)) { /* * We need a stack frame, but we don't necessarily need to * save/restore LR unless we call other functions */ if (ctx->seen & SEEN_FUNC) { EMIT(PPC_INST_MFLR | __PPC_RT(R0)); PPC_BPF_STL(0, 1, PPC_LR_STKOFF); } PPC_BPF_STLU(1, 1, -(BPF_PPC_STACKFRAME + ctx->stack_size)); } /* * Back up non-volatile regs -- BPF registers 6-10 * If we haven't created our own stack frame, we save these * in the protected zone below the previous stack frame */ for (i = BPF_REG_6; i <= BPF_REG_10; i++) if (bpf_is_seen_register(ctx, i)) PPC_BPF_STL(b2p[i], 1, bpf_jit_stack_offsetof(ctx, b2p[i])); /* Setup frame pointer to point to the bpf stack area */ if (bpf_is_seen_register(ctx, BPF_REG_FP)) PPC_ADDI(b2p[BPF_REG_FP], 1, STACK_FRAME_MIN_SIZE + ctx->stack_size); }
static void bpf_jit_build_prologue(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx) { int i; const struct sock_filter *filter = fp->insns; if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) { /* Make stackframe */ if (ctx->seen & SEEN_DATAREF) { /* If we call any helpers (for loads), save LR */ EMIT(PPC_INST_MFLR | __PPC_RT(R0)); PPC_STD(0, 1, 16); /* Back up non-volatile regs. */ PPC_STD(r_D, 1, -(8*(32-r_D))); PPC_STD(r_HL, 1, -(8*(32-r_HL))); } if (ctx->seen & SEEN_MEM) { /* * Conditionally save regs r15-r31 as some will be used * for M[] data. */ for (i = r_M; i < (r_M+16); i++) { if (ctx->seen & (1 << (i-r_M))) PPC_STD(i, 1, -(8*(32-i))); } } EMIT(PPC_INST_STDU | __PPC_RS(R1) | __PPC_RA(R1) | (-BPF_PPC_STACKFRAME & 0xfffc)); } if (ctx->seen & SEEN_DATAREF) { /* * If this filter needs to access skb data, * prepare r_D and r_HL: * r_HL = skb->len - skb->data_len * r_D = skb->data */ PPC_LWZ_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff, data_len)); PPC_LWZ_OFFS(r_HL, r_skb, offsetof(struct sk_buff, len)); PPC_SUB(r_HL, r_HL, r_scratch1); PPC_LD_OFFS(r_D, r_skb, offsetof(struct sk_buff, data)); } if (ctx->seen & SEEN_XREG) { /* * TODO: Could also detect whether first instr. sets X and * avoid this (as below, with A). */ PPC_LI(r_X, 0); } switch (filter[0].code) { case BPF_RET | BPF_K: case BPF_LD | BPF_W | BPF_LEN: case BPF_LD | BPF_W | BPF_ABS: case BPF_LD | BPF_H | BPF_ABS: case BPF_LD | BPF_B | BPF_ABS: /* first instruction sets A register (or is RET 'constant') */ break; default: /* make sure we dont leak kernel information to user */ PPC_LI(r_A, 0); } }