| /* 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> |
| |
| #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 |