• Bug#1091858: [PATCH] mips/math-emu: fix emulation of the prefx instruct

    From =?UTF-8?q?Mateusz=20Jo=C5=84czyk?=@21:1/5 to All on Fri Jan 3 21:50:01 2025
    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].

    (prefx instruction format) & 0x0000003f = 0x0000000f

    The code 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 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.

    Signed-off-by: Mateusz Jończyk <mat.jonczyk@o2.pl>
    Cc: stable@vger.kernel.org # after 2 weeks
    Cc: Dengcheng Zhu <dzhu@wavecomp.com>
    Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
    Fixes: 51061b8876a3 ("MIPS: math-emu: Fix prefx detection and COP1X function field definition")

    [1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1091858
    [2] MIPS Architecture For Programmers Volume II-A: The MIPS32 Instruction Set Link: https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00086-2B-MIPS32BIS-AFP-05.04.pdf
    ---
    arch/mips/math-emu/cp1emu.c | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)

    diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
    index 265bc57819df..c89e70df43d8 100644
    --- a/arch/mips/math-emu/cp1emu.c
    +++ b/arch/mips/math-emu/cp1emu.c
    @@ -1660,7 +1660,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
    break;
    }

    - case 0x3:
    + case 0x7:
    if (MIPSInst_FUNC(ir) != pfetch_op)
    return SIGILL;

    --
    2.25.1

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)