1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <linux/segment.h>
44
45 EBX = 0x00
46 ECX = 0x04
47 EDX = 0x08
48 ESI = 0x0C
49 EDI = 0x10
50 EBP = 0x14
51 EAX = 0x18
52 DS = 0x1C
53 ES = 0x20
54 FS = 0x24
55 GS = 0x28
56 ORIG_EAX = 0x2C
57 EIP = 0x30
58 CS = 0x34
59 EFLAGS = 0x38
60 OLDESP = 0x3C
61 OLDSS = 0x40
62
63 CF_MASK = 0x00000001
64 IF_MASK = 0x00000200
65 NT_MASK = 0x00004000
66 VM_MASK = 0x00020000
67
68
69
70
71 state = 0
72 counter = 4
73 priority = 8
74 signal = 12
75 blocked = 16
76 flags = 20
77 errno = 24
78
79 ENOSYS = 38
80
81 .globl _system_call,_sys_execve,_lcall7
82 .globl _device_not_available, _coprocessor_error
83 .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
84 .globl _double_fault,_coprocessor_segment_overrun
85 .globl _invalid_TSS,_segment_not_present,_stack_segment
86 .globl _general_protection,_reserved
87 .globl _alignment_check,_page_fault
88 .globl ret_from_sys_call
89
90 #define SAVE_ALL \
91 cld; \
92 push %gs; \
93 push %fs; \
94 push %es; \
95 push %ds; \
96 pushl %eax; \
97 pushl %ebp; \
98 pushl %edi; \
99 pushl %esi; \
100 pushl %edx; \
101 pushl %ecx; \
102 pushl %ebx; \
103 movl $KERNEL_DS,%edx; \
104 mov %dx,%ds; \
105 mov %dx,%es; \
106 movl $USER_DS,%edx; \
107 mov %dx,%fs
108
109 #define RESTORE_ALL \
110 popl %ebx; \
111 popl %ecx; \
112 popl %edx; \
113 popl %esi; \
114 popl %edi; \
115 popl %ebp; \
116 popl %eax; \
117 pop %ds; \
118 pop %es; \
119 pop %fs; \
120 pop %gs; \
121 addl $4,%esp; \
122 iret
123
124 .align 4
125 _lcall7:
126 pushfl # We get a different stack layout with call gates,
127 pushl %eax # which has to be cleaned up later..
128 SAVE_ALL
129 movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
130 movl CS(%esp),%edx # this is eip..
131 movl EFLAGS(%esp),%ecx # and this is cs..
132 movl %eax,EFLAGS(%esp) #
133 movl %edx,EIP(%esp) # Now we move them to their "normal" places
134 movl %ecx,CS(%esp) #
135 movl %esp,%eax
136 pushl %eax
137 call _iABI_emulate
138 popl %eax
139 jmp ret_from_sys_call
140
141 .align 4
142 reschedule:
143 pushl $ret_from_sys_call
144 jmp _schedule
145 .align 4
146 _system_call:
147 pushl %eax # save orig_eax
148 SAVE_ALL
149 movl $-ENOSYS,EAX(%esp)
150 cmpl _NR_syscalls,%eax
151 jae ret_from_sys_call
152 movl _current,%ebx
153 movl $0,errno(%ebx)
154 andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors
155 testl $0x20,flags(%ebx) # PF_TRACESYS
156 jne 1f
157 call _sys_call_table(,%eax,4)
158 movl %eax,EAX(%esp) # save the return value
159 movl _current,%eax
160 movl errno(%eax),%edx
161 negl %edx
162 je ret_from_sys_call
163 movl %edx,EAX(%esp)
164 orl $CF_MASK,EFLAGS(%esp) # set carry to indicate error
165 jmp ret_from_sys_call
166 .align 4
167 1: call _syscall_trace
168 movl ORIG_EAX(%esp),%eax
169 call _sys_call_table(,%eax,4)
170 movl %eax,EAX(%esp) # save the return value
171 movl _current,%eax
172 movl errno(%eax),%edx
173 negl %edx
174 je 1f
175 movl %edx,EAX(%esp)
176 orl $CF_MASK,EFLAGS(%esp) # set carry to indicate error
177 1: call _syscall_trace
178
179 .align 4,0x90
180 ret_from_sys_call:
181 movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are
182 testl $VM_MASK,%eax # different then
183 jne 1f
184 cmpw $USER_CS,CS(%esp) # was old code segment supervisor ?
185 jne 2f
186 cmpw $USER_DS,OLDSS(%esp) # was stack segment user segment ?
187 jne 2f
188 1: sti # slow interrupts get here with interrupts disabled
189 orl $IF_MASK,%eax # these just try to make sure
190 andl $~NT_MASK,%eax # the program doesn't do anything
191 movl %eax,EFLAGS(%esp) # stupid
192 cmpl $0,_need_resched
193 jne reschedule
194 movl _current,%eax
195 cmpl _task,%eax # task[0] cannot have signals
196 je 2f
197 cmpl $0,state(%eax) # state
198 jne reschedule
199 cmpl $0,counter(%eax) # counter
200 je reschedule
201 movl blocked(%eax),%ecx
202 movl %ecx,%ebx # save blocked in %ebx for signal handling
203 notl %ecx
204 andl signal(%eax),%ecx
205 jne signal_return
206 2: RESTORE_ALL
207 .align 4
208 signal_return:
209 movl %esp,%ecx
210 pushl %ecx
211 testl $VM_MASK,EFLAGS(%ecx)
212 jne v86_signal_return
213 pushl %ebx
214 call _do_signal
215 popl %ebx
216 popl %ebx
217 RESTORE_ALL
218 .align 4
219 v86_signal_return:
220 call _save_v86_state
221 movl %eax,%esp
222 pushl %eax
223 pushl %ebx
224 call _do_signal
225 popl %ebx
226 popl %ebx
227 RESTORE_ALL
228
229 .align 4
230 _sys_execve:
231 lea (EIP+4)(%esp),%eax # don't forget about the return address.
232 pushl %eax
233 call _do_execve
234 addl $4,%esp
235 ret
236
237 .align 4
238 _divide_error:
239 pushl $0 # no error code
240 pushl $_do_divide_error
241 .align 4,0x90
242 error_code:
243 push %fs
244 push %es
245 push %ds
246 pushl %eax
247 pushl %ebp
248 pushl %edi
249 pushl %esi
250 pushl %edx
251 pushl %ecx
252 pushl %ebx
253 cld
254 movl $-1, %eax
255 xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. )
256 xorl %ebx,%ebx # zero ebx
257 mov %gs,%bx # get the lower order bits of gs
258 xchgl %ebx, GS(%esp) # get the address and save gs.
259 pushl %eax # push the error code
260 lea 4(%esp),%edx
261 pushl %edx
262 movl $KERNEL_DS,%edx
263 mov %dx,%ds
264 mov %dx,%es
265 movl $USER_DS,%edx
266 mov %dx,%fs
267 call *%ebx
268 addl $8,%esp
269 jmp ret_from_sys_call
270
271 .align 4
272 _coprocessor_error:
273 pushl $0
274 pushl $_do_coprocessor_error
275 jmp error_code
276
277 .align 4
278 _device_not_available:
279 pushl $-1 # mark this as an int
280 SAVE_ALL
281 pushl $ret_from_sys_call
282 clts # clear TS so that we can use math
283 movl %cr0,%eax
284 testl $0x4,%eax # EM (math emulation bit)
285 je _math_state_restore
286 pushl $0 # temporary storage for ORIG_EIP
287 call _math_emulate
288 addl $4,%esp
289 ret
290
291 .align 4
292 _debug:
293 pushl $0
294 pushl $_do_debug
295 jmp error_code
296
297 .align 4
298 _nmi:
299 pushl $0
300 pushl $_do_nmi
301 jmp error_code
302
303 .align 4
304 _int3:
305 pushl $0
306 pushl $_do_int3
307 jmp error_code
308
309 .align 4
310 _overflow:
311 pushl $0
312 pushl $_do_overflow
313 jmp error_code
314
315 .align 4
316 _bounds:
317 pushl $0
318 pushl $_do_bounds
319 jmp error_code
320
321 .align 4
322 _invalid_op:
323 pushl $0
324 pushl $_do_invalid_op
325 jmp error_code
326
327 .align 4
328 _coprocessor_segment_overrun:
329 pushl $0
330 pushl $_do_coprocessor_segment_overrun
331 jmp error_code
332
333 .align 4
334 _reserved:
335 pushl $0
336 pushl $_do_reserved
337 jmp error_code
338
339 .align 4
340 _double_fault:
341 pushl $_do_double_fault
342 jmp error_code
343
344 .align 4
345 _invalid_TSS:
346 pushl $_do_invalid_TSS
347 jmp error_code
348
349 .align 4
350 _segment_not_present:
351 pushl $_do_segment_not_present
352 jmp error_code
353
354 .align 4
355 _stack_segment:
356 pushl $_do_stack_segment
357 jmp error_code
358
359 .align 4
360 _general_protection:
361 pushl $_do_general_protection
362 jmp error_code
363
364 .align 4
365 _alignment_check:
366 pushl $_do_alignment_check
367 jmp error_code
368
369 .align 4
370 _page_fault:
371 pushl $_do_page_fault
372 jmp error_code