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 dbgreg6 = 52
79 dbgreg7 = 56
80
81 ENOSYS = 38
82
83 .globl _system_call,_lcall7
84 .globl _device_not_available, _coprocessor_error
85 .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
86 .globl _double_fault,_coprocessor_segment_overrun
87 .globl _invalid_TSS,_segment_not_present,_stack_segment
88 .globl _general_protection,_reserved
89 .globl _alignment_check,_page_fault
90 .globl ret_from_sys_call
91
92 #define SAVE_ALL \
93 cld; \
94 push %gs; \
95 push %fs; \
96 push %es; \
97 push %ds; \
98 pushl %eax; \
99 pushl %ebp; \
100 pushl %edi; \
101 pushl %esi; \
102 pushl %edx; \
103 pushl %ecx; \
104 pushl %ebx; \
105 movl $(KERNEL_DS),%edx; \
106 mov %dx,%ds; \
107 mov %dx,%es; \
108 movl $(USER_DS),%edx; \
109 mov %dx,%fs;
110
111 #define RESTORE_ALL \
112 cmpw $(KERNEL_CS),CS(%esp); \
113 je 1f; \
114 movl _current,%eax; \
115 movl dbgreg7(%eax),%ebx; \
116 movl %ebx,%db7; \
117 1: popl %ebx; \
118 popl %ecx; \
119 popl %edx; \
120 popl %esi; \
121 popl %edi; \
122 popl %ebp; \
123 popl %eax; \
124 pop %ds; \
125 pop %es; \
126 pop %fs; \
127 pop %gs; \
128 addl $4,%esp; \
129 iret
130
131 .align 4
132 _lcall7:
133 pushfl # We get a different stack layout with call gates,
134 pushl %eax # which has to be cleaned up later..
135 SAVE_ALL
136 movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
137 movl CS(%esp),%edx # this is eip..
138 movl EFLAGS(%esp),%ecx # and this is cs..
139 movl %eax,EFLAGS(%esp) #
140 movl %edx,EIP(%esp) # Now we move them to their "normal" places
141 movl %ecx,CS(%esp) #
142 movl %esp,%eax
143 pushl %eax
144 call _iABI_emulate
145 popl %eax
146 jmp ret_from_sys_call
147
148 .align 4
149 handle_bottom_half:
150 pushfl
151 incl _intr_count
152 sti
153 call _do_bottom_half
154 popfl
155 decl _intr_count
156 jmp 9f
157 .align 4
158 reschedule:
159 pushl $ret_from_sys_call
160 jmp _schedule
161 .align 4
162 _system_call:
163 pushl %eax # save orig_eax
164 SAVE_ALL
165 movl $-ENOSYS,EAX(%esp)
166 cmpl _NR_syscalls,%eax
167 jae ret_from_sys_call
168 movl _current,%ebx
169 andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors
170 movl $0,errno(%ebx)
171 movl %db6,%edx
172 movl %edx,dbgreg6(%ebx) # save current hardware debugging status
173 testb $0x20,flags(%ebx) # PF_TRACESYS
174 jne 1f
175 call _sys_call_table(,%eax,4)
176 movl %eax,EAX(%esp) # save the return value
177 movl errno(%ebx),%edx
178 negl %edx
179 je ret_from_sys_call
180 movl %edx,EAX(%esp)
181 orl $(CF_MASK),EFLAGS(%esp) # set carry to indicate error
182 jmp ret_from_sys_call
183 .align 4
184 1: call _syscall_trace
185 movl ORIG_EAX(%esp),%eax
186 call _sys_call_table(,%eax,4)
187 movl %eax,EAX(%esp) # save the return value
188 movl _current,%eax
189 movl errno(%eax),%edx
190 negl %edx
191 je 1f
192 movl %edx,EAX(%esp)
193 orl $(CF_MASK),EFLAGS(%esp) # set carry to indicate error
194 1: call _syscall_trace
195
196 .align 4,0x90
197 ret_from_sys_call:
198 cmpl $0,_intr_count
199 jne 2f
200 movl _bh_mask,%eax
201 andl _bh_active,%eax
202 jne handle_bottom_half
203 9: movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are
204 testl $(VM_MASK),%eax # different then
205 jne 1f
206 cmpw $(KERNEL_CS),CS(%esp) # was old code segment supervisor ?
207 je 2f
208 1: sti
209 orl $(IF_MASK),%eax # these just try to make sure
210 andl $~NT_MASK,%eax # the program doesn't do anything
211 movl %eax,EFLAGS(%esp) # stupid
212 cmpl $0,_need_resched
213 jne reschedule
214 movl _current,%eax
215 cmpl _task,%eax # task[0] cannot have signals
216 je 2f
217 cmpl $0,state(%eax) # state
218 jne reschedule
219 cmpl $0,counter(%eax) # counter
220 je reschedule
221 movl blocked(%eax),%ecx
222 movl %ecx,%ebx # save blocked in %ebx for signal handling
223 notl %ecx
224 andl signal(%eax),%ecx
225 jne signal_return
226 2: RESTORE_ALL
227 .align 4
228 signal_return:
229 movl %esp,%ecx
230 pushl %ecx
231 testl $(VM_MASK),EFLAGS(%ecx)
232 jne v86_signal_return
233 pushl %ebx
234 call _do_signal
235 popl %ebx
236 popl %ebx
237 RESTORE_ALL
238 .align 4
239 v86_signal_return:
240 call _save_v86_state
241 movl %eax,%esp
242 pushl %eax
243 pushl %ebx
244 call _do_signal
245 popl %ebx
246 popl %ebx
247 RESTORE_ALL
248
249 .align 4
250 _divide_error:
251 pushl $0 # no error code
252 pushl $_do_divide_error
253 .align 4,0x90
254 error_code:
255 push %fs
256 push %es
257 push %ds
258 pushl %eax
259 pushl %ebp
260 pushl %edi
261 pushl %esi
262 pushl %edx
263 pushl %ecx
264 pushl %ebx
265 movl $0,%eax
266 movl %eax,%db7 # disable hardware debugging...
267 cld
268 movl $-1, %eax
269 xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. )
270 xorl %ebx,%ebx # zero ebx
271 mov %gs,%bx # get the lower order bits of gs
272 xchgl %ebx, GS(%esp) # get the address and save gs.
273 pushl %eax # push the error code
274 lea 4(%esp),%edx
275 pushl %edx
276 movl $(KERNEL_DS),%edx
277 mov %dx,%ds
278 mov %dx,%es
279 movl $(USER_DS),%edx
280 mov %dx,%fs
281 pushl %eax
282 movl _current,%eax
283 movl %db6,%edx
284 movl %edx,dbgreg6(%eax) # save current hardware debugging status
285 popl %eax
286 call *%ebx
287 addl $8,%esp
288 jmp ret_from_sys_call
289
290 .align 4
291 _coprocessor_error:
292 pushl $0
293 pushl $_do_coprocessor_error
294 jmp error_code
295
296 .align 4
297 _device_not_available:
298 pushl $-1 # mark this as an int
299 SAVE_ALL
300 pushl $ret_from_sys_call
301 movl %cr0,%eax
302 testl $0x4,%eax # EM (math emulation bit)
303 je _math_state_restore
304 pushl $0 # temporary storage for ORIG_EIP
305 call _math_emulate
306 addl $4,%esp
307 ret
308
309 .align 4
310 _debug:
311 pushl $0
312 pushl $_do_debug
313 jmp error_code
314
315 .align 4
316 _nmi:
317 pushl $0
318 pushl $_do_nmi
319 jmp error_code
320
321 .align 4
322 _int3:
323 pushl $0
324 pushl $_do_int3
325 jmp error_code
326
327 .align 4
328 _overflow:
329 pushl $0
330 pushl $_do_overflow
331 jmp error_code
332
333 .align 4
334 _bounds:
335 pushl $0
336 pushl $_do_bounds
337 jmp error_code
338
339 .align 4
340 _invalid_op:
341 pushl $0
342 pushl $_do_invalid_op
343 jmp error_code
344
345 .align 4
346 _coprocessor_segment_overrun:
347 pushl $0
348 pushl $_do_coprocessor_segment_overrun
349 jmp error_code
350
351 .align 4
352 _reserved:
353 pushl $0
354 pushl $_do_reserved
355 jmp error_code
356
357 .align 4
358 _double_fault:
359 pushl $_do_double_fault
360 jmp error_code
361
362 .align 4
363 _invalid_TSS:
364 pushl $_do_invalid_TSS
365 jmp error_code
366
367 .align 4
368 _segment_not_present:
369 pushl $_do_segment_not_present
370 jmp error_code
371
372 .align 4
373 _stack_segment:
374 pushl $_do_stack_segment
375 jmp error_code
376
377 .align 4
378 _general_protection:
379 pushl $_do_general_protection
380 jmp error_code
381
382 .align 4
383 _alignment_check:
384 pushl $_do_alignment_check
385 jmp error_code
386
387 .align 4
388 _page_fault:
389 pushl $_do_page_fault
390 jmp error_code