阅读背景:

armv8 不支持的指令造成的异常会在kernel中通过其他指令替换

来源:互联网 
armv8 hw对某些指令不支持,这样在用户态调用的时候就会陷入异常,这样kernel会为通过软件的方式来执行这些指令,这样用户态由于某些指令异常陷入kernel中,kernel通过软件的方式执行后,会成功返回用户态.
具体可以看下面的函数
static void __init register_insn_emulation(struct insn_emulation_ops *ops)
{
	unsigned long flags;
	struct insn_emulation *insn;

	insn = kzalloc(sizeof(*insn), GFP_KERNEL);
	insn->ops = ops;
	insn->min = INSN_UNDEF;

	switch (ops->status) {
	case INSN_DEPRECATED:
//如果是armv8 不支持的执行,会为这个指令注册一个回调函数
		insn->current_mode = INSN_EMULATE;
		/* Disable the HW mode if it was turned on at early boot time */
		run_all_cpu_set_hw_mode(insn, false);
		insn->max = INSN_HW;
		break;
	
}
那些指令armv8 不支持呢?
static struct undef_hook cp15_barrier_hooks[] = {
	{
		.instr_mask	= 0x0fff0fdf,
		.instr_val	= 0x0e070f9a,
		.pstate_mask	= COMPAT_PSR_MODE_MASK,
		.pstate_val	= COMPAT_PSR_MODE_USR,
		.fn		= cp15barrier_handler,
	},
	{
		.instr_mask	= 0x0fff0fff,
		.instr_val	= 0x0e070f95,
		.pstate_mask	= COMPAT_PSR_MODE_MASK,
		.pstate_val	= COMPAT_PSR_MODE_USR,
		.fn		= cp15barrier_handler,
	},
	{ }
};

static struct insn_emulation_ops cp15_barrier_ops = {
	.name = "cp15_barrier",
	.status = INSN_DEPRECATED,
	.hooks = cp15_barrier_hooks,
	.set_hw_mode = cp15_barrier_set_hw_mode,
};
可见.instr_val	= 0x0e070f9a和.instr_val	= 0x0e070f95, 这两条指令armv8不支持,如果用户态是由于这两个指令异常的话,kernel会调用cp15barrier_handler 执行这两个指令,最终用户态可以正确执行
static int cp15barrier_handler(struct pt_regs *regs, u32 instr)
{
	

	switch (aarch32_insn_mcr_extract_crm(instr)) {

	case 10:
所以0x0e070f9a 这条指令就有下面的两条执行替换,执行后的效果是完全相同的
		/*
		 * dmb - mcr p15, 0, Rt, c7, c10, 5
		 * dsb - mcr p15, 0, Rt, c7, c10, 4
		 */
		if (aarch32_insn_mcr_extract_opc2(instr) == 5) {
			dmb(sy);
			trace_instruction_emulation(
				"mcr p15, 0, Rt, c7, c10, 5 ; dmb", regs->pc);
		} else {
			dsb(sy);
			trace_instruction_emulation(
				"mcr p15, 0, Rt, c7, c10, 4 ; dsb", regs->pc);
		}
		break;
	case 5:
		/*
		 * isb - mcr p15, 0, Rt, c7, c5, 4
		 *
		 * Taking an exception or returning from one acts as an
		 * instruction barrier. So no explicit barrier needed here.
		 */
		trace_instruction_emulation(
			"mcr p15, 0, Rt, c7, c5, 4 ; isb", regs->pc);
		break;
	}

ret:
	pr_warn_ratelimited("\"%s\" (%ld) uses deprecated CP15 Barrier instruction at 0x%llx\n",
			current->comm, (unsigned long)current->pid, regs->pc);

	regs->pc += 4;
	return 0;
}armv8 hw对某些指令不支持,这样在用户态调用的时候就会陷入异常,这样kernel会为通过



你的当前访问异常,请进行认证后继续阅读剩余内容。

分享到: