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

MIPS: Move cop2 save/restore to switch_to()

Move the common code for saving and restoring platform specific COP2
registers to switch_to(). This will make supporting new platforms (like
Netlogic XLP) easier.

The platform specific COP2 definitions are to be specified in
asm/processor.h and in asm/cop2.h.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Cc: linux-mips@linux-mips.org
Cc: ddaney.cavm@gmail.com
Patchwork: https://patchwork.linux-mips.org/patch/5411/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Jayachandran C and committed by
Ralf Baechle
2c952e06 79f8511c

+44 -39
+19
arch/mips/include/asm/cop2.h
··· 11 11 12 12 #include <linux/notifier.h> 13 13 14 + #if defined(CONFIG_CPU_CAVIUM_OCTEON) 15 + 16 + extern void octeon_cop2_save(struct octeon_cop2_state *); 17 + extern void octeon_cop2_restore(struct octeon_cop2_state *); 18 + 19 + #define cop2_save(r) octeon_cop2_save(r) 20 + #define cop2_restore(r) octeon_cop2_restore(r) 21 + 22 + #define cop2_present 1 23 + #define cop2_lazy_restore 1 24 + 25 + #else 26 + 27 + #define cop2_present 0 28 + #define cop2_lazy_restore 0 29 + #define cop2_save(r) 30 + #define cop2_restore(r) 31 + #endif 32 + 14 33 enum cu2_ops { 15 34 CU2_EXCEPTION, 16 35 CU2_LWC2_OP,
+7 -11
arch/mips/include/asm/processor.h
··· 137 137 struct mips3264_watch_reg_state mips3264; 138 138 }; 139 139 140 - #ifdef CONFIG_CPU_CAVIUM_OCTEON 140 + #if defined(CONFIG_CPU_CAVIUM_OCTEON) 141 141 142 142 struct octeon_cop2_state { 143 143 /* DMFC2 rt, 0x0201 */ ··· 182 182 /* DMFC2 rt, 0x025A; DMFC2 rt, 0x025B - Pass2 */ 183 183 unsigned long cop2_gfm_result[2]; 184 184 }; 185 - #define INIT_OCTEON_COP2 {0,} 185 + #define COP2_INIT \ 186 + .cp2 = {0,}, 186 187 187 188 struct octeon_cvmseg_state { 188 189 unsigned long cvmseg[CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE] 189 190 [cpu_dcache_line_size() / sizeof(unsigned long)]; 190 191 }; 191 192 193 + #else 194 + #define COP2_INIT 192 195 #endif 193 196 194 197 typedef struct { ··· 248 245 #define FPAFF_INIT 249 246 #endif /* CONFIG_MIPS_MT_FPAFF */ 250 247 251 - #ifdef CONFIG_CPU_CAVIUM_OCTEON 252 - #define OCTEON_INIT \ 253 - .cp2 = INIT_OCTEON_COP2, 254 - #else 255 - #define OCTEON_INIT 256 - #endif /* CONFIG_CPU_CAVIUM_OCTEON */ 257 - 258 248 #define INIT_THREAD { \ 259 249 /* \ 260 250 * Saved main processor registers \ ··· 296 300 .cp0_baduaddr = 0, \ 297 301 .error_code = 0, \ 298 302 /* \ 299 - * Cavium Octeon specifics (null if not Octeon) \ 303 + * Platform specific cop2 registers(null if no COP2) \ 300 304 */ \ 301 - OCTEON_INIT \ 305 + COP2_INIT \ 302 306 } 303 307 304 308 struct task_struct;
+18 -1
arch/mips/include/asm/switch_to.h
··· 15 15 #include <asm/cpu-features.h> 16 16 #include <asm/watch.h> 17 17 #include <asm/dsp.h> 18 + #include <asm/cop2.h> 18 19 19 20 struct task_struct; 20 21 ··· 67 66 68 67 #define switch_to(prev, next, last) \ 69 68 do { \ 70 - u32 __usedfpu; \ 69 + u32 __usedfpu, __c0_stat; \ 71 70 __mips_mt_fpaff_switch_to(prev); \ 72 71 if (cpu_has_dsp) \ 73 72 __save_dsp(prev); \ 73 + if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) { \ 74 + if (cop2_lazy_restore) \ 75 + KSTK_STATUS(prev) &= ~ST0_CU2; \ 76 + __c0_stat = read_c0_status(); \ 77 + write_c0_status(__c0_stat | ST0_CU2); \ 78 + cop2_save(&prev->thread.cp2); \ 79 + write_c0_status(__c0_stat & ~ST0_CU2); \ 80 + } \ 74 81 __clear_software_ll_bit(); \ 75 82 __usedfpu = test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU); \ 76 83 (last) = resume(prev, next, task_thread_info(next), __usedfpu); \ ··· 86 77 87 78 #define finish_arch_switch(prev) \ 88 79 do { \ 80 + u32 __c0_stat; \ 81 + if (cop2_present && !cop2_lazy_restore && \ 82 + (KSTK_STATUS(current) & ST0_CU2)) { \ 83 + __c0_stat = read_c0_status(); \ 84 + write_c0_status(__c0_stat | ST0_CU2); \ 85 + cop2_restore(&current->thread.cp2); \ 86 + write_c0_status(__c0_stat & ~ST0_CU2); \ 87 + } \ 89 88 if (cpu_has_dsp) \ 90 89 __restore_dsp(current); \ 91 90 if (cpu_has_userlocal) \
-27
arch/mips/kernel/octeon_switch.S
··· 40 40 cpu_save_nonscratch a0 41 41 LONG_S ra, THREAD_REG31(a0) 42 42 43 - /* check if we need to save COP2 registers */ 44 - PTR_L t2, TASK_THREAD_INFO(a0) 45 - LONG_L t0, ST_OFF(t2) 46 - bbit0 t0, 30, 1f 47 - 48 - /* Disable COP2 in the stored process state */ 49 - li t1, ST0_CU2 50 - xor t0, t1 51 - LONG_S t0, ST_OFF(t2) 52 - 53 - /* Enable COP2 so we can save it */ 54 - mfc0 t0, CP0_STATUS 55 - or t0, t1 56 - mtc0 t0, CP0_STATUS 57 - 58 - /* Save COP2 */ 59 - daddu a0, THREAD_CP2 60 - jal octeon_cop2_save 61 - dsubu a0, THREAD_CP2 62 - 63 - /* Disable COP2 now that we are done */ 64 - mfc0 t0, CP0_STATUS 65 - li t1, ST0_CU2 66 - xor t0, t1 67 - mtc0 t0, CP0_STATUS 68 - 69 - 1: 70 43 #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 71 44 /* Check if we need to store CVMSEG state */ 72 45 mfc0 t0, $11,7 /* CvmMemCtl */