Huacai Chen | ef2f826 | 2014-06-26 11:41:31 +0800 | [diff] [blame] | 1 | /* |
| 2 | * This file is subject to the terms and conditions of the GNU General Public |
| 3 | * License. See the file "COPYING" in the main directory of this archive |
| 4 | * for more details. |
| 5 | * |
| 6 | * Copyright (C) 2014 Lemote Corporation. |
| 7 | * written by Huacai Chen <chenhc@lemote.com> |
| 8 | * |
| 9 | * based on arch/mips/cavium-octeon/cpu.c |
| 10 | * Copyright (C) 2009 Wind River Systems, |
| 11 | * written by Ralf Baechle <ralf@linux-mips.org> |
| 12 | */ |
| 13 | #include <linux/init.h> |
| 14 | #include <linux/sched.h> |
| 15 | #include <linux/notifier.h> |
Arnd Bergmann | fc69910 | 2017-03-08 08:29:31 +0100 | [diff] [blame] | 16 | #include <linux/ptrace.h> |
Huacai Chen | ef2f826 | 2014-06-26 11:41:31 +0800 | [diff] [blame] | 17 | |
| 18 | #include <asm/fpu.h> |
| 19 | #include <asm/cop2.h> |
| 20 | #include <asm/current.h> |
| 21 | #include <asm/mipsregs.h> |
| 22 | |
| 23 | static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action, |
| 24 | void *data) |
| 25 | { |
Huacai Chen | bfcdf13 | 2014-08-11 17:10:38 +0800 | [diff] [blame] | 26 | int fpu_owned; |
Huacai Chen | ef2f826 | 2014-06-26 11:41:31 +0800 | [diff] [blame] | 27 | int fr = !test_thread_flag(TIF_32BIT_FPREGS); |
| 28 | |
| 29 | switch (action) { |
| 30 | case CU2_EXCEPTION: |
| 31 | preempt_disable(); |
Huacai Chen | bfcdf13 | 2014-08-11 17:10:38 +0800 | [diff] [blame] | 32 | fpu_owned = __is_fpu_owner(); |
Huacai Chen | ef2f826 | 2014-06-26 11:41:31 +0800 | [diff] [blame] | 33 | if (!fr) |
| 34 | set_c0_status(ST0_CU1 | ST0_CU2); |
| 35 | else |
| 36 | set_c0_status(ST0_CU1 | ST0_CU2 | ST0_FR); |
| 37 | enable_fpu_hazard(); |
| 38 | KSTK_STATUS(current) |= (ST0_CU1 | ST0_CU2); |
| 39 | if (fr) |
| 40 | KSTK_STATUS(current) |= ST0_FR; |
| 41 | else |
| 42 | KSTK_STATUS(current) &= ~ST0_FR; |
Huacai Chen | bfcdf13 | 2014-08-11 17:10:38 +0800 | [diff] [blame] | 43 | /* If FPU is owned, we needn't init or restore fp */ |
| 44 | if (!fpu_owned) { |
Huacai Chen | ef2f826 | 2014-06-26 11:41:31 +0800 | [diff] [blame] | 45 | set_thread_flag(TIF_USEDFPU); |
Paul Burton | cc97ab2 | 2018-11-07 23:13:59 +0000 | [diff] [blame] | 46 | init_fp_ctx(current); |
| 47 | _restore_fp(current); |
Huacai Chen | ef2f826 | 2014-06-26 11:41:31 +0800 | [diff] [blame] | 48 | } |
| 49 | preempt_enable(); |
| 50 | |
| 51 | return NOTIFY_STOP; /* Don't call default notifier */ |
| 52 | } |
| 53 | |
| 54 | return NOTIFY_OK; /* Let default notifier send signals */ |
| 55 | } |
| 56 | |
| 57 | static int __init loongson_cu2_setup(void) |
| 58 | { |
| 59 | return cu2_notifier(loongson_cu2_call, 0); |
| 60 | } |
| 61 | early_initcall(loongson_cu2_setup); |