| /* SPDX-License-Identifier: GPL-2.0 */ | |
| /* | |
| * Author: Qi Hu <huqi@loongson.cn> | |
| * Huacai Chen <chenhuacai@loongson.cn> | |
| * | |
| * Copyright (C) 2020-2023 Loongson Technology Corporation Limited | |
| */ | |
| #include <asm/asm.h> | |
| #include <asm/asmmacro.h> | |
| #include <asm/asm-extable.h> | |
| #include <asm/asm-offsets.h> | |
| #include <asm/errno.h> | |
| #include <asm/regdef.h> | |
| #include <asm/unwind_hints.h> | |
| #define SCR_REG_WIDTH 8 | |
| .macro EX insn, reg, src, offs | |
| .ex\@: \insn \reg, \src, \offs | |
| _asm_extable .ex\@, .L_lbt_fault | |
| .endm | |
| /* | |
| * Save a thread's lbt context. | |
| */ | |
| SYM_FUNC_START(_save_lbt) | |
| movscr2gr t1, $scr0 # save scr | |
| stptr.d t1, a0, THREAD_SCR0 | |
| movscr2gr t1, $scr1 | |
| stptr.d t1, a0, THREAD_SCR1 | |
| movscr2gr t1, $scr2 | |
| stptr.d t1, a0, THREAD_SCR2 | |
| movscr2gr t1, $scr3 | |
| stptr.d t1, a0, THREAD_SCR3 | |
| x86mfflag t1, 0x3f # save eflags | |
| stptr.d t1, a0, THREAD_EFLAGS | |
| jr ra | |
| SYM_FUNC_END(_save_lbt) | |
| EXPORT_SYMBOL(_save_lbt) | |
| /* | |
| * Restore a thread's lbt context. | |
| */ | |
| SYM_FUNC_START(_restore_lbt) | |
| ldptr.d t1, a0, THREAD_SCR0 # restore scr | |
| movgr2scr $scr0, t1 | |
| ldptr.d t1, a0, THREAD_SCR1 | |
| movgr2scr $scr1, t1 | |
| ldptr.d t1, a0, THREAD_SCR2 | |
| movgr2scr $scr2, t1 | |
| ldptr.d t1, a0, THREAD_SCR3 | |
| movgr2scr $scr3, t1 | |
| ldptr.d t1, a0, THREAD_EFLAGS # restore eflags | |
| x86mtflag t1, 0x3f | |
| jr ra | |
| SYM_FUNC_END(_restore_lbt) | |
| EXPORT_SYMBOL(_restore_lbt) | |
| /* | |
| * Load scr/eflag with zero. | |
| */ | |
| SYM_FUNC_START(_init_lbt) | |
| movgr2scr $scr0, zero | |
| movgr2scr $scr1, zero | |
| movgr2scr $scr2, zero | |
| movgr2scr $scr3, zero | |
| x86mtflag zero, 0x3f | |
| jr ra | |
| SYM_FUNC_END(_init_lbt) | |
| /* | |
| * a0: scr | |
| * a1: eflag | |
| */ | |
| SYM_FUNC_START(_save_lbt_context) | |
| movscr2gr t1, $scr0 # save scr | |
| EX st.d t1, a0, (0 * SCR_REG_WIDTH) | |
| movscr2gr t1, $scr1 | |
| EX st.d t1, a0, (1 * SCR_REG_WIDTH) | |
| movscr2gr t1, $scr2 | |
| EX st.d t1, a0, (2 * SCR_REG_WIDTH) | |
| movscr2gr t1, $scr3 | |
| EX st.d t1, a0, (3 * SCR_REG_WIDTH) | |
| x86mfflag t1, 0x3f # save eflags | |
| EX st.w t1, a1, 0 | |
| li.w a0, 0 # success | |
| jr ra | |
| SYM_FUNC_END(_save_lbt_context) | |
| /* | |
| * a0: scr | |
| * a1: eflag | |
| */ | |
| SYM_FUNC_START(_restore_lbt_context) | |
| EX ld.d t1, a0, (0 * SCR_REG_WIDTH) # restore scr | |
| movgr2scr $scr0, t1 | |
| EX ld.d t1, a0, (1 * SCR_REG_WIDTH) | |
| movgr2scr $scr1, t1 | |
| EX ld.d t1, a0, (2 * SCR_REG_WIDTH) | |
| movgr2scr $scr2, t1 | |
| EX ld.d t1, a0, (3 * SCR_REG_WIDTH) | |
| movgr2scr $scr3, t1 | |
| EX ld.w t1, a1, 0 # restore eflags | |
| x86mtflag t1, 0x3f | |
| li.w a0, 0 # success | |
| jr ra | |
| SYM_FUNC_END(_restore_lbt_context) | |
| /* | |
| * a0: ftop | |
| */ | |
| SYM_FUNC_START(_save_ftop_context) | |
| x86mftop t1 | |
| st.w t1, a0, 0 | |
| li.w a0, 0 # success | |
| jr ra | |
| SYM_FUNC_END(_save_ftop_context) | |
| /* | |
| * a0: ftop | |
| */ | |
| SYM_FUNC_START(_restore_ftop_context) | |
| ld.w t1, a0, 0 | |
| andi t1, t1, 0x7 | |
| la.pcrel a0, 1f | |
| alsl.d a0, t1, a0, 3 | |
| jr a0 | |
| 1: | |
| x86mttop 0 | |
| b 2f | |
| x86mttop 1 | |
| b 2f | |
| x86mttop 2 | |
| b 2f | |
| x86mttop 3 | |
| b 2f | |
| x86mttop 4 | |
| b 2f | |
| x86mttop 5 | |
| b 2f | |
| x86mttop 6 | |
| b 2f | |
| x86mttop 7 | |
| 2: | |
| li.w a0, 0 # success | |
| jr ra | |
| SYM_FUNC_END(_restore_ftop_context) | |
| .L_lbt_fault: | |
| li.w a0, -EFAULT # failure | |
| jr ra | |
| STACK_FRAME_NON_STANDARD _restore_ftop_context |