switch (insn.i_format.opcode) { /* *Theseareinstructionsthatacompilerdoesn'tgenerate.We *canassumethereforethatthecodeisMIPS-awareand *reallybuggy.Emulatingtheseinstructionswouldbreakthe *semanticsanyway.
*/ case ll_op: case lld_op: case sc_op: case scd_op:
/* *Fortheseinstructionstheonlywaytocreateanaddress *errorisanattemptedaccesstokernel/supervisoraddress *space.
*/ case ldl_op: case ldr_op: case lwl_op: case lwr_op: case sdl_op: case sdr_op: case swl_op: case swr_op: case lb_op: case lbu_op: case sb_op: goto sigbus;
/* *Theremainingopcodesaretheonesthatarereallyof *interest.
*/ #ifdef CONFIG_MACH_INGENIC case spec2_op: if (insn.mxu_lx_format.func != mxu_lx_op) goto sigbus; /* other MXU instructions we don't care */
switch (insn.mxu_lx_format.op) { case mxu_lxw_op: if (user && !access_ok(addr, 4)) goto sigbus;
LoadW(addr, value, res); if (res) goto fault;
compute_return_epc(regs);
regs->regs[insn.mxu_lx_format.rd] = value; break; case mxu_lxh_op: if (user && !access_ok(addr, 2)) goto sigbus;
LoadHW(addr, value, res); if (res) goto fault;
compute_return_epc(regs);
regs->regs[insn.dsp_format.rd] = value; break; case mxu_lxhu_op: if (user && !access_ok(addr, 2)) goto sigbus;
LoadHWU(addr, value, res); if (res) goto fault;
compute_return_epc(regs);
regs->regs[insn.dsp_format.rd] = value; break; case mxu_lxb_op: case mxu_lxbu_op: goto sigbus; default: goto sigill;
} break; #endif case spec3_op: if (insn.dsp_format.func == lx_op) { switch (insn.dsp_format.op) { case lwx_op: if (user && !access_ok(addr, 4)) goto sigbus;
LoadW(addr, value, res); if (res) goto fault;
compute_return_epc(regs);
regs->regs[insn.dsp_format.rd] = value; break; case lhx_op: if (user && !access_ok(addr, 2)) goto sigbus;
LoadHW(addr, value, res); if (res) goto fault;
compute_return_epc(regs);
regs->regs[insn.dsp_format.rd] = value; break; default: goto sigill;
}
} #ifdef CONFIG_EVA else { /* *wecanlandhereonlyfromkernelaccessinguser *memory,soweneedto"switch"theaddresslimitto *userspace,sothataddresscheckcanworkproperly.
*/ switch (insn.spec3_format.func) { case lhe_op: if (!access_ok(addr, 2)) goto sigbus;
LoadHWE(addr, value, res); if (res) goto fault;
compute_return_epc(regs);
regs->regs[insn.spec3_format.rt] = value; break; case lwe_op: if (!access_ok(addr, 4)) goto sigbus;
LoadWE(addr, value, res); if (res) goto fault;
compute_return_epc(regs);
regs->regs[insn.spec3_format.rt] = value; break; case lhue_op: if (!access_ok(addr, 2)) goto sigbus;
LoadHWUE(addr, value, res); if (res) goto fault;
compute_return_epc(regs);
regs->regs[insn.spec3_format.rt] = value; break; case she_op: if (!access_ok(addr, 2)) goto sigbus;
compute_return_epc(regs);
value = regs->regs[insn.spec3_format.rt];
StoreHWE(addr, value, res); if (res) goto fault; break; case swe_op: if (!access_ok(addr, 4)) goto sigbus;
compute_return_epc(regs);
value = regs->regs[insn.spec3_format.rt];
StoreWE(addr, value, res); if (res) goto fault; break; default: goto sigill;
}
} #endif break; case lh_op: if (user && !access_ok(addr, 2)) goto sigbus;
fault: /* roll back jump/branch */
regs->cp0_epc = origpc;
regs->regs[31] = orig31; /* Did we have an exception handler installed? */ if (fixup_exception(regs)) return;
case mm_sdp_func: #ifdef CONFIG_64BIT
reg = insn.mm_m_format.rd; if (reg == 31) goto sigbus;
if (user && !access_ok(addr, 16)) goto sigbus;
value = regs->regs[reg];
StoreDW(addr, value, res); if (res) goto fault;
addr += 8;
value = regs->regs[reg + 1];
StoreDW(addr, value, res); if (res) goto fault; goto success; #endif/* CONFIG_64BIT */
goto sigill;
case mm_lwm32_func:
reg = insn.mm_m_format.rd;
rvar = reg & 0xf; if ((rvar > 9) || !reg) goto sigill; if (reg & 0x10) { if (user && !access_ok(addr, 4 * (rvar + 1))) goto sigbus;
} else { if (user && !access_ok(addr, 4 * rvar)) goto sigbus;
} if (rvar == 9)
rvar = 8; for (i = 16; rvar; rvar--, i++) {
LoadW(addr, value, res); if (res) goto fault;
addr += 4;
regs->regs[i] = value;
} if ((reg & 0xf) == 9) {
LoadW(addr, value, res); if (res) goto fault;
addr += 4;
regs->regs[30] = value;
} if (reg & 0x10) {
LoadW(addr, value, res); if (res) goto fault;
regs->regs[31] = value;
} goto success;
case mm_swm32_func:
reg = insn.mm_m_format.rd;
rvar = reg & 0xf; if ((rvar > 9) || !reg) goto sigill; if (reg & 0x10) { if (user && !access_ok(addr, 4 * (rvar + 1))) goto sigbus;
} else { if (user && !access_ok(addr, 4 * rvar)) goto sigbus;
} if (rvar == 9)
rvar = 8; for (i = 16; rvar; rvar--, i++) {
value = regs->regs[i];
StoreW(addr, value, res); if (res) goto fault;
addr += 4;
} if ((reg & 0xf) == 9) {
value = regs->regs[30];
StoreW(addr, value, res); if (res) goto fault;
addr += 4;
} if (reg & 0x10) {
value = regs->regs[31];
StoreW(addr, value, res); if (res) goto fault;
} goto success;
case mm_ldm_func: #ifdef CONFIG_64BIT
reg = insn.mm_m_format.rd;
rvar = reg & 0xf; if ((rvar > 9) || !reg) goto sigill; if (reg & 0x10) { if (user && !access_ok(addr, 8 * (rvar + 1))) goto sigbus;
} else { if (user && !access_ok(addr, 8 * rvar)) goto sigbus;
} if (rvar == 9)
rvar = 8;
for (i = 16; rvar; rvar--, i++) {
LoadDW(addr, value, res); if (res) goto fault;
addr += 4;
regs->regs[i] = value;
} if ((reg & 0xf) == 9) {
LoadDW(addr, value, res); if (res) goto fault;
addr += 8;
regs->regs[30] = value;
} if (reg & 0x10) {
LoadDW(addr, value, res); if (res) goto fault;
regs->regs[31] = value;
} goto success; #endif/* CONFIG_64BIT */
goto sigill;
case mm_sdm_func: #ifdef CONFIG_64BIT
reg = insn.mm_m_format.rd;
rvar = reg & 0xf; if ((rvar > 9) || !reg) goto sigill; if (reg & 0x10) { if (user && !access_ok(addr, 8 * (rvar + 1))) goto sigbus;
} else { if (user && !access_ok(addr, 8 * rvar)) goto sigbus;
} if (rvar == 9)
rvar = 8;
for (i = 16; rvar; rvar--, i++) {
value = regs->regs[i];
StoreDW(addr, value, res); if (res) goto fault;
addr += 8;
} if ((reg & 0xf) == 9) {
value = regs->regs[30];
StoreDW(addr, value, res); if (res) goto fault;
addr += 8;
} if (reg & 0x10) {
value = regs->regs[31];
StoreDW(addr, value, res); if (res) goto fault;
} goto success; #endif/* CONFIG_64BIT */
goto sigill;
/* LWC2, SWC2, LDC2, SDC2 are not serviced */
}
goto sigbus;
case mm_pool32c_op: switch (insn.mm_m_format.func) { case mm_lwu_func:
reg = insn.mm_m_format.rd; goto loadWU;
}
/* LL,SC,LLD,SCD are not serviced */ goto sigbus;
#ifdef CONFIG_MIPS_FP_SUPPORT case mm_pool32f_op: switch (insn.mm_x_format.func) { case mm_lwxc1_func: case mm_swxc1_func: case mm_ldxc1_func: case mm_sdxc1_func: goto fpu_emul;
}
goto sigbus;
case mm_ldc132_op: case mm_sdc132_op: case mm_lwc132_op: case mm_swc132_op: { void __user *fault_addr = NULL;
fpu_emul: /* roll back jump/branch */
regs->cp0_epc = origpc;
regs->regs[31] = orig31;
die_if_kernel("Unaligned FP access in kernel code", regs);
BUG_ON(!used_math());
BUG_ON(!is_fpu_owner());
res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1,
&fault_addr);
own_fpu(1); /* restore FPU state */
/* If something went wrong, signal */
process_fpemu_return(res, fault_addr, 0);
fault: /* roll back jump/branch */
regs->cp0_epc = origpc;
regs->regs[31] = orig31; /* Did we have an exception handler installed? */ if (fixup_exception(regs)) return;
/* skip EXTEND instruction */ if (mips16inst.ri.opcode == MIPS16e_extend_op) {
extended = 1;
pc16++;
__get_user(mips16inst.full, pc16);
} elseif (delay_slot(regs)) { /* skip jump instructions */ /* JAL/JALX are 32 bits but have OPCODE in first short int */ if (mips16inst.ri.opcode == MIPS16e_jal_op)
pc16++;
pc16++; if (get_user(mips16inst.full, pc16)) goto sigbus;
}
opcode = mips16inst.ri.opcode; switch (opcode) { case MIPS16e_i64_op: /* I64 or RI64 instruction */ switch (mips16inst.i64.func) { /* I64/RI64 func field check */ case MIPS16e_ldpc_func: case MIPS16e_ldsp_func:
reg = reg16to32[mips16inst.ri64.ry]; goto loadDW;
case MIPS16e_sdsp_func:
reg = reg16to32[mips16inst.ri64.ry]; goto writeDW;
fault: /* roll back jump/branch */
regs->cp0_epc = origpc;
regs->regs[31] = orig31; /* Did we have an exception handler installed? */ if (fixup_exception(regs)) return;
¤ 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.0.131Bemerkung:
(vorverarbeitet am 2026-09-27)
¤
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.