aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJayachandran C <jchandra@broadcom.com>2013-06-10 02:30:00 -0400
committerRalf Baechle <ralf@linux-mips.org>2013-06-13 11:46:41 -0400
commit2c952e06e4f57716109b609956eda28c900faac0 (patch)
tree39dc9361773009cdcfdc1e0e1752b446259d7cef /arch
parent79f8511c83f13689913f54d2f189297c226ec064 (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.h19
-rw-r--r--arch/mips/include/asm/processor.h18
-rw-r--r--arch/mips/include/asm/switch_to.h19
-rw-r--r--arch/mips/kernel/octeon_switch.S27
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
16extern void octeon_cop2_save(struct octeon_cop2_state *);
17extern 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
14enum cu2_ops { 33enum 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
142struct octeon_cop2_state { 142struct 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
187struct octeon_cvmseg_state { 188struct 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
194typedef struct { 197typedef 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
308struct task_struct; 304struct 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
19struct task_struct; 20struct 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) \
68do { \ 69do { \
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) \
79do { \ 88do { \
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(&current->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
691:
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 */