Skip to content

Commit

Permalink
MIPS: OCTEON: Enable use of FPU
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David Daney authored and Ralf Baechle committed May 30, 2014
1 parent dadaa1c commit a36d822
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#define cpu_has_3k_cache 0
#define cpu_has_4k_cache 0
#define cpu_has_tx39_cache 0
#define cpu_has_fpu 0
#define cpu_has_counter 1
#define cpu_has_watch 1
#define cpu_has_divec 1
Expand Down
2 changes: 1 addition & 1 deletion arch/mips/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ obj-$(CONFIG_CPU_R4K_FPU) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
obj-$(CONFIG_CPU_CAVIUM_OCTEON) += octeon_switch.o
obj-$(CONFIG_CPU_CAVIUM_OCTEON) += r4k_fpu.o octeon_switch.o

obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SMP_UP) += smp-up.o
Expand Down
6 changes: 5 additions & 1 deletion arch/mips/kernel/branch.c
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
case cop1_op:
preempt_disable();
if (is_fpu_owner())
asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
asm volatile(
".set push\n"
"\t.set mips1\n"
"\tcfc1\t%0,$31\n"
"\t.set pop" : "=r" (fcr31));
else
fcr31 = current->thread.fpu.fcr31;
preempt_enable();
Expand Down
84 changes: 61 additions & 23 deletions arch/mips/kernel/octeon_switch.S
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,12 @@
* Copyright (C) 2000 MIPS Technologies, Inc.
* written by Carsten Langgaard, carstenl@mips.com
*/
#include <asm/asm.h>
#include <asm/cachectl.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
#include <asm/asm-offsets.h>
#include <asm/pgtable-bits.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
#include <asm/thread_info.h>

#include <asm/asmmacro.h>

/*
* Offset to the current process status flags, the first 32 bytes of the
* stack are not used.
*/
#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)

#define USE_ALTERNATE_RESUME_IMPL 1
.set push
.set arch=mips64r2
#include "r4k_switch.S"
.set pop
/*
* task_struct *resume(task_struct *prev, task_struct *next,
* struct thread_info *next_ti, int usedfpu)
Expand All @@ -40,6 +28,61 @@
cpu_save_nonscratch a0
LONG_S ra, THREAD_REG31(a0)

/*
* check if we need to save FPU registers
*/
PTR_L t3, TASK_THREAD_INFO(a0)
LONG_L t0, TI_FLAGS(t3)
li t1, _TIF_USEDFPU
and t2, t0, t1
beqz t2, 1f
nor t1, zero, t1

and t0, t0, t1
LONG_S t0, TI_FLAGS(t3)

/*
* clear saved user stack CU1 bit
*/
LONG_L t0, ST_OFF(t3)
li t1, ~ST0_CU1
and t0, t0, t1
LONG_S t0, ST_OFF(t3)

.set push
.set arch=mips64r2
fpu_save_double a0 t0 t1 # c0_status passed in t0
# clobbers t1
.set pop
1:

/* check if we need to save COP2 registers */
PTR_L t2, TASK_THREAD_INFO(a0)
LONG_L t0, ST_OFF(t2)
bbit0 t0, 30, 1f

/* Disable COP2 in the stored process state */
li t1, ST0_CU2
xor t0, t1
LONG_S t0, ST_OFF(t2)

/* Enable COP2 so we can save it */
mfc0 t0, CP0_STATUS
or t0, t1
mtc0 t0, CP0_STATUS

/* Save COP2 */
daddu a0, THREAD_CP2
jal octeon_cop2_save
dsubu a0, THREAD_CP2

/* Disable COP2 now that we are done */
mfc0 t0, CP0_STATUS
li t1, ST0_CU2
xor t0, t1
mtc0 t0, CP0_STATUS

1:
#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
/* Check if we need to store CVMSEG state */
mfc0 t0, $11,7 /* CvmMemCtl */
Expand Down Expand Up @@ -85,12 +128,7 @@
move $28, a2
cpu_restore_nonscratch a1

#if (_THREAD_SIZE - 32) < 0x8000
PTR_ADDIU t0, $28, _THREAD_SIZE - 32
#else
PTR_LI t0, _THREAD_SIZE - 32
PTR_ADDU t0, $28
#endif
PTR_ADDU t0, $28, _THREAD_SIZE - 32
set_saved_sp t0, t1, t2

mfc0 t1, CP0_STATUS /* Do we really need this? */
Expand Down
3 changes: 3 additions & 0 deletions arch/mips/kernel/r4k_switch.S
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
*/
#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)

#ifndef USE_ALTERNATE_RESUME_IMPL
/*
* task_struct *resume(task_struct *prev, task_struct *next,
* struct thread_info *next_ti, s32 fp_save)
Expand Down Expand Up @@ -99,6 +100,8 @@
jr ra
END(resume)

#endif /* USE_ALTERNATE_RESUME_IMPL */

/*
* Save a thread's fp context.
*/
Expand Down
6 changes: 5 additions & 1 deletion arch/mips/math-emu/cp1emu.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
if (insn.i_format.rs == bc_op) {
preempt_disable();
if (is_fpu_owner())
asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
asm volatile(
".set push\n"
"\t.set mips1\n"
"\tcfc1\t%0,$31\n"
"\t.set pop" : "=r" (fcr31));
else
fcr31 = current->thread.fpu.fcr31;
preempt_enable();
Expand Down

0 comments on commit a36d822

Please sign in to comment.