root/kernel/sys_call.S

/* [previous][next][first][last][top][bottom][index][help] */
   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
  92 
  93 #define SAVE_ALL \
  94         cld; \
  95         push %gs; \
  96         push %fs; \
  97         push %es; \
  98         push %ds; \
  99         pushl %eax; \
 100         pushl %ebp; \
 101         pushl %edi; \
 102         pushl %esi; \
 103         pushl %edx; \
 104         pushl %ecx; \
 105         pushl %ebx; \
 106         movl $0x10,%edx; \
 107         mov %dx,%ds; \
 108         mov %dx,%es; \
 109         movl $0x17,%edx; \
 110         mov %dx,%fs
 111 
 112 #define ACK_FIRST(mask) \
 113         inb $0x21,%al; \
 114         jmp 1f; \
 115 1:      jmp 1f; \
 116 1:      orb $(mask),%al; \
 117         outb %al,$0x21; \
 118         jmp 1f; \
 119 1:      jmp 1f; \
 120 1:      movb $0x20,%al; \
 121         outb %al,$0x20
 122 
 123 #define ACK_SECOND(mask) \
 124         inb $0xA1,%al; \
 125         jmp 1f; \
 126 1:      jmp 1f; \
 127 1:      orb $mask,%al; \
 128         outb %al,$0xA1; \
 129         jmp 1f; \
 130 1:      jmp 1f; \
 131 1:      movb $0x20,%al; \
 132         outb %al,$0x20
 133         jmp 1f; \
 134 1:      jmp 1f; \
 135 1:      outb %al,$0xA0
 136 
 137 #define UNBLK_FIRST(mask) \
 138         inb $0x21,%al; \
 139         jmp 1f; \
 140 1:      jmp 1f; \
 141 1:      andb $~(mask),%al; \
 142         outb %al,$0x21
 143 
 144 #define UNBLK_SECOND(mask) \
 145         inb $0xA1,%al; \
 146         jmp 1f; \
 147 1:      jmp 1f; \
 148 1:      andb $~(mask),%al; \
 149         outb %al,$0xA1
 150 
 151 .align 2
 152 bad_sys_call:
 153         movl $-ENOSYS,EAX(%esp)
 154         jmp ret_from_sys_call
 155 .align 2
 156 reschedule:
 157         pushl $ret_from_sys_call
 158         jmp _schedule
 159 .align 2
 160 _system_call:
 161         pushl %eax              # save orig_eax
 162         SAVE_ALL
 163         cmpl _NR_syscalls,%eax
 164         jae bad_sys_call
 165         call _sys_call_table(,%eax,4)
 166         movl %eax,EAX(%esp)             # save the return value
 167 ret_from_sys_call:
 168         cmpw $0x0f,CS(%esp)             # was old code segment supervisor ?
 169         jne 2f
 170         cmpw $0x17,OLDSS(%esp)          # was stack segment = 0x17 ?
 171         jne 2f
 172 1:      movl _current,%eax
 173         cmpl _task,%eax                 # task[0] cannot have signals
 174         je 2f
 175         cmpl $0,state(%eax)             # state
 176         jne reschedule
 177         cmpl $0,counter(%eax)           # counter
 178         je reschedule
 179         movl signal(%eax),%ebx
 180         movl blocked(%eax),%ecx
 181         notl %ecx
 182         andl %ebx,%ecx
 183         bsfl %ecx,%ecx
 184         je 2f
 185         btrl %ecx,%ebx
 186         movl %ebx,signal(%eax)
 187         incl %ecx
 188         pushl %ecx
 189         call _do_signal
 190         popl %ecx
 191         testl %eax, %eax
 192         jne 1b                  # see if we need to switch tasks, or do more signals
 193 2:      popl %ebx
 194         popl %ecx
 195         popl %edx
 196         popl %esi
 197         popl %edi
 198         popl %ebp
 199         popl %eax
 200         pop %ds
 201         pop %es
 202         pop %fs
 203         pop %gs
 204         addl $4,%esp            # skip the orig_eax
 205         iret
 206 
 207 .align 2
 208 _irq13:
 209         pushl %eax
 210         xorb %al,%al
 211         outb %al,$0xF0
 212         movb $0x20,%al
 213         outb %al,$0x20
 214         jmp 1f
 215 1:      jmp 1f
 216 1:      outb %al,$0xA0
 217         popl %eax
 218 _coprocessor_error:
 219         pushl $-1               # mark this as an int. 
 220         SAVE_ALL
 221         pushl $ret_from_sys_call
 222         jmp _math_error
 223 
 224 .align 2
 225 _device_not_available:
 226         pushl $-1               # mark this as an int
 227         SAVE_ALL
 228         pushl $ret_from_sys_call
 229         clts                            # clear TS so that we can use math
 230         movl %cr0,%eax
 231         testl $0x4,%eax                 # EM (math emulation bit)
 232         je _math_state_restore
 233         pushl $0                # temporary storage for ORIG_EIP
 234         call _math_emulate
 235         addl $4,%esp
 236         ret
 237 
 238 .align 2
 239 _keyboard_interrupt:
 240         pushl $-1
 241         SAVE_ALL
 242         ACK_FIRST(2)
 243         sti
 244         call _do_keyboard
 245         cli
 246         UNBLK_FIRST(2)
 247         jmp ret_from_sys_call
 248 
 249 .align 2
 250 _timer_interrupt:
 251         pushl $-1               # mark this as an int
 252         SAVE_ALL
 253         incl _jiffies
 254         movb $0x20,%al          # EOI to interrupt controller #1
 255         outb %al,$0x20
 256         movl CS(%esp),%eax
 257         andl $3,%eax            # %eax is CPL (0 or 3, 0=supervisor)
 258         pushl %eax
 259         call _do_timer          # 'do_timer(long CPL)' does everything from
 260         addl $4,%esp            # task switching to accounting ...
 261         jmp ret_from_sys_call
 262 
 263 .align 2
 264 _sys_execve:
 265         lea (EIP+4)(%esp),%eax  # don't forget about the return address.
 266         pushl %eax
 267         call _do_execve
 268         addl $4,%esp
 269         ret
 270 
 271 _divide_error:
 272         pushl $0                # no error code
 273         pushl $_do_divide_error
 274 error_code:
 275         push %fs
 276         push %es
 277         push %ds
 278         pushl %eax
 279         pushl %ebp
 280         pushl %edi
 281         pushl %esi
 282         pushl %edx
 283         pushl %ecx
 284         pushl %ebx
 285         cld
 286         movl $-1, %eax
 287         xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
 288         xorl %ebx,%ebx                  # zero ebx
 289         mov %gs,%bx                     # get the lower order bits of gs
 290         xchgl %ebx, GS(%esp)            # get the address and save gs.
 291         pushl %eax                      # push the error code
 292         lea 52(%esp),%edx
 293         pushl %edx
 294         movl $0x10,%edx
 295         mov %dx,%ds
 296         mov %dx,%es
 297         movl $0x17,%edx
 298         mov %dx,%fs
 299         call *%ebx
 300         addl $8,%esp
 301         jmp ret_from_sys_call
 302 
 303 _debug:
 304         pushl $0
 305         pushl $_do_int3         # _do_debug
 306         jmp error_code
 307 
 308 _nmi:
 309         pushl $0
 310         pushl $_do_nmi
 311         jmp error_code
 312 
 313 _int3:
 314         pushl $0
 315         pushl $_do_int3
 316         jmp error_code
 317 
 318 _overflow:
 319         pushl $0
 320         pushl $_do_overflow
 321         jmp error_code
 322 
 323 _bounds:
 324         pushl $0
 325         pushl $_do_bounds
 326         jmp error_code
 327 
 328 _invalid_op:
 329         pushl $0
 330         pushl $_do_invalid_op
 331         jmp error_code
 332 
 333 _coprocessor_segment_overrun:
 334         pushl $0
 335         pushl $_do_coprocessor_segment_overrun
 336         jmp error_code
 337 
 338 _reserved:
 339         pushl $0
 340         pushl $_do_reserved
 341         jmp error_code
 342 
 343 _double_fault:
 344         pushl $_do_double_fault
 345         jmp error_code
 346 
 347 _invalid_TSS:
 348         pushl $_do_invalid_TSS
 349         jmp error_code
 350 
 351 _segment_not_present:
 352         pushl $_do_segment_not_present
 353         jmp error_code
 354 
 355 _stack_segment:
 356         pushl $_do_stack_segment
 357         jmp error_code
 358 
 359 _general_protection:
 360         pushl $_do_general_protection
 361         jmp error_code
 362 
 363 _alignment_check:
 364         pushl $_do_alignment_check
 365         jmp error_code
 366 
 367 _page_fault:
 368         pushl $_do_page_fault
 369         jmp error_code

/* [previous][next][first][last][top][bottom][index][help] */