• Paul Burton's avatar
    MIPS: Fix pre-r6 emulation FPU initialisation · 18720392
    Paul Burton authored
    commit 7e956304 upstream.
    
    In the mipsr2_decoder() function, used to emulate pre-MIPSr6
    instructions that were removed in MIPSr6, the init_fpu() function is
    called if a removed pre-MIPSr6 floating point instruction is the first
    floating point instruction used by the task. However, init_fpu()
    performs varous actions that rely upon not being migrated. For example
    in the most basic case it sets the coprocessor 0 Status.CU1 bit to
    enable the FPU & then loads FP register context into the FPU registers.
    If the task were to migrate during this time, it may end up attempting
    to load FP register context on a different CPU where it hasn't set the
    CU1 bit, leading to errors such as:
    
        do_cpu invoked from kernel context![#2]:
        CPU: 2 PID: 7338 Comm: fp-prctl Tainted: G      D         4.7.0-00424-g49b0c82 #2
        task: 838e4000 ti: 88d38000 task.ti: 88d38000
        $ 0   : 00000000 00000001 ffffffff 88d3fef8
        $ 4   : 838e4000 88d38004 00000000 00000001
        $ 8   : 3400fc01 801f8020 808e9100 24000000
        $12   : dbffffff 807b69d8 807b0000 00000000
        $16   : 00000000 80786150 00400fc4 809c0398
        $20   : 809c0338 0040273c 88d3ff28 808e9d30
        $24   : 808e9d30 00400fb4
        $28   : 88d38000 88d3fe88 00000000 8011a2ac
        Hi    : 0040273c
        Lo    : 88d3ff28
        epc   : 80114178 _restore_fp+0x10/0xa0
        ra    : 8011a2ac mipsr2_decoder+0xd5c/0x1660
        Status: 1400fc03	KERNEL EXL IE
        Cause : 1080002c (ExcCode 0b)
        PrId  : 0001a920 (MIPS I6400)
        Modules linked in:
        Process fp-prctl (pid: 7338, threadinfo=88d38000, task=838e4000, tls=766527d0)
        Stack : 00000000 00000000 00000000 88d3fe98 00000000 00000000 809c0398 809c0338
        	  808e9100 00000000 88d3ff28 00400fc4 00400fc4 0040273c 7fb69e18 004a0000
        	  004a0000 004a0000 7664add0 8010de18 00000000 00000000 88d3fef8 88d3ff28
        	  808e9100 00000000 766527d0 8010e534 000c0000 85755000 8181d580 00000000
        	  00000000 00000000 004a0000 00000000 766527d0 7fb69e18 004a0000 80105c20
        	  ...
        Call Trace:
        [<80114178>] _restore_fp+0x10/0xa0
        [<8011a2ac>] mipsr2_decoder+0xd5c/0x1660
        [<8010de18>] do_ri+0x90/0x6b8
        [<80105c20>] ret_from_exception+0x0/0x10
    
    Fix this by disabling preemption around the call to init_fpu(), ensuring
    that it starts & completes on one CPU.
    Signed-off-by: default avatarPaul Burton <paul.burton@imgtec.com>
    Fixes: b0a668fb ("MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6")
    Cc: linux-mips@linux-mips.org
    Patchwork: https://patchwork.linux-mips.org/patch/14305/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    18720392
mips-r2-to-r6-emul.c 54.8 KB