arch/parisc/net/bpf_jit_comp64.c

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

File Facts

System
Linux kernel
Corpus path
arch/parisc/net/bpf_jit_comp64.c
Extension
.c
Size
33646 bytes
Lines
1210
Domain
Architecture Layer
Bucket
arch/parisc
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 (BPF_OP(opcode) == BPF_DIV || BPF_OP(opcode) == BPF_MOD) {
		if (BPF_OP(opcode) == BPF_DIV)
			emit_hppa_copy(HPPA_REG_ZERO, HPPA_REG_RET0, ctx);
		else {
			emit_hppa_copy(HPPA_REG_ARG0, HPPA_REG_RET0, ctx);
		}
		emit(hppa_beq(HPPA_REG_ARG1, HPPA_REG_ZERO, 2 - HPPA_BRANCH_DISPLACEMENT), ctx);
	}
	emit(hppa64_bve_l_rp(HPPA_REG_RP), ctx);
	emit(hppa64_ldd_im16(offsetof(struct elf64_fdesc, gp),
			     HPPA_REG_R31, HPPA_REG_GP), ctx);

	emit(hppa_ldo(-FRAME_SIZE, HPPA_REG_SP, HPPA_REG_SP), ctx);

	emit_hppa_copy(HPPA_REG_RET0, arg0, ctx);

	/* restore HPPA_REG_RET0 */
	if (arg0 != HPPA_REG_RET0)
		emit(hppa_copy(HPPA_REG_TCC_SAVED, HPPA_REG_RET0), ctx);
}

static void emit_store(const s8 rd, const s8 rs, s16 off,
			  struct hppa_jit_context *ctx, const u8 size,
			  const u8 mode)
{
	s8 dstreg;

	/* need to calculate address since offset does not fit in 14 bits? */
	if (relative_bits_ok(off, 14))
		dstreg = rd;
	else {
		/* need to use R1 here, since addil puts result into R1 */
		dstreg = HPPA_REG_R1;
		emit(hppa_addil(off, rd), ctx);
		off = im11(off);
	}

	switch (size) {
	case BPF_B:
		emit(hppa_stb(rs, off, dstreg), ctx);
		break;
	case BPF_H:
		emit(hppa_sth(rs, off, dstreg), ctx);
		break;
	case BPF_W:
		emit(hppa_stw(rs, off, dstreg), ctx);
		break;
	case BPF_DW:
		if (off & 7) {
			emit(hppa_ldo(off, dstreg, HPPA_REG_R1), ctx);
			emit(hppa64_std_im5(rs, 0, HPPA_REG_R1), ctx);
		} else if (off >= -16 && off <= 15)
			emit(hppa64_std_im5(rs, off, dstreg), ctx);
		else
			emit(hppa64_std_im16(rs, off, dstreg), ctx);
		break;
	}
}

int bpf_jit_emit_insn(const struct bpf_insn *insn, struct hppa_jit_context *ctx,
		      bool extra_pass)
{
	bool is64 = BPF_CLASS(insn->code) == BPF_ALU64 ||
		    BPF_CLASS(insn->code) == BPF_JMP;
	int s, e, ret, i = insn - ctx->prog->insnsi;
	s64 paoff;
	struct bpf_prog_aux *aux = ctx->prog->aux;
	u8 rd = -1, rs = -1, code = insn->code;
	s16 off = insn->off;
	s32 imm = insn->imm;

	init_regs(&rd, &rs, insn, ctx);

	switch (code) {
	/* dst = src */
	case BPF_ALU | BPF_MOV | BPF_X:
	case BPF_ALU64 | BPF_MOV | BPF_X:
		if (imm == 1) {
			/* Special mov32 for zext */
			emit_zext_32(rd, ctx);
			break;
		}
		if (!is64 && !aux->verifier_zext)
			emit_hppa64_zext32(rs, rd, ctx);
		else
			emit_hppa_copy(rs, rd, ctx);
		break;

	/* dst = dst OP src */
	case BPF_ALU | BPF_ADD | BPF_X:

Annotation

Implementation Notes