Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[MIPS] Fix fpu_save_double on 64-bit.

> Without this fix, _save_fp() in 64-bit kernel is seriously broken.
>
> ffffffff8010bec0 <_save_fp>:
> ffffffff8010bec0: 400d6000 mfc0 t1,c0_status
> ffffffff8010bec4: 000c7140 sll t2,t0,0x5
> ffffffff8010bec8: 05c10011 bgez t2,ffffffff8010bf10 <_save_fp+0x50>
> ffffffff8010becc: 00000000 nop
> ffffffff8010bed0: f4810328 sdc1 $f1,808(a0)
> ...

Fix register usage in fpu_save_double() and make fpu_restore_double()
more symmetric with fpu_save_double().

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Atsushi Nemoto and committed by
Ralf Baechle
c138e12f 73499682

+19 -17
+8 -5
arch/mips/kernel/r4k_switch.S
··· 75 75 and t0, t0, t1 76 76 LONG_S t0, ST_OFF(t3) 77 77 78 - fpu_save_double a0 t1 t0 t2 # c0_status passed in t1 79 - # clobbers t0 and t2 78 + fpu_save_double a0 t0 t1 # c0_status passed in t0 79 + # clobbers t1 80 80 1: 81 81 82 82 /* ··· 129 129 */ 130 130 LEAF(_save_fp) 131 131 #ifdef CONFIG_64BIT 132 - mfc0 t1, CP0_STATUS 132 + mfc0 t0, CP0_STATUS 133 133 #endif 134 - fpu_save_double a0 t1 t0 t2 # clobbers t1 134 + fpu_save_double a0 t0 t1 # clobbers t1 135 135 jr ra 136 136 END(_save_fp) 137 137 ··· 139 139 * Restore a thread's fp context. 140 140 */ 141 141 LEAF(_restore_fp) 142 - fpu_restore_double a0, t1 # clobbers t1 142 + #ifdef CONFIG_64BIT 143 + mfc0 t0, CP0_STATUS 144 + #endif 145 + fpu_restore_double a0 t0 t1 # clobbers t1 143 146 jr ra 144 147 END(_restore_fp) 145 148
+2 -2
include/asm-mips/asmmacro-32.h
··· 12 12 #include <asm/fpregdef.h> 13 13 #include <asm/mipsregs.h> 14 14 15 - .macro fpu_save_double thread status tmp1=t0 tmp2 15 + .macro fpu_save_double thread status tmp1=t0 16 16 cfc1 \tmp1, fcr31 17 17 sdc1 $f0, THREAD_FPR0(\thread) 18 18 sdc1 $f2, THREAD_FPR2(\thread) ··· 70 70 sw \tmp, THREAD_FCR31(\thread) 71 71 .endm 72 72 73 - .macro fpu_restore_double thread tmp=t0 73 + .macro fpu_restore_double thread status tmp=t0 74 74 lw \tmp, THREAD_FCR31(\thread) 75 75 ldc1 $f0, THREAD_FPR0(\thread) 76 76 ldc1 $f2, THREAD_FPR2(\thread)
+9 -10
include/asm-mips/asmmacro-64.h
··· 53 53 sdc1 $f31, THREAD_FPR31(\thread) 54 54 .endm 55 55 56 - .macro fpu_save_double thread status tmp1 tmp2 57 - sll \tmp2, \tmp1, 5 58 - bgez \tmp2, 2f 56 + .macro fpu_save_double thread status tmp 57 + sll \tmp, \status, 5 58 + bgez \tmp, 2f 59 59 fpu_save_16odd \thread 60 60 2: 61 - fpu_save_16even \thread \tmp1 # clobbers t1 61 + fpu_save_16even \thread \tmp 62 62 .endm 63 63 64 64 .macro fpu_restore_16even thread tmp=t0 ··· 101 101 ldc1 $f31, THREAD_FPR31(\thread) 102 102 .endm 103 103 104 - .macro fpu_restore_double thread tmp 105 - mfc0 t0, CP0_STATUS 106 - sll t1, t0, 5 107 - bgez t1, 1f # 16 register mode? 104 + .macro fpu_restore_double thread status tmp 105 + sll \tmp, \status, 5 106 + bgez \tmp, 1f # 16 register mode? 108 107 109 - fpu_restore_16odd a0 110 - 1: fpu_restore_16even a0, t0 # clobbers t0 108 + fpu_restore_16odd \thread 109 + 1: fpu_restore_16even \thread \tmp 111 110 .endm 112 111 113 112 .macro cpu_save_nonscratch thread