mirror of https://github.com/torvalds/linux.git
Currently, installation of Debian 12.8 for mipsel fails on machines
without an FPU [1]. This is caused by the fact that zstd (which is used
for initramfs compression) executes the prefx instruction, which is not
emulated properly by the kernel.
The prefx (Prefetch Indexed) instruction fetches data from memory into
the cache without any side effects. Though functionally unrelated, it
requires an FPU [2].
Bytecode format of this instruction ends on "001111" binary:
(prefx instruction format) & 0x0000003f = 0x0000000f
The code in fpux_emu() runs like so:
#define MIPSInst(x) x
#define MIPSInst_FMA_FFMT(x) (MIPSInst(x) & 0x00000007)
#define MIPSInst_FUNC(x) (MIPSInst(x) & 0x0000003f)
enum cop1x_func { ..., pfetch_op = 0x0f, ... };
...
switch (MIPSInst_FMA_FFMT(ir)) {
...
case 0x3:
if (MIPSInst_FUNC(ir) != pfetch_op)
return SIGILL;
/* ignore prefx operation */
break;
default:
return SIGILL;
}
That snippet above contains a logic error and the
if (MIPSInst_FUNC(ir) != pfetch_op)
comparison always fires.
When MIPSInst_FUNC(ir) is equal to pfetch_op, ir must end on 001111
binary. In this case, MIPSInst_FMA_FFMT(ir) must be equal to 0x7, which
does not match that case label.
This causes emulation failure for the prefx instruction. Fix it.
This has been broken by
commit
|
||
|---|---|---|
| .. | ||
| Makefile | ||
| cp1emu.c | ||
| dp_2008class.c | ||
| dp_add.c | ||
| dp_cmp.c | ||
| dp_div.c | ||
| dp_fint.c | ||
| dp_flong.c | ||
| dp_fmax.c | ||
| dp_fmin.c | ||
| dp_fsp.c | ||
| dp_maddf.c | ||
| dp_mul.c | ||
| dp_rint.c | ||
| dp_simple.c | ||
| dp_sqrt.c | ||
| dp_sub.c | ||
| dp_tint.c | ||
| dp_tlong.c | ||
| dsemul.c | ||
| ieee754.c | ||
| ieee754.h | ||
| ieee754d.c | ||
| ieee754dp.c | ||
| ieee754dp.h | ||
| ieee754int.h | ||
| ieee754sp.c | ||
| ieee754sp.h | ||
| me-debugfs.c | ||
| sp_2008class.c | ||
| sp_add.c | ||
| sp_cmp.c | ||
| sp_div.c | ||
| sp_fdp.c | ||
| sp_fint.c | ||
| sp_flong.c | ||
| sp_fmax.c | ||
| sp_fmin.c | ||
| sp_maddf.c | ||
| sp_mul.c | ||
| sp_rint.c | ||
| sp_simple.c | ||
| sp_sqrt.c | ||
| sp_sub.c | ||
| sp_tint.c | ||
| sp_tlong.c | ||