2014-06-26 07:41:31 +04:00
/*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
* Copyright ( C ) 2014 Lemote Corporation .
* written by Huacai Chen < chenhc @ lemote . com >
*
* based on arch / mips / cavium - octeon / cpu . c
* Copyright ( C ) 2009 Wind River Systems ,
* written by Ralf Baechle < ralf @ linux - mips . org >
*/
# include <linux/init.h>
# include <linux/sched.h>
# include <linux/notifier.h>
# include <asm/fpu.h>
# include <asm/cop2.h>
# include <asm/current.h>
# include <asm/mipsregs.h>
static int loongson_cu2_call ( struct notifier_block * nfb , unsigned long action ,
void * data )
{
2014-08-11 13:10:38 +04:00
int fpu_owned ;
2014-06-26 07:41:31 +04:00
int fr = ! test_thread_flag ( TIF_32BIT_FPREGS ) ;
switch ( action ) {
case CU2_EXCEPTION :
preempt_disable ( ) ;
2014-08-11 13:10:38 +04:00
fpu_owned = __is_fpu_owner ( ) ;
2014-06-26 07:41:31 +04:00
if ( ! fr )
set_c0_status ( ST0_CU1 | ST0_CU2 ) ;
else
set_c0_status ( ST0_CU1 | ST0_CU2 | ST0_FR ) ;
enable_fpu_hazard ( ) ;
KSTK_STATUS ( current ) | = ( ST0_CU1 | ST0_CU2 ) ;
if ( fr )
KSTK_STATUS ( current ) | = ST0_FR ;
else
KSTK_STATUS ( current ) & = ~ ST0_FR ;
2014-08-11 13:10:38 +04:00
/* If FPU is owned, we needn't init or restore fp */
if ( ! fpu_owned ) {
2014-06-26 07:41:31 +04:00
set_thread_flag ( TIF_USEDFPU ) ;
if ( ! used_math ( ) ) {
2015-04-04 01:27:48 +03:00
_init_fpu ( current - > thread . fpu . fcr31 ) ;
2014-06-26 07:41:31 +04:00
set_used_math ( ) ;
} else
_restore_fp ( current ) ;
}
preempt_enable ( ) ;
return NOTIFY_STOP ; /* Don't call default notifier */
}
return NOTIFY_OK ; /* Let default notifier send signals */
}
static int __init loongson_cu2_setup ( void )
{
return cu2_notifier ( loongson_cu2_call , 0 ) ;
}
early_initcall ( loongson_cu2_setup ) ;