arch/powerpc/net/bpf_jit_comp64.c

Source file repositories/reference/linux-study-clean/arch/powerpc/net/bpf_jit_comp64.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/net/bpf_jit_comp64.c
Extension
.c
Size
60883 bytes
Lines
2037
Domain
Architecture Layer
Bucket
arch/powerpc
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 (ctx->seen & SEEN_FUNC) {
			EMIT(PPC_RAW_MFLR(_R0));
			EMIT(PPC_RAW_STD(_R0, _R1, PPC_LR_STKOFF));
		}

		EMIT(PPC_RAW_STDU(_R1, _R1,
				-(bpf_jit_stack_size(ctx) + ctx->stack_size)));
	}

	/*
	 * Program acting as exception boundary pushes R14..R25 in addition to
	 * BPF callee-saved non volatile registers. Exception callback uses
	 * the boundary program's stack frame, recover additionally saved
	 * registers in epilogue of exception callback.
	 */
	if (ctx->exception_boundary) {
		for (i = _R14; i <= _R25; i++)
			EMIT(PPC_RAW_STD(i, _R1, bpf_jit_stack_offsetof(ctx, i)));
	}

	if (!ctx->exception_cb) {
		/*
		 * 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 (ctx->exception_boundary || bpf_is_seen_register(ctx, bpf_to_ppc(i)))
				EMIT(PPC_RAW_STD(bpf_to_ppc(i), _R1,
					bpf_jit_stack_offsetof(ctx, bpf_to_ppc(i))));

		if (ctx->exception_boundary || ctx->arena_vm_start)
			EMIT(PPC_RAW_STD(bpf_to_ppc(ARENA_VM_START), _R1,
				 bpf_jit_stack_offsetof(ctx, bpf_to_ppc(ARENA_VM_START))));
	} else {
		/*
		 * Exception callback receives Frame Pointer of boundary
		 * program(main prog) as third arg
		 */
		EMIT(PPC_RAW_MR(_R1, _R5));
		/*
		 * Exception callback reuses the stack frame of exception boundary.
		 * But BPF stack depth of exception callback and exception boundary
		 * don't have to be same. If BPF stack depth is different, adjust the
		 * stack frame size considering BPF stack depth of exception callback.
		 * The non-volatile register save area remains unchanged. These non-
		 * volatile registers are restored in exception callback's epilogue.
		 */
		EMIT(PPC_RAW_LD(bpf_to_ppc(TMP_REG_1), _R5, 0));
		EMIT(PPC_RAW_SUB(bpf_to_ppc(TMP_REG_2), bpf_to_ppc(TMP_REG_1), _R1));
		EMIT(PPC_RAW_ADDI(bpf_to_ppc(TMP_REG_2), bpf_to_ppc(TMP_REG_2),
			-BPF_PPC_EXC_STACKFRAME));
		EMIT(PPC_RAW_CMPLDI(bpf_to_ppc(TMP_REG_2), ctx->stack_size));
		PPC_BCC_CONST_SHORT(COND_EQ, 12);
		EMIT(PPC_RAW_MR(_R1, bpf_to_ppc(TMP_REG_1)));
		EMIT(PPC_RAW_STDU(_R1, _R1, -(BPF_PPC_EXC_STACKFRAME + ctx->stack_size)));
	}

	/*
	 * Exception_cb not restricted from using stack area or arena.
	 * Setup frame pointer to point to the bpf stack area
	 */
	if (bpf_is_seen_register(ctx, bpf_to_ppc(BPF_REG_FP))) {
		if (ctx->priv_sp) {
			/* Set up fp in private stack */
			emit_fp_priv_stack(image, ctx);
		} else {
			/* Setup frame pointer to point to the bpf stack area */
			EMIT(PPC_RAW_ADDI(bpf_to_ppc(BPF_REG_FP), _R1,
				STACK_FRAME_MIN_SIZE + ctx->stack_size));
		}
	}

	if (ctx->arena_vm_start)
		PPC_LI64(bpf_to_ppc(ARENA_VM_START), ctx->arena_vm_start);
}

static void bpf_jit_emit_common_epilogue(u32 *image, struct codegen_context *ctx)
{
	int i;

	/* Restore NVRs */
	for (i = BPF_REG_6; i <= BPF_REG_10; i++)
		if (ctx->exception_cb || bpf_is_seen_register(ctx, bpf_to_ppc(i)))
			EMIT(PPC_RAW_LD(bpf_to_ppc(i), _R1, bpf_jit_stack_offsetof(ctx, bpf_to_ppc(i))));

	if (ctx->exception_cb || ctx->arena_vm_start)
		EMIT(PPC_RAW_LD(bpf_to_ppc(ARENA_VM_START), _R1,
				bpf_jit_stack_offsetof(ctx, bpf_to_ppc(ARENA_VM_START))));

Annotation

Implementation Notes