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