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,_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 handle_bottom_half:
143 pushfl
144 incl _intr_count
145 sti
146 call _do_bottom_half
147 popfl
148 decl _intr_count
149 jmp 9f
150 .align 4
151 reschedule:
152 pushl $ret_from_sys_call
153 jmp _schedule
154 .align 4
155 _system_call:
156 pushl %eax # save orig_eax
157 SAVE_ALL
158 movl $-ENOSYS,EAX(%esp)
159 cmpl _NR_syscalls,%eax
160 jae ret_from_sys_call
161 movl _current,%ebx
162 andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors
163 movl $0,errno(%ebx)
164 testb $0x20,flags(%ebx) # PF_TRACESYS
165 jne 1f
166 call _sys_call_table(,%eax,4)
167 movl %eax,EAX(%esp) # save the return value
168 movl errno(%ebx),%edx
169 negl %edx
170 je ret_from_sys_call
171 movl %edx,EAX(%esp)
172 orl $(CF_MASK),EFLAGS(%esp) # set carry to indicate error
173 jmp ret_from_sys_call
174 .align 4
175 1: call _syscall_trace
176 movl ORIG_EAX(%esp),%eax
177 call _sys_call_table(,%eax,4)
178 movl %eax,EAX(%esp) # save the return value
179 movl _current,%eax
180 movl errno(%eax),%edx
181 negl %edx
182 je 1f
183 movl %edx,EAX(%esp)
184 orl $(CF_MASK),EFLAGS(%esp) # set carry to indicate error
185 1: call _syscall_trace
186
187 .align 4,0x90
188 ret_from_sys_call:
189 cmpl $0,_intr_count
190 jne 2f
191 movl _bh_mask,%eax
192 andl _bh_active,%eax
193 jne handle_bottom_half
194 9: movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are
195 testl $(VM_MASK),%eax # different then
196 jne 1f
197 cmpw $(USER_CS),CS(%esp) # was old code segment supervisor ?
198 jne 2f
199 cmpw $(USER_DS),OLDSS(%esp) # was stack segment user segment ?
200 jne 2f
201 1: sti
202 orl $(IF_MASK),%eax # these just try to make sure
203 andl $~NT_MASK,%eax # the program doesn't do anything
204 movl %eax,EFLAGS(%esp) # stupid
205 cmpl $0,_need_resched
206 jne reschedule
207 movl _current,%eax
208 cmpl _task,%eax # task[0] cannot have signals
209 je 2f
210 cmpl $0,state(%eax) # state
211 jne reschedule
212 cmpl $0,counter(%eax) # counter
213 je reschedule
214 movl blocked(%eax),%ecx
215 movl %ecx,%ebx # save blocked in %ebx for signal handling
216 notl %ecx
217 andl signal(%eax),%ecx
218 jne signal_return
219 2: RESTORE_ALL
220 .align 4
221 signal_return:
222 movl %esp,%ecx
223 pushl %ecx
224 testl $(VM_MASK),EFLAGS(%ecx)
225 jne v86_signal_return
226 pushl %ebx
227 call _do_signal
228 popl %ebx
229 popl %ebx
230 RESTORE_ALL
231 .align 4
232 v86_signal_return:
233 call _save_v86_state
234 movl %eax,%esp
235 pushl %eax
236 pushl %ebx
237 call _do_signal
238 popl %ebx
239 popl %ebx
240 RESTORE_ALL
241
242 .align 4
243 _divide_error:
244 pushl $0 # no error code
245 pushl $_do_divide_error
246 .align 4,0x90
247 error_code:
248 push %fs
249 push %es
250 push %ds
251 pushl %eax
252 pushl %ebp
253 pushl %edi
254 pushl %esi
255 pushl %edx
256 pushl %ecx
257 pushl %ebx
258 cld
259 movl $-1, %eax
260 xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. )
261 xorl %ebx,%ebx # zero ebx
262 mov %gs,%bx # get the lower order bits of gs
263 xchgl %ebx, GS(%esp) # get the address and save gs.
264 pushl %eax # push the error code
265 lea 4(%esp),%edx
266 pushl %edx
267 movl $(KERNEL_DS),%edx
268 mov %dx,%ds
269 mov %dx,%es
270 movl $(USER_DS),%edx
271 mov %dx,%fs
272 call *%ebx
273 addl $8,%esp
274 jmp ret_from_sys_call
275
276 .align 4
277 _coprocessor_error:
278 pushl $0
279 pushl $_do_coprocessor_error
280 jmp error_code
281
282 .align 4
283 _device_not_available:
284 pushl $-1 # mark this as an int
285 SAVE_ALL
286 pushl $ret_from_sys_call
287 movl %cr0,%eax
288 testl $0x4,%eax # EM (math emulation bit)
289 je _math_state_restore
290 pushl $0 # temporary storage for ORIG_EIP
291 call _math_emulate
292 addl $4,%esp
293 ret
294
295 .align 4
296 _debug:
297 pushl $0
298 pushl $_do_debug
299 jmp error_code
300
301 .align 4
302 _nmi:
303 pushl $0
304 pushl $_do_nmi
305 jmp error_code
306
307 .align 4
308 _int3:
309 pushl $0
310 pushl $_do_int3
311 jmp error_code
312
313 .align 4
314 _overflow:
315 pushl $0
316 pushl $_do_overflow
317 jmp error_code
318
319 .align 4
320 _bounds:
321 pushl $0
322 pushl $_do_bounds
323 jmp error_code
324
325 .align 4
326 _invalid_op:
327 pushl $0
328 pushl $_do_invalid_op
329 jmp error_code
330
331 .align 4
332 _coprocessor_segment_overrun:
333 pushl $0
334 pushl $_do_coprocessor_segment_overrun
335 jmp error_code
336
337 .align 4
338 _reserved:
339 pushl $0
340 pushl $_do_reserved
341 jmp error_code
342
343 .align 4
344 _double_fault:
345 pushl $_do_double_fault
346 jmp error_code
347
348 .align 4
349 _invalid_TSS:
350 pushl $_do_invalid_TSS
351 jmp error_code
352
353 .align 4
354 _segment_not_present:
355 pushl $_do_segment_not_present
356 jmp error_code
357
358 .align 4
359 _stack_segment:
360 pushl $_do_stack_segment
361 jmp error_code
362
363 .align 4
364 _general_protection:
365 pushl $_do_general_protection
366 jmp error_code
367
368 .align 4
369 _alignment_check:
370 pushl $_do_alignment_check
371 jmp error_code
372
373 .align 4
374 _page_fault:
375 pushl $_do_page_fault
376 jmp error_code