/* * Set up process info to signal segmentation fault - called on access error.
*/ staticvoid set_segfault(struct pt_regs *regs, unsignedlong addr)
{ int si_code;
if (likely(res != -EAGAIN) || signal_pending(current)) break;
cond_resched();
}
if (res == 0) { if (type == TYPE_SWPB)
swpbcounter++; else
swpcounter++;
}
return res;
}
/* * swp_handler logs the id of calling process, dissects the instruction, sanity * checks the memory location, calls emulate_swpX for the actual operation and * deals with fixup/error handling before returning
*/ staticint swp_handler(struct pt_regs *regs, unsignedint instr)
{ unsignedint address, destreg, data, type; unsignedint res = 0;
res = arm_check_condition(instr, regs->ARM_cpsr); switch (res) { case ARM_OPCODE_CONDTEST_PASS: break; case ARM_OPCODE_CONDTEST_FAIL: /* Condition failed - return to next instruction */
regs->ARM_pc += 4; return 0; case ARM_OPCODE_CONDTEST_UNCOND: /* If unconditional encoding - not a SWP, undef */ return -EFAULT; default: return -EINVAL;
}
pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n",
EXTRACT_REG_NUM(instr, RN_OFFSET), address,
destreg, EXTRACT_REG_NUM(instr, RT2_OFFSET), data);
/* Check access in reasonable access range for both SWP and SWPB */ if (!access_ok((void __user *)(address & ~3), 4)) {
pr_debug("SWP{B} emulation: access to %p not allowed!\n",
(void *)address);
res = -EFAULT;
} else {
res = emulate_swpX(address, &data, type);
}
if (res == 0) { /* * On successful emulation, revert the adjustment to the PC * made in kernel/traps.c in order to resume execution at the * instruction following the SWP{B}.
*/
regs->ARM_pc += 4;
regs->uregs[destreg] = data;
} elseif (res == -EFAULT) { /* * Memory errors do not mean emulation failed. * Set up signal info to return SEGV, then return OK
*/
set_segfault(regs, address);
}
return 0;
}
/* * Only emulate SWP/SWPB executed in ARM state/User mode. * The kernel must be SWP free and SWP{B} does not exist in Thumb/ThumbEE.
*/ staticstruct undef_hook swp_hook = {
.instr_mask = 0x0fb00ff0,
.instr_val = 0x01000090,
.cpsr_mask = MODE_MASK | PSR_T_BIT | PSR_J_BIT,
.cpsr_val = USR_MODE,
.fn = swp_handler
};
/* * Register handler and create status file in /proc/cpu * Invoked as late_initcall, since not needed before init spawned.
*/ staticint __init swp_emulation_init(void)
{ if (cpu_architecture() < CPU_ARCH_ARMv7) return 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.