arch/loongarch/net/bpf_jit.h

Source file repositories/reference/linux-study-clean/arch/loongarch/net/bpf_jit.h

File Facts

System
Linux kernel
Corpus path
arch/loongarch/net/bpf_jit.h
Extension
.h
Size
8737 bytes
Lines
345
Domain
Architecture Layer
Bucket
arch/loongarch
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

struct jit_ctx {
	const struct bpf_prog *prog;
	unsigned int idx;
	unsigned int flags;
	unsigned int epilogue_offset;
	u32 *offset;
	int num_exentries;
	union loongarch_instruction *image;
	union loongarch_instruction *ro_image;
	u32 stack_size;
	u64 arena_vm_start;
	u64 user_vm_start;
};

struct jit_data {
	struct bpf_binary_header *header;
	struct bpf_binary_header *ro_header;
	struct jit_ctx ctx;
};

static inline void emit_nop(union loongarch_instruction *insn)
{
	insn->word = INSN_NOP;
}

#define emit_insn(ctx, func, ...)						\
do {										\
	if (ctx->image != NULL) {						\
		union loongarch_instruction *insn = &ctx->image[ctx->idx];	\
		emit_##func(insn, ##__VA_ARGS__);				\
	}									\
	ctx->idx++;								\
} while (0)

#define is_signed_imm12(val)	signed_imm_check(val, 12)
#define is_signed_imm14(val)	signed_imm_check(val, 14)
#define is_signed_imm16(val)	signed_imm_check(val, 16)
#define is_signed_imm26(val)	signed_imm_check(val, 26)
#define is_signed_imm32(val)	signed_imm_check(val, 32)
#define is_signed_imm52(val)	signed_imm_check(val, 52)
#define is_unsigned_imm12(val)	unsigned_imm_check(val, 12)

static inline int bpf2la_offset(int bpf_insn, int off, const struct jit_ctx *ctx)
{
	/* BPF JMP offset is relative to the next instruction */
	bpf_insn++;
	/*
	 * Whereas LoongArch branch instructions encode the offset
	 * from the branch itself, so we must subtract 1 from the
	 * instruction offset.
	 */
	return (ctx->offset[bpf_insn + off] - (ctx->offset[bpf_insn] - 1));
}

static inline int epilogue_offset(const struct jit_ctx *ctx)
{
	int from = ctx->idx;
	int to = ctx->epilogue_offset;

	return (to - from);
}

/* Zero-extend 32 bits into 64 bits */
static inline void emit_zext_32(struct jit_ctx *ctx, enum loongarch_gpr reg, bool is32)
{
	if (!is32)
		return;

	emit_insn(ctx, lu32id, reg, 0);
}

/* Signed-extend 32 bits into 64 bits */
static inline void emit_sext_32(struct jit_ctx *ctx, enum loongarch_gpr reg, bool is32)
{
	if (!is32)
		return;

	emit_insn(ctx, addiw, reg, reg, 0);
}

/* Emit proper extension according to ABI requirements.
 * Note that it requires a value of size `size` already resides in register `reg`.
 */
static inline void emit_abi_ext(struct jit_ctx *ctx, int reg, u8 size, bool sign)
{
	/* ABI requires unsigned char/short to be zero-extended */
	if (!sign && (size == 1 || size == 2))
		return;

	switch (size) {

Annotation

Implementation Notes