mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 01:04:19 +08:00
9b26616c8d
Define the central place the default FCSR value is set from, initialised in `cpu_probe'. Determine the FCSR mask applied to values written to the register with CTC1 in the full emulation mode and via ptrace(2), according to the ISA level of processor hardware or the writability of bits 31:18 if actual FPU hardware is used. Software may rely on FCSR bits whose functions our emulator does not implement, so it should not allow them to be set or software may get confused. For ptrace(2) it's just sanity. [ralf@linux-mips.org: Fixed double inclusion of <asm/current.h>.] Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/9711/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
64 lines
1.6 KiB
C
64 lines
1.6 KiB
C
/*
|
|
* 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)
|
|
{
|
|
int fpu_owned;
|
|
int fr = !test_thread_flag(TIF_32BIT_FPREGS);
|
|
|
|
switch (action) {
|
|
case CU2_EXCEPTION:
|
|
preempt_disable();
|
|
fpu_owned = __is_fpu_owner();
|
|
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;
|
|
/* If FPU is owned, we needn't init or restore fp */
|
|
if (!fpu_owned) {
|
|
set_thread_flag(TIF_USEDFPU);
|
|
if (!used_math()) {
|
|
_init_fpu(current->thread.fpu.fcr31);
|
|
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);
|