arch/arm64/kernel/probes/simulate-insn.c

Source file repositories/reference/linux-study-clean/arch/arm64/kernel/probes/simulate-insn.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kernel/probes/simulate-insn.c
Extension
.c
Size
5373 bytes
Lines
239
Domain
Architecture Layer
Bucket
arch/arm64
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 (err) {
			force_sig(SIGSEGV);
			return err;
		}
	}
	procedure_link_pointer_set(regs, addr);
	return err;
}

static bool __kprobes check_cbz(u32 opcode, struct pt_regs *regs)
{
	int xn = opcode & 0x1f;

	return (opcode & (1 << 31)) ?
	    (get_x_reg(regs, xn) == 0) : (get_w_reg(regs, xn) == 0);
}

static bool __kprobes check_cbnz(u32 opcode, struct pt_regs *regs)
{
	int xn = opcode & 0x1f;

	return (opcode & (1 << 31)) ?
	    (get_x_reg(regs, xn) != 0) : (get_w_reg(regs, xn) != 0);
}

static bool __kprobes check_tbz(u32 opcode, struct pt_regs *regs)
{
	int xn = opcode & 0x1f;
	int bit_pos = ((opcode & (1 << 31)) >> 26) | ((opcode >> 19) & 0x1f);

	return ((get_x_reg(regs, xn) >> bit_pos) & 0x1) == 0;
}

static bool __kprobes check_tbnz(u32 opcode, struct pt_regs *regs)
{
	int xn = opcode & 0x1f;
	int bit_pos = ((opcode & (1 << 31)) >> 26) | ((opcode >> 19) & 0x1f);

	return ((get_x_reg(regs, xn) >> bit_pos) & 0x1) != 0;
}

/*
 * instruction simulation functions
 */
void __kprobes
simulate_adr_adrp(u32 opcode, long addr, struct pt_regs *regs)
{
	long imm, xn, val;

	xn = opcode & 0x1f;
	imm = ((opcode >> 3) & 0x1ffffc) | ((opcode >> 29) & 0x3);
	imm = sign_extend64(imm, 20);
	if (opcode & 0x80000000)
		val = (imm<<12) + (addr & 0xfffffffffffff000);
	else
		val = imm + addr;

	set_x_reg(regs, xn, val);

	instruction_pointer_set(regs, instruction_pointer(regs) + 4);
}

void __kprobes
simulate_b_bl(u32 opcode, long addr, struct pt_regs *regs)
{
	int disp = bbl_displacement(opcode);

	if (opcode & (1 << 31))
		if (update_lr(regs, addr + 4))
			return;

	instruction_pointer_set(regs, addr + disp);
}

void __kprobes
simulate_b_cond(u32 opcode, long addr, struct pt_regs *regs)
{
	int disp = 4;

	if (aarch32_opcode_cond_checks[opcode & 0xf](regs->pstate & 0xffffffff))
		disp = bcond_displacement(opcode);

	instruction_pointer_set(regs, addr + disp);
}

void __kprobes
simulate_br_blr(u32 opcode, long addr, struct pt_regs *regs)
{
	int xn = (opcode >> 5) & 0x1f;
	u64 b_target = get_x_reg(regs, xn);

Annotation

Implementation Notes