/* Bits in the flags field */ #define LD 0 /* load */ #define ST 1 /* store */ #define SE 2 /* sign-extend value, or FP ld/st as word */ #define SW 0x20 /* byte swap */ #define E4 0x40 /* SPE endianness is word */ #define E8 0x80 /* SPE endianness is double word */
/* DAR has the operand effective address */
addr = (unsignedchar __user *)regs->dar;
nb = spe_aligninfo[instr].len;
flags = spe_aligninfo[instr].flags;
/* userland only */ if (unlikely(!user_mode(regs))) return 0;
flush_spe_to_thread(current);
/* If we are loading, get the data from user space, else * get it from register values
*/ if (flags & ST) {
data.ll = 0; switch (instr) { case EVSTDD: case EVSTDW: case EVSTDH:
data.w[0] = *evr;
data.w[1] = regs->gpr[reg]; break; case EVSTWHE:
data.h[2] = *evr >> 16;
data.h[3] = regs->gpr[reg] >> 16; break; case EVSTWHO:
data.h[2] = *evr & 0xffff;
data.h[3] = regs->gpr[reg] & 0xffff; break; case EVSTWWE:
data.w[1] = *evr; break; case EVSTWWO:
data.w[1] = regs->gpr[reg]; break; default: return -EINVAL;
}
} else {
temp.ll = data.ll = 0;
p = addr;
if (!user_read_access_begin(addr, nb)) return -EFAULT;
/* * Called on alignment exception. Attempts to fixup * * Return 1 on success * Return 0 if unable to handle the interrupt * Return -EFAULT if data address is bad * Other negative return values indicate that the instruction can't * be emulated, and the process should be given a SIGBUS.
*/
int fix_alignment(struct pt_regs *regs)
{
ppc_inst_t instr; struct instruction_op op; int r, type;
if (is_kernel_addr(regs->nip))
r = copy_inst_from_kernel_nofault(&instr, (void *)regs->nip); else
r = __get_user_instr(instr, (void __user *)regs->nip);
if (unlikely(r)) return -EFAULT; if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) { /* We don't handle PPC little-endian any more... */ if (cpu_has_feature(CPU_FTR_PPC_LE)) return -EIO;
instr = ppc_inst_swab(instr);
}
/* * ISA 3.0 (such as P9) copy, copy_first, paste and paste_last alignment * check. * * Send a SIGBUS to the process that caused the fault. * * We do not emulate these because paste may contain additional metadata * when pasting to a co-processor. Furthermore, paste_last is the * synchronisation point for preceding copy/paste sequences.
*/ if ((ppc_inst_val(instr) & 0xfc0006fe) == (PPC_INST_COPY & 0xfc0006fe)) return -EIO;
r = analyse_instr(&op, regs, instr); if (r < 0) return -EINVAL;
type = GETTYPE(op.type); if (!OP_IS_LOAD_STORE(type)) { if (op.type != CACHEOP + DCBZ) return -EINVAL;
PPC_WARN_ALIGNMENT(dcbz, regs);
WARN_ON_ONCE(!user_mode(regs));
r = emulate_dcbz(op.ea, regs);
} else { if (type == LARX || type == STCX) return -EIO;
PPC_WARN_ALIGNMENT(unaligned, regs);
r = emulate_loadstore(regs, &op);
}
if (!r) return 1; return r;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
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.