|
|
1.1 root 1: /*
2: * linux/kernel/system_call.s
3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
7: /*
8: * system_call.s contains the system-call low-level handling routines.
9: * This also contains the timer-interrupt handler, as some of the code is
10: * the same. The hd- and flopppy-interrupts are also here.
11: *
12: * NOTE: This code handles signal-recognition, which happens every time
13: * after a timer-interrupt and after each system call. Ordinary interrupts
14: * don't handle signal-recognition, as that would clutter them up totally
15: * unnecessarily.
16: *
17: * Stack layout in 'ret_from_system_call':
1.1.1.2 ! root 18: * ptrace needs to have all regs on the stack.
! 19: * if the order here is changed, it needs to be
! 20: * updated in fork.c:copy_process, signal.c:do_signal,
! 21: * ptrace.c ptrace.h
1.1 root 22: *
1.1.1.2 ! root 23: * 0(%esp) - %ebx
! 24: * 4(%esp) - %ecx
! 25: * 8(%esp) - %edx
! 26: * C(%esp) - %esi
! 27: * 10(%esp) - %edi
! 28: * 14(%esp) - %ebp
! 29: * 18(%esp) - %eax
1.1 root 30: * 1C(%esp) - %ds
1.1.1.2 ! root 31: * 20(%esp) - %es
! 32: * 24(%esp) - %fs
! 33: * 28(%esp) - %gs
! 34: * 2C(%esp) - orig_eax
! 35: * 30(%esp) - %eip
! 36: * 34(%esp) - %cs
! 37: * 38(%esp) - %eflags
! 38: * 3C(%esp) - %oldesp
! 39: * 40(%esp) - %oldss
1.1 root 40: */
41:
42: SIG_CHLD = 17
43:
1.1.1.2 ! root 44: EBX = 0x00
! 45: ECX = 0x04
! 46: EDX = 0x08
! 47: ESI = 0x0C
! 48: EDI = 0x10
! 49: EBP = 0x14
! 50: EAX = 0x18
1.1 root 51: DS = 0x1C
1.1.1.2 ! root 52: ES = 0x20
! 53: FS = 0x24
! 54: GS = 0x28
! 55: ORIG_EAX = 0x2C
! 56: EIP = 0x30
! 57: CS = 0x34
! 58: EFLAGS = 0x38
! 59: OLDESP = 0x3C
! 60: OLDSS = 0x40
1.1 root 61:
62: state = 0 # these are offsets into the task-struct.
63: counter = 4
64: priority = 8
65: signal = 12
66: sigaction = 16 # MUST be 16 (=len of sigaction)
67: blocked = (33*16)
68:
69: # offsets within sigaction
70: sa_handler = 0
71: sa_mask = 4
72: sa_flags = 8
73: sa_restorer = 12
74:
75: nr_system_calls = 82
76:
77: ENOSYS = 38
78:
79: /*
80: * Ok, I get parallel printer interrupts while using the floppy for some
81: * strange reason. Urgel. Now I just ignore them.
82: */
1.1.1.2 ! root 83: .globl _system_call,_timer_interrupt,_sys_execve
1.1 root 84: .globl _hd_interrupt,_floppy_interrupt,_parallel_interrupt
85: .globl _device_not_available, _coprocessor_error
86:
87: .align 2
88: bad_sys_call:
89: pushl $-ENOSYS
90: jmp ret_from_sys_call
91: .align 2
92: reschedule:
93: pushl $ret_from_sys_call
94: jmp _schedule
95: .align 2
96: _system_call:
1.1.1.2 ! root 97: cld
! 98: pushl %eax # save orig_eax
! 99: push %gs
1.1 root 100: push %fs
1.1.1.2 ! root 101: push %es
! 102: push %ds
! 103: pushl %eax # save eax. The return value will be put here.
! 104: pushl %ebp
! 105: pushl %edi
! 106: pushl %esi
1.1 root 107: pushl %edx
108: pushl %ecx # push %ebx,%ecx,%edx as parameters
109: pushl %ebx # to the system call
110: movl $0x10,%edx # set up ds,es to kernel space
111: mov %dx,%ds
112: mov %dx,%es
113: movl $0x17,%edx # fs points to local data space
114: mov %dx,%fs
115: cmpl _NR_syscalls,%eax
116: jae bad_sys_call
117: call _sys_call_table(,%eax,4)
1.1.1.2 ! root 118: movl %eax,EAX(%esp) # save the return value
! 119: 2: movl _current,%eax
1.1 root 120: cmpl $0,state(%eax) # state
121: jne reschedule
122: cmpl $0,counter(%eax) # counter
123: je reschedule
124: ret_from_sys_call:
125: movl _current,%eax
126: cmpl _task,%eax # task[0] cannot have signals
127: je 3f
128: cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
129: jne 3f
130: cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
131: jne 3f
132: movl signal(%eax),%ebx
133: movl blocked(%eax),%ecx
134: notl %ecx
135: andl %ebx,%ecx
136: bsfl %ecx,%ecx
137: je 3f
138: btrl %ecx,%ebx
139: movl %ebx,signal(%eax)
140: incl %ecx
141: pushl %ecx
142: call _do_signal
143: popl %ecx
144: testl %eax, %eax
145: jne 2b # see if we need to switch tasks, or do more signals
1.1.1.2 ! root 146: 3:
1.1 root 147: popl %ebx
148: popl %ecx
149: popl %edx
1.1.1.2 ! root 150: popl %esi
! 151: popl %edi
! 152: popl %ebp
! 153: popl %eax
1.1 root 154: pop %ds
1.1.1.2 ! root 155: pop %es
! 156: pop %fs
! 157: pop %gs
! 158: addl $4,%esp # skip the orig_eax
1.1 root 159: iret
160:
161: .align 2
162: _coprocessor_error:
1.1.1.2 ! root 163: cld
! 164: pushl $-1 # mark this as an int.
! 165: push %gs
1.1 root 166: push %fs
1.1.1.2 ! root 167: push %es
! 168: push %ds
! 169: pushl %eax # save eax.
! 170: pushl %ebp
! 171: pushl %edi
! 172: pushl %esi
1.1 root 173: pushl %edx
174: pushl %ecx
175: pushl %ebx
176: movl $0x10,%eax
177: mov %ax,%ds
178: mov %ax,%es
179: movl $0x17,%eax
180: mov %ax,%fs
181: pushl $ret_from_sys_call
182: jmp _math_error
183:
184: .align 2
185: _device_not_available:
1.1.1.2 ! root 186: cld
! 187: pushl $-1 # mark this as an int
! 188: push %gs
1.1 root 189: push %fs
1.1.1.2 ! root 190: push %es
! 191: push %ds
! 192: pushl %eax
! 193: pushl %ebp
! 194: pushl %edi
! 195: pushl %esi
1.1 root 196: pushl %edx
197: pushl %ecx
198: pushl %ebx
199: movl $0x10,%eax
200: mov %ax,%ds
201: mov %ax,%es
202: movl $0x17,%eax
203: mov %ax,%fs
204: pushl $ret_from_sys_call
205: clts # clear TS so that we can use math
206: movl %cr0,%eax
207: testl $0x4,%eax # EM (math emulation bit)
208: je _math_state_restore
209: pushl $0 # temporary storage for ORIG_EIP
210: call _math_emulate
211: addl $4,%esp
212: ret
213:
214: .align 2
215: _timer_interrupt:
1.1.1.2 ! root 216: cld
! 217: pushl $-1 # mark this as an int
! 218: push %gs
1.1 root 219: push %fs
1.1.1.2 ! root 220: push %es
! 221: push %ds
1.1 root 222: pushl %eax
1.1.1.2 ! root 223: pushl %ebp
! 224: pushl %edi
! 225: pushl %esi
! 226: pushl %edx
! 227: pushl %ecx
! 228: pushl %ebx
1.1 root 229: movl $0x10,%eax
230: mov %ax,%ds
231: mov %ax,%es
232: movl $0x17,%eax
233: mov %ax,%fs
234: incl _jiffies
235: movb $0x20,%al # EOI to interrupt controller #1
236: outb %al,$0x20
237: movl CS(%esp),%eax
238: andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
239: pushl %eax
240: call _do_timer # 'do_timer(long CPL)' does everything from
241: addl $4,%esp # task switching to accounting ...
242: jmp ret_from_sys_call
243:
244: .align 2
245: _sys_execve:
1.1.1.2 ! root 246: lea (EIP+4)(%esp),%eax # don't forget about the return address.
1.1 root 247: pushl %eax
248: call _do_execve
249: addl $4,%esp
250: ret
251:
252: _hd_interrupt:
1.1.1.2 ! root 253: cld
1.1 root 254: pushl %eax
255: pushl %ecx
256: pushl %edx
257: push %ds
258: push %es
259: push %fs
260: movl $0x10,%eax
261: mov %ax,%ds
262: mov %ax,%es
263: movl $0x17,%eax
264: mov %ax,%fs
265: movb $0x20,%al
266: outb %al,$0xA0 # EOI to interrupt controller #1
267: jmp 1f # give port chance to breathe
268: 1: jmp 1f
1.1.1.2 ! root 269: 1: outb %al,$0x20
! 270: andl $0xfffeffff,_timer_active
! 271: xorl %edx,%edx
1.1 root 272: xchgl _do_hd,%edx
273: testl %edx,%edx
274: jne 1f
275: movl $_unexpected_hd_interrupt,%edx
1.1.1.2 ! root 276: 1: call *%edx # "interesting" way of handling intr.
1.1 root 277: pop %fs
278: pop %es
279: pop %ds
280: popl %edx
281: popl %ecx
282: popl %eax
283: iret
284:
285: _floppy_interrupt:
1.1.1.2 ! root 286: cld
1.1 root 287: pushl %eax
288: pushl %ecx
289: pushl %edx
290: push %ds
291: push %es
292: push %fs
293: movl $0x10,%eax
294: mov %ax,%ds
295: mov %ax,%es
296: movl $0x17,%eax
297: mov %ax,%fs
298: movb $0x20,%al
299: outb %al,$0x20 # EOI to interrupt controller #1
300: xorl %eax,%eax
301: xchgl _do_floppy,%eax
302: testl %eax,%eax
303: jne 1f
304: movl $_unexpected_floppy_interrupt,%eax
305: 1: call *%eax # "interesting" way of handling intr.
306: pop %fs
307: pop %es
308: pop %ds
309: popl %edx
310: popl %ecx
311: popl %eax
312: iret
313:
314: _parallel_interrupt:
1.1.1.2 ! root 315: cld
1.1 root 316: pushl %eax
317: movb $0x20,%al
318: outb %al,$0x20
319: popl %eax
320: iret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.