1 /* SPDX-License-Identifier: GPL-2.0 */ << 2 /* 1 /* 3 * Copyright (C) 2020-2022 Loongson Technology !! 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. 4 * 5 * 5 * Derived from MIPS: << 6 * Copyright (C) 1994 - 2000, 2001, 2003 Ralf 6 * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle 7 * Copyright (C) 1999, 2000 Silicon Graphics, 7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 * Copyright (C) 2001 MIPS Technologies, Inc. 8 * Copyright (C) 2001 MIPS Technologies, Inc. 9 */ 9 */ 10 10 11 #include <asm/asm.h> 11 #include <asm/asm.h> 12 #include <asm/asmmacro.h> 12 #include <asm/asmmacro.h> 13 #include <asm/loongarch.h> !! 13 #include <asm/compiler.h> >> 14 #include <asm/irqflags.h> 14 #include <asm/regdef.h> 15 #include <asm/regdef.h> >> 16 #include <asm/mipsregs.h> 15 #include <asm/stackframe.h> 17 #include <asm/stackframe.h> >> 18 #include <asm/isadep.h> 16 #include <asm/thread_info.h> 19 #include <asm/thread_info.h> 17 #include <asm/unwind_hints.h> !! 20 >> 21 #ifndef CONFIG_PREEMPTION >> 22 #define resume_kernel restore_all >> 23 #else >> 24 #define __ret_from_irq ret_from_exception >> 25 #endif 18 26 19 .text 27 .text 20 .cfi_sections .debug_frame << 21 .align 5 28 .align 5 22 SYM_CODE_START(handle_syscall) !! 29 #ifndef CONFIG_PREEMPTION 23 UNWIND_HINT_UNDEFINED !! 30 FEXPORT(ret_from_exception) 24 csrrd t0, PERCPU_BASE_KS !! 31 local_irq_disable # preempt stop 25 la.pcrel t1, kernelsp !! 32 b __ret_from_irq 26 add.d t1, t1, t0 !! 33 #endif 27 move t2, sp !! 34 FEXPORT(ret_from_irq) 28 ld.d sp, t1, 0 !! 35 LONG_S s0, TI_REGS($28) 29 !! 36 FEXPORT(__ret_from_irq) 30 addi.d sp, sp, -PT_SIZE !! 37 /* 31 cfi_st t2, PT_R3 !! 38 * We can be coming here from a syscall done in the kernel space, 32 cfi_rel_offset sp, PT_R3 !! 39 * e.g. a failed kernel_execve(). 33 st.d zero, sp, PT_R0 !! 40 */ 34 csrrd t2, LOONGARCH_CSR_PRMD !! 41 resume_userspace_check: 35 st.d t2, sp, PT_PRMD !! 42 LONG_L t0, PT_STATUS(sp) # returning to kernel mode? 36 csrrd t2, LOONGARCH_CSR_CRMD !! 43 andi t0, t0, KU_USER 37 st.d t2, sp, PT_CRMD !! 44 beqz t0, resume_kernel 38 csrrd t2, LOONGARCH_CSR_EUEN !! 45 39 st.d t2, sp, PT_EUEN !! 46 resume_userspace: 40 csrrd t2, LOONGARCH_CSR_ECFG !! 47 local_irq_disable # make sure we dont miss an 41 st.d t2, sp, PT_ECFG !! 48 # interrupt setting need_resched 42 csrrd t2, LOONGARCH_CSR_ESTA !! 49 # between sampling and return 43 st.d t2, sp, PT_ESTAT !! 50 LONG_L a2, TI_FLAGS($28) # current->work 44 cfi_st ra, PT_R1 !! 51 andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace) 45 cfi_st a0, PT_R4 !! 52 bnez t0, work_pending 46 cfi_st a1, PT_R5 !! 53 j restore_all 47 cfi_st a2, PT_R6 !! 54 48 cfi_st a3, PT_R7 !! 55 #ifdef CONFIG_PREEMPTION 49 cfi_st a4, PT_R8 !! 56 resume_kernel: 50 cfi_st a5, PT_R9 !! 57 local_irq_disable 51 cfi_st a6, PT_R10 !! 58 lw t0, TI_PRE_COUNT($28) 52 cfi_st a7, PT_R11 !! 59 bnez t0, restore_all 53 csrrd ra, LOONGARCH_CSR_ERA !! 60 LONG_L t0, TI_FLAGS($28) 54 st.d ra, sp, PT_ERA !! 61 andi t1, t0, _TIF_NEED_RESCHED 55 cfi_rel_offset ra, PT_ERA !! 62 beqz t1, restore_all 56 !! 63 LONG_L t0, PT_STATUS(sp) # Interrupts off? 57 cfi_st tp, PT_R2 !! 64 andi t0, 1 58 cfi_st u0, PT_R21 !! 65 beqz t0, restore_all 59 cfi_st fp, PT_R22 !! 66 PTR_LA ra, restore_all >> 67 j preempt_schedule_irq >> 68 #endif 60 69 >> 70 FEXPORT(ret_from_kernel_thread) >> 71 jal schedule_tail # a0 = struct task_struct *prev >> 72 move a0, s1 >> 73 jal s0 >> 74 j syscall_exit >> 75 >> 76 FEXPORT(ret_from_fork) >> 77 jal schedule_tail # a0 = struct task_struct *prev >> 78 >> 79 FEXPORT(syscall_exit) >> 80 #ifdef CONFIG_DEBUG_RSEQ >> 81 move a0, sp >> 82 jal rseq_syscall >> 83 #endif >> 84 local_irq_disable # make sure need_resched and >> 85 # signals dont change between >> 86 # sampling and return >> 87 LONG_L a2, TI_FLAGS($28) # current->work >> 88 li t0, _TIF_ALLWORK_MASK >> 89 and t0, a2, t0 >> 90 bnez t0, syscall_exit_work >> 91 >> 92 restore_all: # restore full frame >> 93 .set noat >> 94 RESTORE_TEMP >> 95 RESTORE_AT >> 96 RESTORE_STATIC >> 97 restore_partial: # restore partial frame >> 98 #ifdef CONFIG_TRACE_IRQFLAGS 61 SAVE_STATIC 99 SAVE_STATIC 62 UNWIND_HINT_REGS !! 100 SAVE_AT 63 !! 101 SAVE_TEMP 64 #ifdef CONFIG_KGDB !! 102 LONG_L v0, PT_STATUS(sp) 65 li.w t1, CSR_CRMD_WE !! 103 #if defined(CONFIG_CPU_R3000) 66 csrxchg t1, t1, LOONGARCH_CSR_ !! 104 and v0, ST0_IEP >> 105 #else >> 106 and v0, ST0_IE 67 #endif 107 #endif 68 !! 108 beqz v0, 1f 69 move u0, t0 !! 109 jal trace_hardirqs_on 70 li.d tp, ~_THREAD_MASK !! 110 b 2f 71 and tp, tp, sp !! 111 1: jal trace_hardirqs_off 72 !! 112 2: 73 move a0, sp !! 113 RESTORE_TEMP 74 bl do_syscall !! 114 RESTORE_AT 75 << 76 RESTORE_ALL_AND_RET << 77 SYM_CODE_END(handle_syscall) << 78 _ASM_NOKPROBE(handle_syscall) << 79 << 80 SYM_CODE_START(ret_from_fork) << 81 UNWIND_HINT_REGS << 82 bl schedule_tail << 83 move a0, sp << 84 bl syscall_exit_to_user_m << 85 RESTORE_STATIC 115 RESTORE_STATIC >> 116 #endif 86 RESTORE_SOME 117 RESTORE_SOME 87 RESTORE_SP_AND_RET 118 RESTORE_SP_AND_RET 88 SYM_CODE_END(ret_from_fork) !! 119 .set at 89 120 90 SYM_CODE_START(ret_from_kernel_thread) !! 121 work_pending: 91 UNWIND_HINT_REGS !! 122 andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS 92 bl schedule_tail !! 123 beqz t0, work_notifysig 93 move a0, s1 !! 124 work_resched: 94 jirl ra, s0, 0 !! 125 TRACE_IRQS_OFF 95 move a0, sp !! 126 jal schedule 96 bl syscall_exit_to_user_m !! 127 97 RESTORE_STATIC !! 128 local_irq_disable # make sure need_resched and 98 RESTORE_SOME !! 129 # signals dont change between 99 RESTORE_SP_AND_RET !! 130 # sampling and return 100 SYM_CODE_END(ret_from_kernel_thread) !! 131 LONG_L a2, TI_FLAGS($28) >> 132 andi t0, a2, _TIF_WORK_MASK # is there any work to be done >> 133 # other than syscall tracing? >> 134 beqz t0, restore_all >> 135 andi t0, a2, _TIF_NEED_RESCHED >> 136 bnez t0, work_resched >> 137 >> 138 work_notifysig: # deal with pending signals and >> 139 # notify-resume requests >> 140 move a0, sp >> 141 li a1, 0 >> 142 jal do_notify_resume # a2 already loaded >> 143 j resume_userspace_check >> 144 >> 145 FEXPORT(syscall_exit_partial) >> 146 #ifdef CONFIG_DEBUG_RSEQ >> 147 move a0, sp >> 148 jal rseq_syscall >> 149 #endif >> 150 local_irq_disable # make sure need_resched doesn't >> 151 # change between and return >> 152 LONG_L a2, TI_FLAGS($28) # current->work >> 153 li t0, _TIF_ALLWORK_MASK >> 154 and t0, a2 >> 155 beqz t0, restore_partial >> 156 SAVE_STATIC >> 157 syscall_exit_work: >> 158 LONG_L t0, PT_STATUS(sp) # returning to kernel mode? >> 159 andi t0, t0, KU_USER >> 160 beqz t0, resume_kernel >> 161 li t0, _TIF_WORK_SYSCALL_EXIT >> 162 and t0, a2 # a2 is preloaded with TI_FLAGS >> 163 beqz t0, work_pending # trace bit set? >> 164 local_irq_enable # could let syscall_trace_leave() >> 165 # call schedule() instead >> 166 TRACE_IRQS_ON >> 167 move a0, sp >> 168 jal syscall_trace_leave >> 169 b resume_userspace >> 170 >> 171 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \ >> 172 defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_MIPS_MT) >> 173 >> 174 /* >> 175 * MIPS32R2 Instruction Hazard Barrier - must be called >> 176 * >> 177 * For C code use the inline version named instruction_hazard(). >> 178 */ >> 179 LEAF(mips_ihb) >> 180 .set MIPS_ISA_LEVEL_RAW >> 181 jr.hb ra >> 182 nop >> 183 END(mips_ihb) >> 184 >> 185 #endif /* CONFIG_CPU_MIPSR2 - CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.