arch/arc/net/bpf_jit_arcv2.c

Source file repositories/reference/linux-study-clean/arch/arc/net/bpf_jit_arcv2.c

File Facts

System
Linux kernel
Corpus path
arch/arc/net/bpf_jit_arcv2.c
Extension
.c
Size
73964 bytes
Lines
3008
Domain
Architecture Layer
Bucket
arch/arc
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 (sign_ext == 8 || sign_ext == 16 || sign_ext == 32) {
			len += arc_asri_r(BUF(buf, len),
					  REG_HI(rd), REG_LO(rd), 31);
		}

		return len;
	}

	/* Unsigned move. */

	if (rd == rs)
		return 0;

	len = arc_mov_r(buf, REG_LO(rd), REG_LO(rs));

	if (rs != BPF_REG_FP)
		len += arc_mov_r(BUF(buf, len), REG_HI(rd), REG_HI(rs));
	/* BPF_REG_FP is mapped to 32-bit "fp" register. */
	else
		len += arc_movi_r(BUF(buf, len), REG_HI(rd), 0);

	return len;
}

/* Sign extend the 32-bit immediate into 64-bit register pair. */
u8 mov_r64_i32(u8 *buf, u8 reg, s32 imm)
{
	u8 len = 0;

	len = arc_mov_i(buf, REG_LO(reg), imm);

	/* BPF_REG_FP is mapped to 32-bit "fp" register. */
	if (reg != BPF_REG_FP) {
		if (imm >= 0)
			len += arc_movi_r(BUF(buf, len), REG_HI(reg), 0);
		else
			len += arc_movi_r(BUF(buf, len), REG_HI(reg), -1);
	}

	return len;
}

/*
 * This is merely used for translation of "LD R, IMM64" instructions
 * of the BPF. These sort of instructions are sometimes used for
 * relocations. If during the normal pass, the relocation value is
 * not known, the BPF instruction may look something like:
 *
 * LD R <- 0x0000_0001_0000_0001
 *
 * Which will nicely translate to two 4-byte ARC instructions:
 *
 * mov R_lo, 1               # imm is small enough to be s12
 * mov R_hi, 1               # same
 *
 * However, during the extra pass, the IMM64 will have changed
 * to the resolved address and looks something like:
 *
 * LD R <- 0x0000_0000_1234_5678
 *
 * Now, the translated code will require 12 bytes:
 *
 * mov R_lo, 0x12345678      # this is an 8-byte instruction
 * mov R_hi, 0               # still 4 bytes
 *
 * Which in practice will result in overwriting the following
 * instruction. To avoid such cases, we will always emit codes
 * with fixed sizes.
 */
u8 mov_r64_i64(u8 *buf, u8 reg, u32 lo, u32 hi)
{
	u8 len;

	len  = arc_mov_i_fixed(buf, REG_LO(reg), lo);
	len += arc_mov_i_fixed(BUF(buf, len), REG_HI(reg), hi);

	return len;
}

/*
 * If the "off"set is too big (doesn't encode as S9) for:
 *
 *   {ld,st}  r, [rm, off]
 *
 * Then emit:
 *
 *   add r10, REG_LO(rm), off
 *
 * and make sure that r10 becomes the effective address:
 *

Annotation

Implementation Notes