|
|
1.1 root 1: /*
2: * linux/kernel/sys_call.S
3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
7: /*
8: * sys_call.S contains the system-call and fault low-level handling routines.
9: * This also contains the timer-interrupt handler, as well as all interrupts
10: * and faults that can result in a task-switch.
11: *
12: * NOTE: This code handles signal-recognition, which happens every time
13: * after a timer-interrupt and after each system call.
14: *
15: * Stack layout in 'ret_from_system_call':
16: * ptrace needs to have all regs on the stack.
17: * if the order here is changed, it needs to be
18: * updated in fork.c:copy_process, signal.c:do_signal,
19: * ptrace.c and ptrace.h
20: *
21: * 0(%esp) - %ebx
22: * 4(%esp) - %ecx
23: * 8(%esp) - %edx
24: * C(%esp) - %esi
25: * 10(%esp) - %edi
26: * 14(%esp) - %ebp
27: * 18(%esp) - %eax
28: * 1C(%esp) - %ds
29: * 20(%esp) - %es
30: * 24(%esp) - %fs
31: * 28(%esp) - %gs
32: * 2C(%esp) - orig_eax
33: * 30(%esp) - %eip
34: * 34(%esp) - %cs
35: * 38(%esp) - %eflags
36: * 3C(%esp) - %oldesp
37: * 40(%esp) - %oldss
38: */
39:
40: SIG_CHLD = 17
41:
42: EBX = 0x00
43: ECX = 0x04
44: EDX = 0x08
45: ESI = 0x0C
46: EDI = 0x10
47: EBP = 0x14
48: EAX = 0x18
49: DS = 0x1C
50: ES = 0x20
51: FS = 0x24
52: GS = 0x28
53: ORIG_EAX = 0x2C
54: EIP = 0x30
55: CS = 0x34
56: EFLAGS = 0x38
57: OLDESP = 0x3C
58: OLDSS = 0x40
59:
60: /*
61: * these are offsets into the task-struct.
62: */
63: state = 0
64: counter = 4
65: priority = 8
66: signal = 12
67: sigaction = 16 # MUST be 16 (=len of sigaction)
68: blocked = (33*16)
69:
70: /*
71: * offsets within sigaction
72: */
73: sa_handler = 0
74: sa_mask = 4
75: sa_flags = 8
76: sa_restorer = 12
77:
78: ENOSYS = 38
79:
80: /*
81: * Ok, I get parallel printer interrupts while using the floppy for some
82: * strange reason. Urgel. Now I just ignore them.
83: */
84: .globl _system_call,_timer_interrupt,_sys_execve
85: .globl _device_not_available, _coprocessor_error
86: .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
87: .globl _double_fault,_coprocessor_segment_overrun
88: .globl _invalid_TSS,_segment_not_present,_stack_segment
89: .globl _general_protection,_irq13,_reserved
90: .globl _alignment_check,_page_fault
91: .globl _keyboard_interrupt,_hd_interrupt
92: .globl _IRQ3_interrupt,_IRQ4_interrupt
93:
94: #define SAVE_ALL \
95: cld; \
96: push %gs; \
97: push %fs; \
98: push %es; \
99: push %ds; \
100: pushl %eax; \
101: pushl %ebp; \
102: pushl %edi; \
103: pushl %esi; \
104: pushl %edx; \
105: pushl %ecx; \
106: pushl %ebx; \
107: movl $0x10,%edx; \
108: mov %dx,%ds; \
109: mov %dx,%es; \
110: movl $0x17,%edx; \
111: mov %dx,%fs
112:
113: #define ACK_FIRST(mask) \
114: inb $0x21,%al; \
115: jmp 1f; \
116: 1: jmp 1f; \
117: 1: orb $(mask),%al; \
118: outb %al,$0x21; \
119: jmp 1f; \
120: 1: jmp 1f; \
121: 1: movb $0x20,%al; \
122: outb %al,$0x20
123:
124: #define ACK_SECOND(mask) \
125: inb $0xA1,%al; \
126: jmp 1f; \
127: 1: jmp 1f; \
128: 1: orb $(mask),%al; \
129: outb %al,$0xA1; \
130: jmp 1f; \
131: 1: jmp 1f; \
132: 1: movb $0x20,%al; \
133: outb %al,$0xA0 \
134: jmp 1f; \
135: 1: jmp 1f; \
136: 1: outb %al,$0x20
137:
138: #define UNBLK_FIRST(mask) \
139: inb $0x21,%al; \
140: jmp 1f; \
141: 1: jmp 1f; \
142: 1: andb $~(mask),%al; \
143: outb %al,$0x21
144:
145: #define UNBLK_SECOND(mask) \
146: inb $0xA1,%al; \
147: jmp 1f; \
148: 1: jmp 1f; \
149: 1: andb $~(mask),%al; \
150: outb %al,$0xA1
151:
152: .align 2
153: bad_sys_call:
154: movl $-ENOSYS,EAX(%esp)
155: jmp ret_from_sys_call
156: .align 2
157: reschedule:
158: pushl $ret_from_sys_call
159: jmp _schedule
160: .align 2
161: _system_call:
162: pushl %eax # save orig_eax
163: SAVE_ALL
164: cmpl _NR_syscalls,%eax
165: jae bad_sys_call
166: call _sys_call_table(,%eax,4)
167: movl %eax,EAX(%esp) # save the return value
168: ret_from_sys_call:
169: cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
170: jne 2f
171: cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
172: jne 2f
173: 1: movl _current,%eax
174: cmpl _task,%eax # task[0] cannot have signals
175: je 2f
176: cmpl $0,_need_resched
177: jne reschedule
178: cmpl $0,state(%eax) # state
179: jne reschedule
180: cmpl $0,counter(%eax) # counter
181: je reschedule
182: movl signal(%eax),%ebx
183: movl blocked(%eax),%ecx
184: notl %ecx
185: andl %ebx,%ecx
186: bsfl %ecx,%ecx
187: je 2f
188: btrl %ecx,%ebx
189: movl %ebx,signal(%eax)
1.1.1.2 ! root 190: movl %esp,%ebx
! 191: pushl %ebx
1.1 root 192: incl %ecx
193: pushl %ecx
194: call _do_signal
195: popl %ecx
1.1.1.2 ! root 196: popl %ebx
1.1 root 197: testl %eax, %eax
198: jne 1b # see if we need to switch tasks, or do more signals
199: 2: popl %ebx
200: popl %ecx
201: popl %edx
202: popl %esi
203: popl %edi
204: popl %ebp
205: popl %eax
206: pop %ds
207: pop %es
208: pop %fs
209: pop %gs
210: addl $4,%esp # skip the orig_eax
211: iret
212:
213: .align 2
214: _irq13:
215: pushl %eax
216: xorb %al,%al
217: outb %al,$0xF0
218: movb $0x20,%al
219: outb %al,$0x20
220: jmp 1f
221: 1: jmp 1f
222: 1: outb %al,$0xA0
223: popl %eax
224: _coprocessor_error:
225: pushl $-1 # mark this as an int.
226: SAVE_ALL
227: pushl $ret_from_sys_call
228: jmp _math_error
229:
230: .align 2
231: _device_not_available:
232: pushl $-1 # mark this as an int
233: SAVE_ALL
234: pushl $ret_from_sys_call
235: clts # clear TS so that we can use math
236: movl %cr0,%eax
237: testl $0x4,%eax # EM (math emulation bit)
238: je _math_state_restore
239: pushl $0 # temporary storage for ORIG_EIP
240: call _math_emulate
241: addl $4,%esp
242: ret
243:
244: .align 2
245: _keyboard_interrupt:
246: pushl $-1
247: SAVE_ALL
248: ACK_FIRST(0x02)
249: sti
250: call _do_keyboard
251: cli
252: UNBLK_FIRST(0x02)
253: jmp ret_from_sys_call
254:
255: .align 2
256: _IRQ3_interrupt:
257: pushl $-1
258: SAVE_ALL
259: ACK_FIRST(0x08)
260: sti
261: call _do_IRQ3
262: cli
263: UNBLK_FIRST(0x08)
264: jmp ret_from_sys_call
265:
266: .align 2
267: _IRQ4_interrupt:
268: pushl $-1
269: SAVE_ALL
270: ACK_FIRST(0x10)
271: sti
272: call _do_IRQ4
273: cli
274: UNBLK_FIRST(0x10)
275: jmp ret_from_sys_call
276:
277: .align 2
278: _timer_interrupt:
279: pushl $-1 # mark this as an int
280: SAVE_ALL
281: ACK_FIRST(0x01)
282: sti
283: incl _jiffies
284: movl CS(%esp),%eax
285: andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
286: pushl %eax
287: call _do_timer # 'do_timer(long CPL)' does everything from
288: addl $4,%esp # task switching to accounting ...
289: cli
290: UNBLK_FIRST(0x01)
291: jmp ret_from_sys_call
292:
293: .align 2
294: _hd_interrupt:
295: pushl $-1
296: SAVE_ALL
297: ACK_SECOND(0x40)
298: andl $0xfffeffff,_timer_active
299: xorl %edx,%edx
300: xchgl _do_hd,%edx
301: testl %edx,%edx
302: jne 1f
303: movl $_unexpected_hd_interrupt,%edx
304: 1: call *%edx # "interesting" way of handling intr.
305: cli
306: UNBLK_SECOND(0x40)
307: jmp ret_from_sys_call
308:
309: .align 2
310: _sys_execve:
311: lea (EIP+4)(%esp),%eax # don't forget about the return address.
312: pushl %eax
313: call _do_execve
314: addl $4,%esp
315: ret
316:
317: _divide_error:
318: pushl $0 # no error code
319: pushl $_do_divide_error
320: error_code:
321: push %fs
322: push %es
323: push %ds
324: pushl %eax
325: pushl %ebp
326: pushl %edi
327: pushl %esi
328: pushl %edx
329: pushl %ecx
330: pushl %ebx
331: cld
332: movl $-1, %eax
333: xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. )
334: xorl %ebx,%ebx # zero ebx
335: mov %gs,%bx # get the lower order bits of gs
336: xchgl %ebx, GS(%esp) # get the address and save gs.
337: pushl %eax # push the error code
338: lea 52(%esp),%edx
339: pushl %edx
340: movl $0x10,%edx
341: mov %dx,%ds
342: mov %dx,%es
343: movl $0x17,%edx
344: mov %dx,%fs
345: call *%ebx
346: addl $8,%esp
347: jmp ret_from_sys_call
348:
349: _debug:
350: pushl $0
351: pushl $_do_int3 # _do_debug
352: jmp error_code
353:
354: _nmi:
355: pushl $0
356: pushl $_do_nmi
357: jmp error_code
358:
359: _int3:
360: pushl $0
361: pushl $_do_int3
362: jmp error_code
363:
364: _overflow:
365: pushl $0
366: pushl $_do_overflow
367: jmp error_code
368:
369: _bounds:
370: pushl $0
371: pushl $_do_bounds
372: jmp error_code
373:
374: _invalid_op:
375: pushl $0
376: pushl $_do_invalid_op
377: jmp error_code
378:
379: _coprocessor_segment_overrun:
380: pushl $0
381: pushl $_do_coprocessor_segment_overrun
382: jmp error_code
383:
384: _reserved:
385: pushl $0
386: pushl $_do_reserved
387: jmp error_code
388:
389: _double_fault:
390: pushl $_do_double_fault
391: jmp error_code
392:
393: _invalid_TSS:
394: pushl $_do_invalid_TSS
395: jmp error_code
396:
397: _segment_not_present:
398: pushl $_do_segment_not_present
399: jmp error_code
400:
401: _stack_segment:
402: pushl $_do_stack_segment
403: jmp error_code
404:
405: _general_protection:
406: pushl $_do_general_protection
407: jmp error_code
408:
409: _alignment_check:
410: pushl $_do_alignment_check
411: jmp error_code
412:
413: _page_fault:
414: pushl $_do_page_fault
415: jmp error_code
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.