diff options
author | David Daney <david.daney@cavium.com> | 2014-05-28 17:52:04 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-05-30 15:01:09 -0400 |
commit | a36d8225bceba4b7be47ade34d175945f85cffbc (patch) | |
tree | e410a514298003ab96d3a10cf091c518a8a423c8 | |
parent | dadaa1c2c0eddc09d11d7494b040c3f331ecd98f (diff) |
MIPS: OCTEON: Enable use of FPU
Some versions of the assembler will not assemble CFC1 for OCTEON, so
override the ISA for these.
Add r4k_fpu.o to handle low level FPU initialization.
Modify octeon_switch.S to save the FPU registers. And include
r4k_switch.S to pick up more FPU support.
Get rid of "#define cpu_has_fpu 0"
Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann@caviumnetworks.com>
Cc: linux-mips@linux-mips.org
Cc: James Hogan <james.hogan@imgtec.com>
Cc: kvm@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/7006/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h | 1 | ||||
-rw-r--r-- | arch/mips/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/kernel/branch.c | 6 | ||||
-rw-r--r-- | arch/mips/kernel/octeon_switch.S | 84 | ||||
-rw-r--r-- | arch/mips/kernel/r4k_switch.S | 3 | ||||
-rw-r--r-- | arch/mips/math-emu/cp1emu.c | 6 |
6 files changed, 75 insertions, 27 deletions
diff --git a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h index 94ed063eec92..cf8022872892 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h | |||
@@ -22,7 +22,6 @@ | |||
22 | #define cpu_has_3k_cache 0 | 22 | #define cpu_has_3k_cache 0 |
23 | #define cpu_has_4k_cache 0 | 23 | #define cpu_has_4k_cache 0 |
24 | #define cpu_has_tx39_cache 0 | 24 | #define cpu_has_tx39_cache 0 |
25 | #define cpu_has_fpu 0 | ||
26 | #define cpu_has_counter 1 | 25 | #define cpu_has_counter 1 |
27 | #define cpu_has_watch 1 | 26 | #define cpu_has_watch 1 |
28 | #define cpu_has_divec 1 | 27 | #define cpu_has_divec 1 |
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index a61d108f4c0e..008a2fed0584 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile | |||
@@ -41,7 +41,7 @@ obj-$(CONFIG_CPU_R4K_FPU) += r4k_fpu.o r4k_switch.o | |||
41 | obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o | 41 | obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o |
42 | obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o | 42 | obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o |
43 | obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o | 43 | obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o |
44 | obj-$(CONFIG_CPU_CAVIUM_OCTEON) += octeon_switch.o | 44 | obj-$(CONFIG_CPU_CAVIUM_OCTEON) += r4k_fpu.o octeon_switch.o |
45 | 45 | ||
46 | obj-$(CONFIG_SMP) += smp.o | 46 | obj-$(CONFIG_SMP) += smp.o |
47 | obj-$(CONFIG_SMP_UP) += smp-up.o | 47 | obj-$(CONFIG_SMP_UP) += smp-up.o |
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 84888d9332b9..e198d9bf17bb 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c | |||
@@ -562,7 +562,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, | |||
562 | case cop1_op: | 562 | case cop1_op: |
563 | preempt_disable(); | 563 | preempt_disable(); |
564 | if (is_fpu_owner()) | 564 | if (is_fpu_owner()) |
565 | asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); | 565 | asm volatile( |
566 | ".set push\n" | ||
567 | "\t.set mips1\n" | ||
568 | "\tcfc1\t%0,$31\n" | ||
569 | "\t.set pop" : "=r" (fcr31)); | ||
566 | else | 570 | else |
567 | fcr31 = current->thread.fpu.fcr31; | 571 | fcr31 = current->thread.fpu.fcr31; |
568 | preempt_enable(); | 572 | preempt_enable(); |
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S index 029e002a4ea0..f6547680c81c 100644 --- a/arch/mips/kernel/octeon_switch.S +++ b/arch/mips/kernel/octeon_switch.S | |||
@@ -10,24 +10,12 @@ | |||
10 | * Copyright (C) 2000 MIPS Technologies, Inc. | 10 | * Copyright (C) 2000 MIPS Technologies, Inc. |
11 | * written by Carsten Langgaard, carstenl@mips.com | 11 | * written by Carsten Langgaard, carstenl@mips.com |
12 | */ | 12 | */ |
13 | #include <asm/asm.h> | ||
14 | #include <asm/cachectl.h> | ||
15 | #include <asm/fpregdef.h> | ||
16 | #include <asm/mipsregs.h> | ||
17 | #include <asm/asm-offsets.h> | ||
18 | #include <asm/pgtable-bits.h> | ||
19 | #include <asm/regdef.h> | ||
20 | #include <asm/stackframe.h> | ||
21 | #include <asm/thread_info.h> | ||
22 | |||
23 | #include <asm/asmmacro.h> | ||
24 | |||
25 | /* | ||
26 | * Offset to the current process status flags, the first 32 bytes of the | ||
27 | * stack are not used. | ||
28 | */ | ||
29 | #define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) | ||
30 | 13 | ||
14 | #define USE_ALTERNATE_RESUME_IMPL 1 | ||
15 | .set push | ||
16 | .set arch=mips64r2 | ||
17 | #include "r4k_switch.S" | ||
18 | .set pop | ||
31 | /* | 19 | /* |
32 | * task_struct *resume(task_struct *prev, task_struct *next, | 20 | * task_struct *resume(task_struct *prev, task_struct *next, |
33 | * struct thread_info *next_ti, int usedfpu) | 21 | * struct thread_info *next_ti, int usedfpu) |
@@ -40,6 +28,61 @@ | |||
40 | cpu_save_nonscratch a0 | 28 | cpu_save_nonscratch a0 |
41 | LONG_S ra, THREAD_REG31(a0) | 29 | LONG_S ra, THREAD_REG31(a0) |
42 | 30 | ||
31 | /* | ||
32 | * check if we need to save FPU registers | ||
33 | */ | ||
34 | PTR_L t3, TASK_THREAD_INFO(a0) | ||
35 | LONG_L t0, TI_FLAGS(t3) | ||
36 | li t1, _TIF_USEDFPU | ||
37 | and t2, t0, t1 | ||
38 | beqz t2, 1f | ||
39 | nor t1, zero, t1 | ||
40 | |||
41 | and t0, t0, t1 | ||
42 | LONG_S t0, TI_FLAGS(t3) | ||
43 | |||
44 | /* | ||
45 | * clear saved user stack CU1 bit | ||
46 | */ | ||
47 | LONG_L t0, ST_OFF(t3) | ||
48 | li t1, ~ST0_CU1 | ||
49 | and t0, t0, t1 | ||
50 | LONG_S t0, ST_OFF(t3) | ||
51 | |||
52 | .set push | ||
53 | .set arch=mips64r2 | ||
54 | fpu_save_double a0 t0 t1 # c0_status passed in t0 | ||
55 | # clobbers t1 | ||
56 | .set pop | ||
57 | 1: | ||
58 | |||
59 | /* check if we need to save COP2 registers */ | ||
60 | PTR_L t2, TASK_THREAD_INFO(a0) | ||
61 | LONG_L t0, ST_OFF(t2) | ||
62 | bbit0 t0, 30, 1f | ||
63 | |||
64 | /* Disable COP2 in the stored process state */ | ||
65 | li t1, ST0_CU2 | ||
66 | xor t0, t1 | ||
67 | LONG_S t0, ST_OFF(t2) | ||
68 | |||
69 | /* Enable COP2 so we can save it */ | ||
70 | mfc0 t0, CP0_STATUS | ||
71 | or t0, t1 | ||
72 | mtc0 t0, CP0_STATUS | ||
73 | |||
74 | /* Save COP2 */ | ||
75 | daddu a0, THREAD_CP2 | ||
76 | jal octeon_cop2_save | ||
77 | dsubu a0, THREAD_CP2 | ||
78 | |||
79 | /* Disable COP2 now that we are done */ | ||
80 | mfc0 t0, CP0_STATUS | ||
81 | li t1, ST0_CU2 | ||
82 | xor t0, t1 | ||
83 | mtc0 t0, CP0_STATUS | ||
84 | |||
85 | 1: | ||
43 | #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 | 86 | #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 |
44 | /* Check if we need to store CVMSEG state */ | 87 | /* Check if we need to store CVMSEG state */ |
45 | mfc0 t0, $11,7 /* CvmMemCtl */ | 88 | mfc0 t0, $11,7 /* CvmMemCtl */ |
@@ -85,12 +128,7 @@ | |||
85 | move $28, a2 | 128 | move $28, a2 |
86 | cpu_restore_nonscratch a1 | 129 | cpu_restore_nonscratch a1 |
87 | 130 | ||
88 | #if (_THREAD_SIZE - 32) < 0x8000 | 131 | PTR_ADDU t0, $28, _THREAD_SIZE - 32 |
89 | PTR_ADDIU t0, $28, _THREAD_SIZE - 32 | ||
90 | #else | ||
91 | PTR_LI t0, _THREAD_SIZE - 32 | ||
92 | PTR_ADDU t0, $28 | ||
93 | #endif | ||
94 | set_saved_sp t0, t1, t2 | 132 | set_saved_sp t0, t1, t2 |
95 | 133 | ||
96 | mfc0 t1, CP0_STATUS /* Do we really need this? */ | 134 | mfc0 t1, CP0_STATUS /* Do we really need this? */ |
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 547c522964de..81ca3f70fe29 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S | |||
@@ -28,6 +28,7 @@ | |||
28 | */ | 28 | */ |
29 | #define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) | 29 | #define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) |
30 | 30 | ||
31 | #ifndef USE_ALTERNATE_RESUME_IMPL | ||
31 | /* | 32 | /* |
32 | * task_struct *resume(task_struct *prev, task_struct *next, | 33 | * task_struct *resume(task_struct *prev, task_struct *next, |
33 | * struct thread_info *next_ti, s32 fp_save) | 34 | * struct thread_info *next_ti, s32 fp_save) |
@@ -99,6 +100,8 @@ | |||
99 | jr ra | 100 | jr ra |
100 | END(resume) | 101 | END(resume) |
101 | 102 | ||
103 | #endif /* USE_ALTERNATE_RESUME_IMPL */ | ||
104 | |||
102 | /* | 105 | /* |
103 | * Save a thread's fp context. | 106 | * Save a thread's fp context. |
104 | */ | 107 | */ |
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index cdfed285c244..736c17a226e9 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c | |||
@@ -584,7 +584,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, | |||
584 | if (insn.i_format.rs == bc_op) { | 584 | if (insn.i_format.rs == bc_op) { |
585 | preempt_disable(); | 585 | preempt_disable(); |
586 | if (is_fpu_owner()) | 586 | if (is_fpu_owner()) |
587 | asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); | 587 | asm volatile( |
588 | ".set push\n" | ||
589 | "\t.set mips1\n" | ||
590 | "\tcfc1\t%0,$31\n" | ||
591 | "\t.set pop" : "=r" (fcr31)); | ||
588 | else | 592 | else |
589 | fcr31 = current->thread.fpu.fcr31; | 593 | fcr31 = current->thread.fpu.fcr31; |
590 | preempt_enable(); | 594 | preempt_enable(); |