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 $(KERNEL_CS),CS(%esp) # was old code segment supervisor ?
198 je 2f
199 1: sti
200 orl $(IF_MASK),%eax # these just try to make sure
201 andl $~NT_MASK,%eax # the program doesn't do anything
202 movl %eax,EFLAGS(%esp) # stupid
203 cmpl $0,_need_resched
204 jne reschedule
205 movl _current,%eax
206 cmpl _task,%eax # task[0] cannot have signals
207 je 2f
208 cmpl $0,state(%eax) # state
209 jne reschedule
210 cmpl $0,counter(%eax) # counter
211 je reschedule
212 movl blocked(%eax),%ecx
213 movl %ecx,%ebx # save blocked in %ebx for signal handling
214 notl %ecx
215 andl signal(%eax),%ecx
216 jne signal_return
217 2: RESTORE_ALL
218 .align 4
219 signal_return:
220 movl %esp,%ecx
221 pushl %ecx
222 testl $(VM_MASK),EFLAGS(%ecx)
223 jne v86_signal_return
224 pushl %ebx
225 call _do_signal
226 popl %ebx
227 popl %ebx
228 RESTORE_ALL
229 .align 4
230 v86_signal_return:
231 call _save_v86_state
232 movl %eax,%esp
233 pushl %eax
234 pushl %ebx
235 call _do_signal
236 popl %ebx
237 popl %ebx
238 RESTORE_ALL
239
240 .align 4
241 _divide_error:
242 pushl $0 # no error code
243 pushl $_do_divide_error
244 .align 4,0x90
245 error_code:
246 push %fs
247 push %es
248 push %ds
249 pushl %eax
250 pushl %ebp
251 pushl %edi
252 pushl %esi
253 pushl %edx
254 pushl %ecx
255 pushl %ebx
256 cld
257 movl $-1, %eax
258 xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. )
259 xorl %ebx,%ebx # zero ebx
260 mov %gs,%bx # get the lower order bits of gs
261 xchgl %ebx, GS(%esp) # get the address and save gs.
262 pushl %eax # push the error code
263 lea 4(%esp),%edx
264 pushl %edx
265 movl $(KERNEL_DS),%edx
266 mov %dx,%ds
267 mov %dx,%es
268 movl $(USER_DS),%edx
269 mov %dx,%fs
270 call *%ebx
271 addl $8,%esp
272 jmp ret_from_sys_call
273
274 .align 4
275 _coprocessor_error:
276 pushl $0
277 pushl $_do_coprocessor_error
278 jmp error_code
279
280 .align 4
281 _device_not_available:
282 pushl $-1 # mark this as an int
283 SAVE_ALL
284 pushl $ret_from_sys_call
285 movl %cr0,%eax
286 testl $0x4,%eax # EM (math emulation bit)
287 je _math_state_restore
288 pushl $0 # temporary storage for ORIG_EIP
289 call _math_emulate
290 addl $4,%esp
291 ret
292
293 .align 4
294 _debug:
295 pushl $0
296 pushl $_do_debug
297 jmp error_code
298
299 .align 4
300 _nmi:
301 pushl $0
302 pushl $_do_nmi
303 jmp error_code
304
305 .align 4
306 _int3:
307 pushl $0
308 pushl $_do_int3
309 jmp error_code
310
311 .align 4
312 _overflow:
313 pushl $0
314 pushl $_do_overflow
315 jmp error_code
316
317 .align 4
318 _bounds:
319 pushl $0
320 pushl $_do_bounds
321 jmp error_code
322
323 .align 4
324 _invalid_op:
325 pushl $0
326 pushl $_do_invalid_op
327 jmp error_code
328
329 .align 4
330 _coprocessor_segment_overrun:
331 pushl $0
332 pushl $_do_coprocessor_segment_overrun
333 jmp error_code
334
335 .align 4
336 _reserved:
337 pushl $0
338 pushl $_do_reserved
339 jmp error_code
340
341 .align 4
342 _double_fault:
343 pushl $_do_double_fault
344 jmp error_code
345
346 .align 4
347 _invalid_TSS:
348 pushl $_do_invalid_TSS
349 jmp error_code
350
351 .align 4
352 _segment_not_present:
353 pushl $_do_segment_not_present
354 jmp error_code
355
356 .align 4
357 _stack_segment:
358 pushl $_do_stack_segment
359 jmp error_code
360
361 .align 4
362 _general_protection:
363 pushl $_do_general_protection
364 jmp error_code
365
366 .align 4
367 _alignment_check:
368 pushl $_do_alignment_check
369 jmp error_code
370
371 .align 4
372 _page_fault:
373 pushl $_do_page_fault
374 jmp error_code