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':
18 *
19 * 0(%esp) - %eax
20 * 4(%esp) - %ebx
21 * 8(%esp) - %ecx
22 * C(%esp) - %edx
23 * 10(%esp) - %fs
24 * 14(%esp) - %es
25 * 18(%esp) - %ds
26 * 1C(%esp) - %eip
27 * 20(%esp) - %cs
28 * 24(%esp) - %eflags
29 * 28(%esp) - %oldesp
30 * 2C(%esp) - %oldss
31 */
32
33 SIG_CHLD = 17
34
35 EAX = 0x00
36 EBX = 0x04
37 ECX = 0x08
38 EDX = 0x0C
39 FS = 0x10
40 ES = 0x14
41 DS = 0x18
42 EIP = 0x1C
43 CS = 0x20
44 EFLAGS = 0x24
45 OLDESP = 0x28
46 OLDSS = 0x2C
47
48 state = 0 # these are offsets into the task-struct.
49 counter = 4
50 priority = 8
51 signal = 12
52 sigaction = 16 # MUST be 16 (=len of sigaction)
53 blocked = (33*16)
54
55 # offsets within sigaction
56 sa_handler = 0
57 sa_mask = 4
58 sa_flags = 8
59 sa_restorer = 12
60
61 nr_system_calls = 72
62
63 /*
64 * Ok, I get parallel printer interrupts while using the floppy for some
65 * strange reason. Urgel. Now I just ignore them.
66 */
67 .globl _system_call,_sys_fork,_timer_interrupt,_sys_execve
68 .globl _hd_interrupt,_floppy_interrupt,_parallel_interrupt
69 .globl _device_not_available, _coprocessor_error
70
71 .align 2
72 bad_sys_call:
73 movl $-1,%eax
74 iret
75 .align 2
76 reschedule:
77 pushl $ret_from_sys_call
78 jmp _schedule
79 .align 2
80 _system_call:
81 cmpl $nr_system_calls-1,%eax
82 ja bad_sys_call
83 push %ds
84 push %es
85 push %fs
86 pushl %edx
87 pushl %ecx # push %ebx,%ecx,%edx as parameters
88 pushl %ebx # to the system call
89 movl $0x10,%edx # set up ds,es to kernel space
90 mov %dx,%ds
91 mov %dx,%es
92 movl $0x17,%edx # fs points to local data space
93 mov %dx,%fs
94 call _sys_call_table(,%eax,4)
95 pushl %eax
96 movl _current,%eax
97 cmpl $0,state(%eax) # state
98 jne reschedule
99 cmpl $0,counter(%eax) # counter
100 je reschedule
101 ret_from_sys_call:
102 movl _current,%eax # task[0] cannot have signals
103 cmpl _task,%eax
104 je 3f
105 cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
106 jne 3f
107 cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
108 jne 3f
109 movl signal(%eax),%ebx
110 movl blocked(%eax),%ecx
111 notl %ecx
112 andl %ebx,%ecx
113 bsfl %ecx,%ecx
114 je 3f
115 btrl %ecx,%ebx
116 movl %ebx,signal(%eax)
117 incl %ecx
118 pushl %ecx
119 call _do_signal
120 popl %eax
121 3: popl %eax
122 popl %ebx
123 popl %ecx
124 popl %edx
125 pop %fs
126 pop %es
127 pop %ds
128 iret
129
130 .align 2
131 _coprocessor_error:
132 push %ds
133 push %es
134 push %fs
135 pushl %edx
136 pushl %ecx
137 pushl %ebx
138 pushl %eax
139 movl $0x10,%eax
140 mov %ax,%ds
141 mov %ax,%es
142 movl $0x17,%eax
143 mov %ax,%fs
144 pushl $ret_from_sys_call
145 jmp _math_error
146
147 .align 2
148 _device_not_available:
149 push %ds
150 push %es
151 push %fs
152 pushl %edx
153 pushl %ecx
154 pushl %ebx
155 pushl %eax
156 movl $0x10,%eax
157 mov %ax,%ds
158 mov %ax,%es
159 movl $0x17,%eax
160 mov %ax,%fs
161 pushl $ret_from_sys_call
162 clts # clear TS so that we can use math
163 movl %cr0,%eax
164 testl $0x4,%eax # EM (math emulation bit)
165 je _math_state_restore
166 pushl %ebp
167 pushl %esi
168 pushl %edi
169 call _math_emulate
170 popl %edi
171 popl %esi
172 popl %ebp
173 ret
174
175 .align 2
176 _timer_interrupt:
177 push %ds # save ds,es and put kernel data space
178 push %es # into them. %fs is used by _system_call
179 push %fs
180 pushl %edx # we save %eax,%ecx,%edx as gcc doesn't
181 pushl %ecx # save those across function calls. %ebx
182 pushl %ebx # is saved as we use that in ret_sys_call
183 pushl %eax
184 movl $0x10,%eax
185 mov %ax,%ds
186 mov %ax,%es
187 movl $0x17,%eax
188 mov %ax,%fs
189 incl _jiffies
190 movb $0x20,%al # EOI to interrupt controller #1
191 outb %al,$0x20
192 movl CS(%esp),%eax
193 andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
194 pushl %eax
195 call _do_timer # 'do_timer(long CPL)' does everything from
196 addl $4,%esp # task switching to accounting ...
197 jmp ret_from_sys_call
198
199 .align 2
200 _sys_execve:
201 lea EIP(%esp),%eax
202 pushl %eax
203 call _do_execve
204 addl $4,%esp
205 ret
206
207 .align 2
208 _sys_fork:
209 call _find_empty_process
210 testl %eax,%eax
211 js 1f
212 push %gs
213 pushl %esi
214 pushl %edi
215 pushl %ebp
216 pushl %eax
217 call _copy_process
218 addl $20,%esp
219 1: ret
220
221 _hd_interrupt:
222 pushl %eax
223 pushl %ecx
224 pushl %edx
225 push %ds
226 push %es
227 push %fs
228 movl $0x10,%eax
229 mov %ax,%ds
230 mov %ax,%es
231 movl $0x17,%eax
232 mov %ax,%fs
233 movb $0x20,%al
234 outb %al,$0xA0 # EOI to interrupt controller #1
235 jmp 1f # give port chance to breathe
236 1: jmp 1f
237 1: xorl %edx,%edx
238 xchgl _do_hd,%edx
239 testl %edx,%edx
240 jne 1f
241 movl $_unexpected_hd_interrupt,%edx
242 1: outb %al,$0x20
243 call *%edx # "interesting" way of handling intr.
244 pop %fs
245 pop %es
246 pop %ds
247 popl %edx
248 popl %ecx
249 popl %eax
250 iret
251
252 _floppy_interrupt:
253 pushl %eax
254 pushl %ecx
255 pushl %edx
256 push %ds
257 push %es
258 push %fs
259 movl $0x10,%eax
260 mov %ax,%ds
261 mov %ax,%es
262 movl $0x17,%eax
263 mov %ax,%fs
264 movb $0x20,%al
265 outb %al,$0x20 # EOI to interrupt controller #1
266 xorl %eax,%eax
267 xchgl _do_floppy,%eax
268 testl %eax,%eax
269 jne 1f
270 movl $_unexpected_floppy_interrupt,%eax
271 1: call *%eax # "interesting" way of handling intr.
272 pop %fs
273 pop %es
274 pop %ds
275 popl %edx
276 popl %ecx
277 popl %eax
278 iret
279
280 _parallel_interrupt:
281 pushl %eax
282 movb $0x20,%al
283 outb %al,$0x20
284 popl %eax
285 iret