arch/mips/net/bpf_jit_comp.c

Source file repositories/reference/linux-study-clean/arch/mips/net/bpf_jit_comp.c

File Facts

System
Linux kernel
Corpus path
arch/mips/net/bpf_jit_comp.c
Extension
.c
Size
26246 bytes
Lines
1022
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (mask & BIT(reg)) {
			if ((excl & BIT(reg)) == 0) {
				if (sizeof(long) == 4)
					emit(ctx, sw, reg, depth, MIPS_R_SP);
				else /* sizeof(long) == 8 */
					emit(ctx, sd, reg, depth, MIPS_R_SP);
			}
			depth += sizeof(long);
		}

	ctx->stack_used = max((int)ctx->stack_used, depth);
	return depth;
}

/*
 * Pop registers from the stack, starting at a given depth from the stack
 * pointer and increasing. The next depth to be read is returned.
 */
int pop_regs(struct jit_context *ctx, u32 mask, u32 excl, int depth)
{
	int reg;

	for (reg = 0; reg < BITS_PER_BYTE * sizeof(mask); reg++)
		if (mask & BIT(reg)) {
			if ((excl & BIT(reg)) == 0) {
				if (sizeof(long) == 4)
					emit(ctx, lw, reg, depth, MIPS_R_SP);
				else /* sizeof(long) == 8 */
					emit(ctx, ld, reg, depth, MIPS_R_SP);
			}
			depth += sizeof(long);
		}

	return depth;
}

/* Compute the 28-bit jump target address from a BPF program location */
int get_target(struct jit_context *ctx, u32 loc)
{
	u32 index = INDEX(ctx->descriptors[loc]);
	unsigned long pc = (unsigned long)&ctx->target[ctx->jit_index];
	unsigned long addr = (unsigned long)&ctx->target[index];

	if (!ctx->target)
		return 0;

	if ((addr ^ pc) & ~MIPS_JMP_MASK)
		return -1;

	return addr & MIPS_JMP_MASK;
}

/* Compute the PC-relative offset to relative BPF program offset */
int get_offset(const struct jit_context *ctx, int off)
{
	return (INDEX(ctx->descriptors[ctx->bpf_index + off]) -
		ctx->jit_index - 1) * sizeof(u32);
}

/* dst = imm (register width) */
void emit_mov_i(struct jit_context *ctx, u8 dst, s32 imm)
{
	if (imm >= -0x8000 && imm <= 0x7fff) {
		emit(ctx, addiu, dst, MIPS_R_ZERO, imm);
	} else {
		emit(ctx, lui, dst, (s16)((u32)imm >> 16));
		emit(ctx, ori, dst, dst, (u16)(imm & 0xffff));
	}
	clobber_reg(ctx, dst);
}

/* dst = src (register width) */
void emit_mov_r(struct jit_context *ctx, u8 dst, u8 src)
{
	emit(ctx, ori, dst, src, 0);
	clobber_reg(ctx, dst);
}

/* Validate ALU immediate range */
bool valid_alu_i(u8 op, s32 imm)
{
	switch (BPF_OP(op)) {
	case BPF_NEG:
	case BPF_LSH:
	case BPF_RSH:
	case BPF_ARSH:
		/* All legal eBPF values are valid */
		return true;
	case BPF_ADD:
		if (IS_ENABLED(CONFIG_CPU_DADDI_WORKAROUNDS))

Annotation

Implementation Notes