diff options
Diffstat (limited to 'arch/loongarch/kernel/genex.S')
| -rw-r--r-- | arch/loongarch/kernel/genex.S | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/arch/loongarch/kernel/genex.S b/arch/loongarch/kernel/genex.S new file mode 100644 index 000000000000..733a7665e434 --- /dev/null +++ b/arch/loongarch/kernel/genex.S @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited + * + * Derived from MIPS: + * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2002, 2007 Maciej W. Rozycki + * Copyright (C) 2001, 2012 MIPS Technologies, Inc. All rights reserved. + */ +#include <asm/asm.h> +#include <asm/asmmacro.h> +#include <asm/loongarch.h> +#include <asm/regdef.h> +#include <asm/fpregdef.h> +#include <asm/stackframe.h> +#include <asm/thread_info.h> + + .section .cpuidle.text, "ax" + .align 5 +SYM_FUNC_START(__arch_cpu_idle) + /* start of idle interrupt region */ + ori t0, zero, CSR_CRMD_IE + /* idle instruction needs irq enabled */ + csrxchg t0, t0, LOONGARCH_CSR_CRMD + /* + * If an interrupt lands here; between enabling interrupts above and + * going idle on the next instruction, we must *NOT* go idle since the + * interrupt could have set TIF_NEED_RESCHED or caused an timer to need + * reprogramming. Fall through -- see handle_vint() below -- and have + * the idle loop take care of things. + */ + idle 0 + /* end of idle interrupt region */ +idle_exit: + jr ra +SYM_FUNC_END(__arch_cpu_idle) + .previous + +SYM_CODE_START(handle_vint) + UNWIND_HINT_UNDEFINED + BACKUP_T0T1 + SAVE_ALL + la_abs t1, idle_exit + LONG_L t0, sp, PT_ERA + /* 3 instructions idle interrupt region */ + ori t0, t0, 0b1100 + bne t0, t1, 1f + LONG_S t0, sp, PT_ERA +1: move a0, sp + move a1, sp + la_abs t0, do_vint + jirl ra, t0, 0 + RESTORE_ALL_AND_RET +SYM_CODE_END(handle_vint) + +SYM_CODE_START(except_vec_cex) + UNWIND_HINT_UNDEFINED + b cache_parity_error +SYM_CODE_END(except_vec_cex) + + .macro build_prep_badv + csrrd t0, LOONGARCH_CSR_BADV + PTR_S t0, sp, PT_BVADDR + .endm + + .macro build_prep_fcsr + movfcsr2gr a1, fcsr0 + .endm + + .macro build_prep_none + .endm + + .macro BUILD_HANDLER exception handler prep + .align 5 + SYM_CODE_START(handle_\exception) + UNWIND_HINT_UNDEFINED + 666: + BACKUP_T0T1 + SAVE_ALL + build_prep_\prep + move a0, sp + la_abs t0, do_\handler + jirl ra, t0, 0 + 668: + RESTORE_ALL_AND_RET + SYM_CODE_END(handle_\exception) + .pushsection ".data", "aw", %progbits + SYM_DATA(unwind_hint_\exception, .word 668b - 666b) + .popsection + .endm + + BUILD_HANDLER ade ade badv + BUILD_HANDLER ale ale badv + BUILD_HANDLER bce bce none + BUILD_HANDLER bp bp none + BUILD_HANDLER fpe fpe fcsr + BUILD_HANDLER fpu fpu none + BUILD_HANDLER lsx lsx none + BUILD_HANDLER lasx lasx none + BUILD_HANDLER lbt lbt none + BUILD_HANDLER ri ri none + BUILD_HANDLER watch watch none + BUILD_HANDLER reserved reserved none /* others */ + +SYM_CODE_START(handle_sys) + UNWIND_HINT_UNDEFINED + la_abs t0, handle_syscall + jr t0 +SYM_CODE_END(handle_sys) |
