/* * LDM/STM alignment handler. * * There are 4 variants of this instruction: * * B = rn pointer before instruction, A = rn pointer after instruction * ------ increasing address -----> * | | r0 | r1 | ... | rx | | * PU = 01 B A * PU = 11 B A * PU = 00 A B * PU = 10 A B
*/ staticint
do_alignment_ldmstm(unsignedlong addr, u32 instr, struct pt_regs *regs)
{ unsignedint rd, rn, nr_regs, regbits; unsignedlong eaddr, newaddr; unsignedint val;
/* count the number of registers in the mask to be transferred */
nr_regs = hweight16(REGMASK_BITS(instr)) * 4;
if (!LDST_U_BIT(instr))
nr_regs = -nr_regs;
newaddr += nr_regs; if (!LDST_U_BIT(instr))
eaddr = newaddr;
if (LDST_P_EQ_U(instr)) /* U = P */
eaddr += 4;
for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
regbits >>= 1, rd += 1) if (regbits & 1) { if (LDST_L_BIT(instr)) { if (get_user(val, (u32 __user *)eaddr)) return TYPE_FAULT; if (rd < 15)
regs->regs[rd] = val; else
regs->pc = val;
} else { /* * The PC register has a bias of +8 in ARM mode * and +4 in Thumb mode. This means that a read * of the value of PC should account for this. * Since Thumb does not permit STM instructions * to refer to PC, just add 8 here.
*/
val = (rd < 15) ? regs->regs[rd] : regs->pc + 8; if (put_user(val, (u32 __user *)eaddr)) return TYPE_FAULT;
}
eaddr += 4;
}
if (LDST_W_BIT(instr))
regs->regs[rn] = newaddr;
return TYPE_DONE;
}
/* * Convert Thumb multi-word load/store instruction forms to equivalent ARM * instructions so we can reuse ARM userland alignment fault fixups for Thumb. * * This implementation was initially based on the algorithm found in * gdb/sim/arm/thumbemu.c. It is basically just a code reduction of same * to convert only Thumb ld/st instruction forms to equivalent ARM forms. * * NOTES: * 1. Comments below refer to ARM ARM DDI0100E Thumb Instruction sections. * 2. If for some reason we're passed an non-ld/st Thumb instruction to * decode, we return 0xdeadc0de. This should never happen under normal * circumstances but if it does, we've got other problems to deal with * elsewhere and we obviously can't fix those problems here.
*/
/* * Convert Thumb-2 32 bit LDM, STM, LDRD, STRD to equivalent instruction * handlable by ARM alignment handler, also find the corresponding handler, * so that we can reuse ARM userland alignment fault fixups for Thumb. * * @pinstr: original Thumb-2 instruction; returns new handlable instruction * @regs: register context. * @poffset: return offset from faulted addr for later writeback * * NOTES: * 1. Comments below refer to ARMv7 DDI0406A Thumb Instruction sections. * 2. Register name Rt from ARMv7 is same as Rd from ARMv6 (Rd is Rt)
*/ staticvoid *
do_alignment_t32_to_handler(u32 *pinstr, struct pt_regs *regs, union offset_union *poffset)
{
u32 instr = *pinstr;
u16 tinst1 = (instr >> 16) & 0xffff;
u16 tinst2 = instr & 0xffff;
switch (tinst1 & 0xffe0) { /* A6.3.5 Load/Store multiple */ case 0xe880: /* STM/STMIA/STMEA,LDM/LDMIA, PUSH/POP T2 */ case 0xe8a0: /* ...above writeback version */ case 0xe900: /* STMDB/STMFD, LDMDB/LDMEA */ case 0xe920: /* ...above writeback version */ /* no need offset decision since handler calculates it */ return do_alignment_ldmstm;
case 0xf840: /* POP/PUSH T3 (single register) */ if (RN_BITS(instr) == 13 && (tinst2 & 0x09ff) == 0x0904) {
u32 L = !!(LDST_L_BIT(instr)); const u32 subset[2] = {
0xe92d0000, /* STMDB sp!,{registers} */
0xe8bd0000, /* LDMIA sp!,{registers} */
};
*pinstr = subset[L] | (1<<RD_BITS(instr)); return do_alignment_ldmstm;
} /* Else fall through for illegal instruction case */ break;
/* A6.3.6 Load/store double, STRD/LDRD(immed, lit, reg) */ case 0xe860: case 0xe960: case 0xe8e0: case 0xe9e0:
poffset->un = (tinst2 & 0xff) << 2;
fallthrough;
case 0xe940: case 0xe9c0: return do_alignment_ldrdstrd;
/* * No need to handle load/store instructions up to word size * since ARMv6 and later CPUs can perform unaligned accesses.
*/ default: break;
} return NULL;
}
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.