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 不支持的指令造成的异常会在kernel中通过其他指令替换
最新推荐文章于 2024-07-12 20:58:01 发布