|
|
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
1.1.1.3 ! root 92: .globl _IRQ3_interrupt,_IRQ4_interrupt,_IRQ5_interrupt,_IRQ9_interrupt
1.1 root 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
1.1.1.3 ! root 261: pushl $3
! 262: call _do_IRQ
! 263: addl $4,%esp
1.1 root 264: cli
265: UNBLK_FIRST(0x08)
266: jmp ret_from_sys_call
267:
268: .align 2
269: _IRQ4_interrupt:
270: pushl $-1
271: SAVE_ALL
272: ACK_FIRST(0x10)
273: sti
1.1.1.3 ! root 274: pushl $4
! 275: call _do_IRQ
! 276: addl $4,%esp
1.1 root 277: cli
278: UNBLK_FIRST(0x10)
279: jmp ret_from_sys_call
280:
281: .align 2
1.1.1.3 ! root 282: _IRQ5_interrupt:
! 283: pushl $-1
! 284: SAVE_ALL
! 285: ACK_FIRST(0x20)
! 286: sti
! 287: pushl $5
! 288: call _do_IRQ
! 289: addl $4,%esp
! 290: cli
! 291: UNBLK_FIRST(0x20)
! 292: jmp ret_from_sys_call
! 293:
! 294: .align 2
! 295: _IRQ9_interrupt:
! 296: pushl $-1
! 297: SAVE_ALL
! 298: ACK_SECOND(0x02)
! 299: sti
! 300: pushl $9
! 301: call _do_IRQ
! 302: addl $4,%esp
! 303: cli
! 304: UNBLK_SECOND(0x02)
! 305: jmp ret_from_sys_call
! 306:
! 307: .align 2
1.1 root 308: _timer_interrupt:
309: pushl $-1 # mark this as an int
310: SAVE_ALL
311: ACK_FIRST(0x01)
312: sti
313: incl _jiffies
314: movl CS(%esp),%eax
315: andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
316: pushl %eax
317: call _do_timer # 'do_timer(long CPL)' does everything from
318: addl $4,%esp # task switching to accounting ...
319: cli
320: UNBLK_FIRST(0x01)
321: jmp ret_from_sys_call
322:
323: .align 2
324: _hd_interrupt:
325: pushl $-1
326: SAVE_ALL
327: ACK_SECOND(0x40)
328: andl $0xfffeffff,_timer_active
329: xorl %edx,%edx
330: xchgl _do_hd,%edx
331: testl %edx,%edx
332: jne 1f
333: movl $_unexpected_hd_interrupt,%edx
334: 1: call *%edx # "interesting" way of handling intr.
335: cli
336: UNBLK_SECOND(0x40)
337: jmp ret_from_sys_call
338:
339: .align 2
340: _sys_execve:
341: lea (EIP+4)(%esp),%eax # don't forget about the return address.
342: pushl %eax
343: call _do_execve
344: addl $4,%esp
345: ret
346:
347: _divide_error:
348: pushl $0 # no error code
349: pushl $_do_divide_error
350: error_code:
351: push %fs
352: push %es
353: push %ds
354: pushl %eax
355: pushl %ebp
356: pushl %edi
357: pushl %esi
358: pushl %edx
359: pushl %ecx
360: pushl %ebx
361: cld
362: movl $-1, %eax
363: xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. )
364: xorl %ebx,%ebx # zero ebx
365: mov %gs,%bx # get the lower order bits of gs
366: xchgl %ebx, GS(%esp) # get the address and save gs.
367: pushl %eax # push the error code
368: lea 52(%esp),%edx
369: pushl %edx
370: movl $0x10,%edx
371: mov %dx,%ds
372: mov %dx,%es
373: movl $0x17,%edx
374: mov %dx,%fs
375: call *%ebx
376: addl $8,%esp
377: jmp ret_from_sys_call
378:
379: _debug:
380: pushl $0
381: pushl $_do_int3 # _do_debug
382: jmp error_code
383:
384: _nmi:
385: pushl $0
386: pushl $_do_nmi
387: jmp error_code
388:
389: _int3:
390: pushl $0
391: pushl $_do_int3
392: jmp error_code
393:
394: _overflow:
395: pushl $0
396: pushl $_do_overflow
397: jmp error_code
398:
399: _bounds:
400: pushl $0
401: pushl $_do_bounds
402: jmp error_code
403:
404: _invalid_op:
405: pushl $0
406: pushl $_do_invalid_op
407: jmp error_code
408:
409: _coprocessor_segment_overrun:
410: pushl $0
411: pushl $_do_coprocessor_segment_overrun
412: jmp error_code
413:
414: _reserved:
415: pushl $0
416: pushl $_do_reserved
417: jmp error_code
418:
419: _double_fault:
420: pushl $_do_double_fault
421: jmp error_code
422:
423: _invalid_TSS:
424: pushl $_do_invalid_TSS
425: jmp error_code
426:
427: _segment_not_present:
428: pushl $_do_segment_not_present
429: jmp error_code
430:
431: _stack_segment:
432: pushl $_do_stack_segment
433: jmp error_code
434:
435: _general_protection:
436: pushl $_do_general_protection
437: jmp error_code
438:
439: _alignment_check:
440: pushl $_do_alignment_check
441: jmp error_code
442:
443: _page_fault:
444: pushl $_do_page_fault
445: jmp error_code
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.