From 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 Mon Sep 17 00:00:00 2001 From: Yunhong Jiang Date: Tue, 4 Aug 2015 12:17:53 -0700 Subject: Add the rt linux 4.1.3-rt3 as base Import the rt linux 4.1.3-rt3 as OPNFV kvm base. It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and the base is: commit 0917f823c59692d751951bf5ea699a2d1e2f26a2 Author: Sebastian Andrzej Siewior Date: Sat Jul 25 12:13:34 2015 +0200 Prepare v4.1.3-rt3 Signed-off-by: Sebastian Andrzej Siewior We lose all the git history this way and it's not good. We should apply another opnfv project repo in future. Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423 Signed-off-by: Yunhong Jiang --- kernel/arch/mips/include/asm/fpu.h | 251 +++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 kernel/arch/mips/include/asm/fpu.h (limited to 'kernel/arch/mips/include/asm/fpu.h') diff --git a/kernel/arch/mips/include/asm/fpu.h b/kernel/arch/mips/include/asm/fpu.h new file mode 100644 index 000000000..084780b35 --- /dev/null +++ b/kernel/arch/mips/include/asm/fpu.h @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2002 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#ifndef _ASM_FPU_H +#define _ASM_FPU_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MIPS_MT_FPAFF +#include +#endif + +struct sigcontext; +struct sigcontext32; + +extern void _init_fpu(unsigned int); +extern void _save_fp(struct task_struct *); +extern void _restore_fp(struct task_struct *); + +/* + * This enum specifies a mode in which we want the FPU to operate, for cores + * which implement the Status.FR bit. Note that the bottom bit of the value + * purposefully matches the desired value of the Status.FR bit. + */ +enum fpu_mode { + FPU_32BIT = 0, /* FR = 0 */ + FPU_64BIT, /* FR = 1, FRE = 0 */ + FPU_AS_IS, + FPU_HYBRID, /* FR = 1, FRE = 1 */ + +#define FPU_FR_MASK 0x1 +}; + +#define __disable_fpu() \ +do { \ + clear_c0_status(ST0_CU1); \ + disable_fpu_hazard(); \ +} while (0) + +static inline int __enable_fpu(enum fpu_mode mode) +{ + int fr; + + switch (mode) { + case FPU_AS_IS: + /* just enable the FPU in its current mode */ + set_c0_status(ST0_CU1); + enable_fpu_hazard(); + return 0; + + case FPU_HYBRID: + if (!cpu_has_fre) + return SIGFPE; + + /* set FRE */ + set_c0_config5(MIPS_CONF5_FRE); + goto fr_common; + + case FPU_64BIT: +#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6) \ + || defined(CONFIG_64BIT)) + /* we only have a 32-bit FPU */ + return SIGFPE; +#endif + /* fall through */ + case FPU_32BIT: + if (cpu_has_fre) { + /* clear FRE */ + clear_c0_config5(MIPS_CONF5_FRE); + } +fr_common: + /* set CU1 & change FR appropriately */ + fr = (int)mode & FPU_FR_MASK; + change_c0_status(ST0_CU1 | ST0_FR, ST0_CU1 | (fr ? ST0_FR : 0)); + enable_fpu_hazard(); + + /* check FR has the desired value */ + if (!!(read_c0_status() & ST0_FR) == !!fr) + return 0; + + /* unsupported FR value */ + __disable_fpu(); + return SIGFPE; + + default: + BUG(); + } + + return SIGFPE; +} + +#define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU) + +static inline int __is_fpu_owner(void) +{ + return test_thread_flag(TIF_USEDFPU); +} + +static inline int is_fpu_owner(void) +{ + return cpu_has_fpu && __is_fpu_owner(); +} + +static inline int __own_fpu(void) +{ + enum fpu_mode mode; + int ret; + + if (test_thread_flag(TIF_HYBRID_FPREGS)) + mode = FPU_HYBRID; + else + mode = !test_thread_flag(TIF_32BIT_FPREGS); + + ret = __enable_fpu(mode); + if (ret) + return ret; + + KSTK_STATUS(current) |= ST0_CU1; + if (mode == FPU_64BIT || mode == FPU_HYBRID) + KSTK_STATUS(current) |= ST0_FR; + else /* mode == FPU_32BIT */ + KSTK_STATUS(current) &= ~ST0_FR; + + set_thread_flag(TIF_USEDFPU); + return 0; +} + +static inline int own_fpu_inatomic(int restore) +{ + int ret = 0; + + if (cpu_has_fpu && !__is_fpu_owner()) { + ret = __own_fpu(); + if (restore && !ret) + _restore_fp(current); + } + return ret; +} + +static inline int own_fpu(int restore) +{ + int ret; + + preempt_disable(); + ret = own_fpu_inatomic(restore); + preempt_enable(); + return ret; +} + +static inline void lose_fpu(int save) +{ + preempt_disable(); + if (is_msa_enabled()) { + if (save) { + save_msa(current); + current->thread.fpu.fcr31 = + read_32bit_cp1_register(CP1_STATUS); + } + disable_msa(); + clear_thread_flag(TIF_USEDMSA); + __disable_fpu(); + } else if (is_fpu_owner()) { + if (save) + _save_fp(current); + __disable_fpu(); + } + KSTK_STATUS(current) &= ~ST0_CU1; + clear_thread_flag(TIF_USEDFPU); + preempt_enable(); +} + +static inline int init_fpu(void) +{ + unsigned int fcr31 = current->thread.fpu.fcr31; + int ret = 0; + + if (cpu_has_fpu) { + unsigned int config5; + + ret = __own_fpu(); + if (ret) + return ret; + + if (!cpu_has_fre) { + _init_fpu(fcr31); + + return 0; + } + + /* + * Ensure FRE is clear whilst running _init_fpu, since + * single precision FP instructions are used. If FRE + * was set then we'll just end up initialising all 32 + * 64b registers. + */ + config5 = clear_c0_config5(MIPS_CONF5_FRE); + enable_fpu_hazard(); + + _init_fpu(fcr31); + + /* Restore FRE */ + write_c0_config5(config5); + enable_fpu_hazard(); + } else + fpu_emulator_init_fpu(); + + return ret; +} + +static inline void save_fp(struct task_struct *tsk) +{ + if (cpu_has_fpu) + _save_fp(tsk); +} + +static inline void restore_fp(struct task_struct *tsk) +{ + if (cpu_has_fpu) + _restore_fp(tsk); +} + +static inline union fpureg *get_fpu_regs(struct task_struct *tsk) +{ + if (tsk == current) { + preempt_disable(); + if (is_fpu_owner()) + _save_fp(current); + preempt_enable(); + } + + return tsk->thread.fpu.fpr; +} + +#endif /* _ASM_FPU_H */ -- cgit 1.2.3-korg