in kernel/traps.c [378:423]
static inline void simulate_swa(struct pt_regs *regs, unsigned long address,
unsigned int insn)
{
unsigned long __user *vaddr;
unsigned long orig_pc;
unsigned int ra, rb;
long imm;
const struct exception_table_entry *entry;
orig_pc = regs->pc;
adjust_pc(regs, address);
ra = (insn >> 16) & 0x1f;
rb = (insn >> 11) & 0x1f;
imm = (short)(((insn & 0x2200000) >> 10) | (insn & 0x7ff));
vaddr = (unsigned long __user *)(regs->gpr[ra] + imm);
if (!lwa_flag || vaddr != lwa_addr) {
regs->sr &= ~SPR_SR_F;
return;
}
if ((unsigned long)vaddr & 0x3) {
do_unaligned_access(regs, address);
return;
}
if (put_user(regs->gpr[rb], vaddr)) {
if (user_mode(regs)) {
force_sig(SIGSEGV);
return;
}
if ((entry = search_exception_tables(orig_pc))) {
regs->pc = entry->fixup;
return;
}
/* kernel access in kernel space, store it directly */
*((unsigned long *)vaddr) = regs->gpr[rb];
}
lwa_flag = 0;
regs->sr |= SPR_SR_F;
}