aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Daney <david.daney@cavium.com>2014-05-28 17:52:04 -0400
committerRalf Baechle <ralf@linux-mips.org>2014-05-30 15:01:09 -0400
commita36d8225bceba4b7be47ade34d175945f85cffbc (patch)
treee410a514298003ab96d3a10cf091c518a8a423c8
parentdadaa1c2c0eddc09d11d7494b040c3f331ecd98f (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.h1
-rw-r--r--arch/mips/kernel/Makefile2
-rw-r--r--arch/mips/kernel/branch.c6
-rw-r--r--arch/mips/kernel/octeon_switch.S84
-rw-r--r--arch/mips/kernel/r4k_switch.S3
-rw-r--r--arch/mips/math-emu/cp1emu.c6
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
41obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o 41obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
42obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o 42obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
43obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o 43obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
44obj-$(CONFIG_CPU_CAVIUM_OCTEON) += octeon_switch.o 44obj-$(CONFIG_CPU_CAVIUM_OCTEON) += r4k_fpu.o octeon_switch.o
45 45
46obj-$(CONFIG_SMP) += smp.o 46obj-$(CONFIG_SMP) += smp.o
47obj-$(CONFIG_SMP_UP) += smp-up.o 47obj-$(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
571:
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
851:
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();