diff options
author | Jayachandran C <jchandra@broadcom.com> | 2013-06-10 02:30:00 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2013-06-13 11:46:41 -0400 |
commit | 2c952e06e4f57716109b609956eda28c900faac0 (patch) | |
tree | 39dc9361773009cdcfdc1e0e1752b446259d7cef /arch | |
parent | 79f8511c83f13689913f54d2f189297c226ec064 (diff) |
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/include/asm/cop2.h | 19 | ||||
-rw-r--r-- | arch/mips/include/asm/processor.h | 18 | ||||
-rw-r--r-- | arch/mips/include/asm/switch_to.h | 19 | ||||
-rw-r--r-- | arch/mips/kernel/octeon_switch.S | 27 |
4 files changed, 44 insertions, 39 deletions
diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h index 3532e2c5f098..b17f38ee1ed4 100644 --- a/arch/mips/include/asm/cop2.h +++ b/arch/mips/include/asm/cop2.h | |||
@@ -11,6 +11,25 @@ | |||
11 | 11 | ||
12 | #include <linux/notifier.h> | 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 | enum cu2_ops { | 33 | enum cu2_ops { |
15 | CU2_EXCEPTION, | 34 | CU2_EXCEPTION, |
16 | CU2_LWC2_OP, | 35 | CU2_LWC2_OP, |
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 1470b7b68b0e..7c637a461ced 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h | |||
@@ -137,7 +137,7 @@ union mips_watch_reg_state { | |||
137 | struct mips3264_watch_reg_state mips3264; | 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 | struct octeon_cop2_state { | 142 | struct octeon_cop2_state { |
143 | /* DMFC2 rt, 0x0201 */ | 143 | /* DMFC2 rt, 0x0201 */ |
@@ -182,13 +182,16 @@ struct octeon_cop2_state { | |||
182 | /* DMFC2 rt, 0x025A; DMFC2 rt, 0x025B - Pass2 */ | 182 | /* DMFC2 rt, 0x025A; DMFC2 rt, 0x025B - Pass2 */ |
183 | unsigned long cop2_gfm_result[2]; | 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 | struct octeon_cvmseg_state { | 188 | struct octeon_cvmseg_state { |
188 | unsigned long cvmseg[CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE] | 189 | unsigned long cvmseg[CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE] |
189 | [cpu_dcache_line_size() / sizeof(unsigned long)]; | 190 | [cpu_dcache_line_size() / sizeof(unsigned long)]; |
190 | }; | 191 | }; |
191 | 192 | ||
193 | #else | ||
194 | #define COP2_INIT | ||
192 | #endif | 195 | #endif |
193 | 196 | ||
194 | typedef struct { | 197 | typedef struct { |
@@ -245,13 +248,6 @@ struct thread_struct { | |||
245 | #define FPAFF_INIT | 248 | #define FPAFF_INIT |
246 | #endif /* CONFIG_MIPS_MT_FPAFF */ | 249 | #endif /* CONFIG_MIPS_MT_FPAFF */ |
247 | 250 | ||
248 | #ifdef CONFIG_CPU_CAVIUM_OCTEON | ||
249 | #define OCTEON_INIT \ | ||
250 | .cp2 = INIT_OCTEON_COP2, | ||
251 | #else | ||
252 | #define OCTEON_INIT | ||
253 | #endif /* CONFIG_CPU_CAVIUM_OCTEON */ | ||
254 | |||
255 | #define INIT_THREAD { \ | 251 | #define INIT_THREAD { \ |
256 | /* \ | 252 | /* \ |
257 | * Saved main processor registers \ | 253 | * Saved main processor registers \ |
@@ -300,9 +296,9 @@ struct thread_struct { | |||
300 | .cp0_baduaddr = 0, \ | 296 | .cp0_baduaddr = 0, \ |
301 | .error_code = 0, \ | 297 | .error_code = 0, \ |
302 | /* \ | 298 | /* \ |
303 | * Cavium Octeon specifics (null if not Octeon) \ | 299 | * Platform specific cop2 registers(null if no COP2) \ |
304 | */ \ | 300 | */ \ |
305 | OCTEON_INIT \ | 301 | COP2_INIT \ |
306 | } | 302 | } |
307 | 303 | ||
308 | struct task_struct; | 304 | struct task_struct; |
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h index fd16bcb6c311..eb0af15ac656 100644 --- a/arch/mips/include/asm/switch_to.h +++ b/arch/mips/include/asm/switch_to.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <asm/cpu-features.h> | 15 | #include <asm/cpu-features.h> |
16 | #include <asm/watch.h> | 16 | #include <asm/watch.h> |
17 | #include <asm/dsp.h> | 17 | #include <asm/dsp.h> |
18 | #include <asm/cop2.h> | ||
18 | 19 | ||
19 | struct task_struct; | 20 | struct task_struct; |
20 | 21 | ||
@@ -66,10 +67,18 @@ do { \ | |||
66 | 67 | ||
67 | #define switch_to(prev, next, last) \ | 68 | #define switch_to(prev, next, last) \ |
68 | do { \ | 69 | do { \ |
69 | u32 __usedfpu; \ | 70 | u32 __usedfpu, __c0_stat; \ |
70 | __mips_mt_fpaff_switch_to(prev); \ | 71 | __mips_mt_fpaff_switch_to(prev); \ |
71 | if (cpu_has_dsp) \ | 72 | if (cpu_has_dsp) \ |
72 | __save_dsp(prev); \ | 73 | __save_dsp(prev); \ |
74 | if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) { \ | ||
75 | if (cop2_lazy_restore) \ | ||
76 | KSTK_STATUS(prev) &= ~ST0_CU2; \ | ||
77 | __c0_stat = read_c0_status(); \ | ||
78 | write_c0_status(__c0_stat | ST0_CU2); \ | ||
79 | cop2_save(&prev->thread.cp2); \ | ||
80 | write_c0_status(__c0_stat & ~ST0_CU2); \ | ||
81 | } \ | ||
73 | __clear_software_ll_bit(); \ | 82 | __clear_software_ll_bit(); \ |
74 | __usedfpu = test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU); \ | 83 | __usedfpu = test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU); \ |
75 | (last) = resume(prev, next, task_thread_info(next), __usedfpu); \ | 84 | (last) = resume(prev, next, task_thread_info(next), __usedfpu); \ |
@@ -77,6 +86,14 @@ do { \ | |||
77 | 86 | ||
78 | #define finish_arch_switch(prev) \ | 87 | #define finish_arch_switch(prev) \ |
79 | do { \ | 88 | do { \ |
89 | u32 __c0_stat; \ | ||
90 | if (cop2_present && !cop2_lazy_restore && \ | ||
91 | (KSTK_STATUS(current) & ST0_CU2)) { \ | ||
92 | __c0_stat = read_c0_status(); \ | ||
93 | write_c0_status(__c0_stat | ST0_CU2); \ | ||
94 | cop2_restore(¤t->thread.cp2); \ | ||
95 | write_c0_status(__c0_stat & ~ST0_CU2); \ | ||
96 | } \ | ||
80 | if (cpu_has_dsp) \ | 97 | if (cpu_has_dsp) \ |
81 | __restore_dsp(current); \ | 98 | __restore_dsp(current); \ |
82 | if (cpu_has_userlocal) \ | 99 | if (cpu_has_userlocal) \ |
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S index 0e23343eb0a9..22e2aa1e8d37 100644 --- a/arch/mips/kernel/octeon_switch.S +++ b/arch/mips/kernel/octeon_switch.S | |||
@@ -40,33 +40,6 @@ | |||
40 | cpu_save_nonscratch a0 | 40 | cpu_save_nonscratch a0 |
41 | LONG_S ra, THREAD_REG31(a0) | 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 | #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 | 43 | #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 |
71 | /* Check if we need to store CVMSEG state */ | 44 | /* Check if we need to store CVMSEG state */ |
72 | mfc0 t0, $11,7 /* CvmMemCtl */ | 45 | mfc0 t0, $11,7 /* CvmMemCtl */ |