|
|
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)
190: incl %ecx
191: pushl %ecx
192: call _do_signal
193: popl %ecx
194: testl %eax, %eax
195: jne 1b # see if we need to switch tasks, or do more signals
196: 2: popl %ebx
197: popl %ecx
198: popl %edx
199: popl %esi
200: popl %edi
201: popl %ebp
202: popl %eax
203: pop %ds
204: pop %es
205: pop %fs
206: pop %gs
207: addl $4,%esp # skip the orig_eax
208: iret
209:
210: .align 2
211: _irq13:
212: pushl %eax
213: xorb %al,%al
214: outb %al,$0xF0
215: movb $0x20,%al
216: outb %al,$0x20
217: jmp 1f
218: 1: jmp 1f
219: 1: outb %al,$0xA0
220: popl %eax
221: _coprocessor_error:
222: pushl $-1 # mark this as an int.
223: SAVE_ALL
224: pushl $ret_from_sys_call
225: jmp _math_error
226:
227: .align 2
228: _device_not_available:
229: pushl $-1 # mark this as an int
230: SAVE_ALL
231: pushl $ret_from_sys_call
232: clts # clear TS so that we can use math
233: movl %cr0,%eax
234: testl $0x4,%eax # EM (math emulation bit)
235: je _math_state_restore
236: pushl $0 # temporary storage for ORIG_EIP
237: call _math_emulate
238: addl $4,%esp
239: ret
240:
241: .align 2
242: _keyboard_interrupt:
243: pushl $-1
244: SAVE_ALL
245: ACK_FIRST(0x02)
246: sti
247: call _do_keyboard
248: cli
249: UNBLK_FIRST(0x02)
250: jmp ret_from_sys_call
251:
252: .align 2
253: _IRQ3_interrupt:
254: pushl $-1
255: SAVE_ALL
256: ACK_FIRST(0x08)
257: sti
258: call _do_IRQ3
259: cli
260: UNBLK_FIRST(0x08)
261: jmp ret_from_sys_call
262:
263: .align 2
264: _IRQ4_interrupt:
265: pushl $-1
266: SAVE_ALL
267: ACK_FIRST(0x10)
268: sti
269: call _do_IRQ4
270: cli
271: UNBLK_FIRST(0x10)
272: jmp ret_from_sys_call
273:
274: .align 2
275: _timer_interrupt:
276: pushl $-1 # mark this as an int
277: SAVE_ALL
278: ACK_FIRST(0x01)
279: sti
280: incl _jiffies
281: movl CS(%esp),%eax
282: andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
283: pushl %eax
284: call _do_timer # 'do_timer(long CPL)' does everything from
285: addl $4,%esp # task switching to accounting ...
286: cli
287: UNBLK_FIRST(0x01)
288: jmp ret_from_sys_call
289:
290: .align 2
291: _hd_interrupt:
292: pushl $-1
293: SAVE_ALL
294: ACK_SECOND(0x40)
295: andl $0xfffeffff,_timer_active
296: xorl %edx,%edx
297: xchgl _do_hd,%edx
298: testl %edx,%edx
299: jne 1f
300: movl $_unexpected_hd_interrupt,%edx
301: 1: call *%edx # "interesting" way of handling intr.
302: cli
303: UNBLK_SECOND(0x40)
304: jmp ret_from_sys_call
305:
306: .align 2
307: _sys_execve:
308: lea (EIP+4)(%esp),%eax # don't forget about the return address.
309: pushl %eax
310: call _do_execve
311: addl $4,%esp
312: ret
313:
314: _divide_error:
315: pushl $0 # no error code
316: pushl $_do_divide_error
317: error_code:
318: push %fs
319: push %es
320: push %ds
321: pushl %eax
322: pushl %ebp
323: pushl %edi
324: pushl %esi
325: pushl %edx
326: pushl %ecx
327: pushl %ebx
328: cld
329: movl $-1, %eax
330: xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. )
331: xorl %ebx,%ebx # zero ebx
332: mov %gs,%bx # get the lower order bits of gs
333: xchgl %ebx, GS(%esp) # get the address and save gs.
334: pushl %eax # push the error code
335: lea 52(%esp),%edx
336: pushl %edx
337: movl $0x10,%edx
338: mov %dx,%ds
339: mov %dx,%es
340: movl $0x17,%edx
341: mov %dx,%fs
342: call *%ebx
343: addl $8,%esp
344: jmp ret_from_sys_call
345:
346: _debug:
347: pushl $0
348: pushl $_do_int3 # _do_debug
349: jmp error_code
350:
351: _nmi:
352: pushl $0
353: pushl $_do_nmi
354: jmp error_code
355:
356: _int3:
357: pushl $0
358: pushl $_do_int3
359: jmp error_code
360:
361: _overflow:
362: pushl $0
363: pushl $_do_overflow
364: jmp error_code
365:
366: _bounds:
367: pushl $0
368: pushl $_do_bounds
369: jmp error_code
370:
371: _invalid_op:
372: pushl $0
373: pushl $_do_invalid_op
374: jmp error_code
375:
376: _coprocessor_segment_overrun:
377: pushl $0
378: pushl $_do_coprocessor_segment_overrun
379: jmp error_code
380:
381: _reserved:
382: pushl $0
383: pushl $_do_reserved
384: jmp error_code
385:
386: _double_fault:
387: pushl $_do_double_fault
388: jmp error_code
389:
390: _invalid_TSS:
391: pushl $_do_invalid_TSS
392: jmp error_code
393:
394: _segment_not_present:
395: pushl $_do_segment_not_present
396: jmp error_code
397:
398: _stack_segment:
399: pushl $_do_stack_segment
400: jmp error_code
401:
402: _general_protection:
403: pushl $_do_general_protection
404: jmp error_code
405:
406: _alignment_check:
407: pushl $_do_alignment_check
408: jmp error_code
409:
410: _page_fault:
411: pushl $_do_page_fault
412: jmp error_code
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.