Commit a36d8225 authored by David Daney's avatar David Daney Committed by Ralf Baechle

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: default avatarDavid Daney <david.daney@cavium.com>
Signed-off-by: default avatarAndreas 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: default avatarRalf Baechle <ralf@linux-mips.org>
parent dadaa1c2
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#define cpu_has_3k_cache 0 #define cpu_has_3k_cache 0
#define cpu_has_4k_cache 0 #define cpu_has_4k_cache 0
#define cpu_has_tx39_cache 0 #define cpu_has_tx39_cache 0
#define cpu_has_fpu 0
#define cpu_has_counter 1 #define cpu_has_counter 1
#define cpu_has_watch 1 #define cpu_has_watch 1
#define cpu_has_divec 1 #define cpu_has_divec 1
......
...@@ -41,7 +41,7 @@ obj-$(CONFIG_CPU_R4K_FPU) += r4k_fpu.o r4k_switch.o ...@@ -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_R3000) += r2300_fpu.o r2300_switch.o
obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_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_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) += smp.o
obj-$(CONFIG_SMP_UP) += smp-up.o obj-$(CONFIG_SMP_UP) += smp-up.o
......
...@@ -562,7 +562,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, ...@@ -562,7 +562,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
case cop1_op: case cop1_op:
preempt_disable(); preempt_disable();
if (is_fpu_owner()) 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 else
fcr31 = current->thread.fpu.fcr31; fcr31 = current->thread.fpu.fcr31;
preempt_enable(); preempt_enable();
......
...@@ -10,24 +10,12 @@ ...@@ -10,24 +10,12 @@
* Copyright (C) 2000 MIPS Technologies, Inc. * Copyright (C) 2000 MIPS Technologies, Inc.
* written by Carsten Langgaard, carstenl@mips.com * 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, * task_struct *resume(task_struct *prev, task_struct *next,
* struct thread_info *next_ti, int usedfpu) * struct thread_info *next_ti, int usedfpu)
...@@ -40,6 +28,61 @@ ...@@ -40,6 +28,61 @@
cpu_save_nonscratch a0 cpu_save_nonscratch a0
LONG_S ra, THREAD_REG31(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 #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
/* Check if we need to store CVMSEG state */ /* Check if we need to store CVMSEG state */
mfc0 t0, $11,7 /* CvmMemCtl */ mfc0 t0, $11,7 /* CvmMemCtl */
...@@ -85,12 +128,7 @@ ...@@ -85,12 +128,7 @@
move $28, a2 move $28, a2
cpu_restore_nonscratch a1 cpu_restore_nonscratch a1
#if (_THREAD_SIZE - 32) < 0x8000 PTR_ADDU t0, $28, _THREAD_SIZE - 32
PTR_ADDIU t0, $28, _THREAD_SIZE - 32
#else
PTR_LI t0, _THREAD_SIZE - 32
PTR_ADDU t0, $28
#endif
set_saved_sp t0, t1, t2 set_saved_sp t0, t1, t2
mfc0 t1, CP0_STATUS /* Do we really need this? */ mfc0 t1, CP0_STATUS /* Do we really need this? */
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
*/ */
#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) #define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
#ifndef USE_ALTERNATE_RESUME_IMPL
/* /*
* task_struct *resume(task_struct *prev, task_struct *next, * task_struct *resume(task_struct *prev, task_struct *next,
* struct thread_info *next_ti, s32 fp_save) * struct thread_info *next_ti, s32 fp_save)
...@@ -99,6 +100,8 @@ ...@@ -99,6 +100,8 @@
jr ra jr ra
END(resume) END(resume)
#endif /* USE_ALTERNATE_RESUME_IMPL */
/* /*
* Save a thread's fp context. * Save a thread's fp context.
*/ */
......
...@@ -584,7 +584,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, ...@@ -584,7 +584,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
if (insn.i_format.rs == bc_op) { if (insn.i_format.rs == bc_op) {
preempt_disable(); preempt_disable();
if (is_fpu_owner()) 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 else
fcr31 = current->thread.fpu.fcr31; fcr31 = current->thread.fpu.fcr31;
preempt_enable(); preempt_enable();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment