arch/x86/net/bpf_jit_comp32.c

Source file repositories/reference/linux-study-clean/arch/x86/net/bpf_jit_comp32.c

File Facts

System
Linux kernel
Corpus path
arch/x86/net/bpf_jit_comp32.c
Extension
.c
Size
68189 bytes
Lines
2599
Domain
Architecture Layer
Bucket
arch/x86
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_context {
	int cleanup_addr; /* Epilogue code offset */
};

/* Maximum number of bytes emitted while JITing one eBPF insn */
#define BPF_MAX_INSN_SIZE	128
#define BPF_INSN_SAFETY		64

#define PROLOGUE_SIZE 35

/*
 * Emit prologue code for BPF program and check its size.
 * bpf_tail_call helper will skip it while jumping into another program.
 */
static void emit_prologue(u8 **pprog, u32 stack_depth)
{
	u8 *prog = *pprog;
	int cnt = 0;
	const u8 *r1 = bpf2ia32[BPF_REG_1];
	const u8 fplo = bpf2ia32[BPF_REG_FP][0];
	const u8 fphi = bpf2ia32[BPF_REG_FP][1];
	const u8 *tcc = bpf2ia32[TCALL_CNT];

	/* push ebp */
	EMIT1(0x55);
	/* mov ebp,esp */
	EMIT2(0x89, 0xE5);
	/* push edi */
	EMIT1(0x57);
	/* push esi */
	EMIT1(0x56);
	/* push ebx */
	EMIT1(0x53);

	/* sub esp,STACK_SIZE */
	EMIT2_off32(0x81, 0xEC, STACK_SIZE);
	/* sub ebp,SCRATCH_SIZE+12*/
	EMIT3(0x83, add_1reg(0xE8, IA32_EBP), SCRATCH_SIZE + 12);
	/* xor ebx,ebx */
	EMIT2(0x31, add_2reg(0xC0, IA32_EBX, IA32_EBX));

	/* Set up BPF prog stack base register */
	EMIT3(0x89, add_2reg(0x40, IA32_EBP, IA32_EBP), STACK_VAR(fplo));
	EMIT3(0x89, add_2reg(0x40, IA32_EBP, IA32_EBX), STACK_VAR(fphi));

	/* Move BPF_CTX (EAX) to BPF_REG_R1 */
	/* mov dword ptr [ebp+off],eax */
	EMIT3(0x89, add_2reg(0x40, IA32_EBP, IA32_EAX), STACK_VAR(r1[0]));
	EMIT3(0x89, add_2reg(0x40, IA32_EBP, IA32_EBX), STACK_VAR(r1[1]));

	/* Initialize Tail Count */
	EMIT3(0x89, add_2reg(0x40, IA32_EBP, IA32_EBX), STACK_VAR(tcc[0]));
	EMIT3(0x89, add_2reg(0x40, IA32_EBP, IA32_EBX), STACK_VAR(tcc[1]));

	BUILD_BUG_ON(cnt != PROLOGUE_SIZE);
	*pprog = prog;
}

/* Emit epilogue code for BPF program */
static void emit_epilogue(u8 **pprog, u32 stack_depth)
{
	u8 *prog = *pprog;
	const u8 *r0 = bpf2ia32[BPF_REG_0];
	int cnt = 0;

	/* mov eax,dword ptr [ebp+off]*/
	EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EAX), STACK_VAR(r0[0]));
	/* mov edx,dword ptr [ebp+off]*/
	EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EDX), STACK_VAR(r0[1]));

	/* add ebp,SCRATCH_SIZE+12*/
	EMIT3(0x83, add_1reg(0xC0, IA32_EBP), SCRATCH_SIZE + 12);

	/* mov ebx,dword ptr [ebp-12]*/
	EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EBX), -12);
	/* mov esi,dword ptr [ebp-8]*/
	EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_ESI), -8);
	/* mov edi,dword ptr [ebp-4]*/
	EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EDI), -4);

	EMIT1(0xC9); /* leave */
	EMIT1(0xC3); /* ret */
	*pprog = prog;
}

static int emit_jmp_edx(u8 **pprog, u8 *ip)
{
	u8 *prog = *pprog;
	int cnt = 0;

Annotation

Implementation Notes