diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/kernel/scall32-o32.S | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/kernel/scall32-o32.S')
-rw-r--r-- | arch/mips/kernel/scall32-o32.S | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S new file mode 100644 index 000000000..b449b6866 --- /dev/null +++ b/arch/mips/kernel/scall32-o32.S | |||
@@ -0,0 +1,225 @@ | |||
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) 1995-99, 2000- 02, 06 Ralf Baechle <ralf@linux-mips.org> | ||
7 | * Copyright (C) 2001 MIPS Technologies, Inc. | ||
8 | * Copyright (C) 2004 Thiemo Seufer | ||
9 | * Copyright (C) 2014 Imagination Technologies Ltd. | ||
10 | */ | ||
11 | #include <linux/errno.h> | ||
12 | #include <asm/asm.h> | ||
13 | #include <asm/asmmacro.h> | ||
14 | #include <asm/irqflags.h> | ||
15 | #include <asm/mipsregs.h> | ||
16 | #include <asm/regdef.h> | ||
17 | #include <asm/stackframe.h> | ||
18 | #include <asm/isadep.h> | ||
19 | #include <asm/sysmips.h> | ||
20 | #include <asm/thread_info.h> | ||
21 | #include <asm/unistd.h> | ||
22 | #include <asm/war.h> | ||
23 | #include <asm/asm-offsets.h> | ||
24 | |||
25 | .align 5 | ||
26 | NESTED(handle_sys, PT_SIZE, sp) | ||
27 | .set noat | ||
28 | SAVE_SOME | ||
29 | TRACE_IRQS_ON_RELOAD | ||
30 | STI | ||
31 | .set at | ||
32 | |||
33 | lw t1, PT_EPC(sp) # skip syscall on return | ||
34 | |||
35 | addiu t1, 4 # skip to next instruction | ||
36 | sw t1, PT_EPC(sp) | ||
37 | |||
38 | sw a3, PT_R26(sp) # save a3 for syscall restarting | ||
39 | |||
40 | /* | ||
41 | * More than four arguments. Try to deal with it by copying the | ||
42 | * stack arguments from the user stack to the kernel stack. | ||
43 | * This Sucks (TM). | ||
44 | */ | ||
45 | lw t0, PT_R29(sp) # get old user stack pointer | ||
46 | |||
47 | /* | ||
48 | * We intentionally keep the kernel stack a little below the top of | ||
49 | * userspace so we don't have to do a slower byte accurate check here. | ||
50 | */ | ||
51 | lw t5, TI_ADDR_LIMIT($28) | ||
52 | addu t4, t0, 32 | ||
53 | and t5, t4 | ||
54 | bltz t5, bad_stack # -> sp is bad | ||
55 | |||
56 | /* | ||
57 | * Ok, copy the args from the luser stack to the kernel stack. | ||
58 | */ | ||
59 | |||
60 | .set push | ||
61 | .set noreorder | ||
62 | .set nomacro | ||
63 | |||
64 | load_a4: user_lw(t5, 16(t0)) # argument #5 from usp | ||
65 | load_a5: user_lw(t6, 20(t0)) # argument #6 from usp | ||
66 | load_a6: user_lw(t7, 24(t0)) # argument #7 from usp | ||
67 | load_a7: user_lw(t8, 28(t0)) # argument #8 from usp | ||
68 | loads_done: | ||
69 | |||
70 | sw t5, 16(sp) # argument #5 to ksp | ||
71 | sw t6, 20(sp) # argument #6 to ksp | ||
72 | sw t7, 24(sp) # argument #7 to ksp | ||
73 | sw t8, 28(sp) # argument #8 to ksp | ||
74 | .set pop | ||
75 | |||
76 | .section __ex_table,"a" | ||
77 | PTR load_a4, bad_stack_a4 | ||
78 | PTR load_a5, bad_stack_a5 | ||
79 | PTR load_a6, bad_stack_a6 | ||
80 | PTR load_a7, bad_stack_a7 | ||
81 | .previous | ||
82 | |||
83 | lw t0, TI_FLAGS($28) # syscall tracing enabled? | ||
84 | li t1, _TIF_WORK_SYSCALL_ENTRY | ||
85 | and t0, t1 | ||
86 | bnez t0, syscall_trace_entry # -> yes | ||
87 | syscall_common: | ||
88 | subu v0, v0, __NR_O32_Linux # check syscall number | ||
89 | sltiu t0, v0, __NR_O32_Linux_syscalls | ||
90 | beqz t0, illegal_syscall | ||
91 | |||
92 | sll t0, v0, 2 | ||
93 | la t1, sys_call_table | ||
94 | addu t1, t0 | ||
95 | lw t2, (t1) # syscall routine | ||
96 | |||
97 | beqz t2, illegal_syscall | ||
98 | |||
99 | jalr t2 # Do The Real Thing (TM) | ||
100 | |||
101 | li t0, -EMAXERRNO - 1 # error? | ||
102 | sltu t0, t0, v0 | ||
103 | sw t0, PT_R7(sp) # set error flag | ||
104 | beqz t0, 1f | ||
105 | |||
106 | lw t1, PT_R2(sp) # syscall number | ||
107 | negu v0 # error | ||
108 | sw t1, PT_R0(sp) # save it for syscall restarting | ||
109 | 1: sw v0, PT_R2(sp) # result | ||
110 | |||
111 | o32_syscall_exit: | ||
112 | j syscall_exit_partial | ||
113 | |||
114 | /* ------------------------------------------------------------------------ */ | ||
115 | |||
116 | syscall_trace_entry: | ||
117 | SAVE_STATIC | ||
118 | move a0, sp | ||
119 | |||
120 | /* | ||
121 | * syscall number is in v0 unless we called syscall(__NR_###) | ||
122 | * where the real syscall number is in a0 | ||
123 | */ | ||
124 | move a1, v0 | ||
125 | subu t2, v0, __NR_O32_Linux | ||
126 | bnez t2, 1f /* __NR_syscall at offset 0 */ | ||
127 | lw a1, PT_R4(sp) | ||
128 | |||
129 | 1: jal syscall_trace_enter | ||
130 | |||
131 | bltz v0, 1f # seccomp failed? Skip syscall | ||
132 | |||
133 | RESTORE_STATIC | ||
134 | lw v0, PT_R2(sp) # Restore syscall (maybe modified) | ||
135 | lw a0, PT_R4(sp) # Restore argument registers | ||
136 | lw a1, PT_R5(sp) | ||
137 | lw a2, PT_R6(sp) | ||
138 | lw a3, PT_R7(sp) | ||
139 | j syscall_common | ||
140 | |||
141 | 1: j syscall_exit | ||
142 | |||
143 | /* ------------------------------------------------------------------------ */ | ||
144 | |||
145 | /* | ||
146 | * Our open-coded access area sanity test for the stack pointer | ||
147 | * failed. We probably should handle this case a bit more drastic. | ||
148 | */ | ||
149 | bad_stack: | ||
150 | li v0, EFAULT | ||
151 | sw v0, PT_R2(sp) | ||
152 | li t0, 1 # set error flag | ||
153 | sw t0, PT_R7(sp) | ||
154 | j o32_syscall_exit | ||
155 | |||
156 | bad_stack_a4: | ||
157 | li t5, 0 | ||
158 | b load_a5 | ||
159 | |||
160 | bad_stack_a5: | ||
161 | li t6, 0 | ||
162 | b load_a6 | ||
163 | |||
164 | bad_stack_a6: | ||
165 | li t7, 0 | ||
166 | b load_a7 | ||
167 | |||
168 | bad_stack_a7: | ||
169 | li t8, 0 | ||
170 | b loads_done | ||
171 | |||
172 | /* | ||
173 | * The system call does not exist in this kernel | ||
174 | */ | ||
175 | illegal_syscall: | ||
176 | li v0, ENOSYS # error | ||
177 | sw v0, PT_R2(sp) | ||
178 | li t0, 1 # set error flag | ||
179 | sw t0, PT_R7(sp) | ||
180 | j o32_syscall_exit | ||
181 | END(handle_sys) | ||
182 | |||
183 | LEAF(sys_syscall) | ||
184 | subu t0, a0, __NR_O32_Linux # check syscall number | ||
185 | sltiu v0, t0, __NR_O32_Linux_syscalls | ||
186 | beqz t0, einval # do not recurse | ||
187 | sll t1, t0, 2 | ||
188 | beqz v0, einval | ||
189 | lw t2, sys_call_table(t1) # syscall routine | ||
190 | |||
191 | move a0, a1 # shift argument registers | ||
192 | move a1, a2 | ||
193 | move a2, a3 | ||
194 | lw a3, 16(sp) | ||
195 | lw t4, 20(sp) | ||
196 | lw t5, 24(sp) | ||
197 | lw t6, 28(sp) | ||
198 | sw t4, 16(sp) | ||
199 | sw t5, 20(sp) | ||
200 | sw t6, 24(sp) | ||
201 | jr t2 | ||
202 | /* Unreached */ | ||
203 | |||
204 | einval: li v0, -ENOSYS | ||
205 | jr ra | ||
206 | END(sys_syscall) | ||
207 | |||
208 | #ifdef CONFIG_MIPS_MT_FPAFF | ||
209 | /* | ||
210 | * For FPU affinity scheduling on MIPS MT processors, we need to | ||
211 | * intercept sys_sched_xxxaffinity() calls until we get a proper hook | ||
212 | * in kernel/sched/core.c. Considered only temporary we only support | ||
213 | * these hooks for the 32-bit kernel - there is no MIPS64 MT processor | ||
214 | * atm. | ||
215 | */ | ||
216 | #define sys_sched_setaffinity mipsmt_sys_sched_setaffinity | ||
217 | #define sys_sched_getaffinity mipsmt_sys_sched_getaffinity | ||
218 | #endif /* CONFIG_MIPS_MT_FPAFF */ | ||
219 | |||
220 | #define __SYSCALL(nr, entry) PTR entry | ||
221 | .align 2 | ||
222 | .type sys_call_table, @object | ||
223 | EXPORT(sys_call_table) | ||
224 | #include <asm/syscall_table_32_o32.h> | ||
225 | #undef __SYSCALL | ||