root/kernel/sys_call.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /*
   2  *  linux/kernel/sys_call.S
   3  *
   4  *  Copyright (C) 1991, 1992  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  * I changed all the .align's to 4 (16 byte alignment), as that's faster
  16  * on a 486.
  17  *
  18  * Stack layout in 'ret_from_system_call':
  19  *      ptrace needs to have all regs on the stack.
  20  *      if the order here is changed, it needs to be 
  21  *      updated in fork.c:copy_process, signal.c:do_signal,
  22  *      ptrace.c and ptrace.h
  23  *
  24  *       0(%esp) - %ebx
  25  *       4(%esp) - %ecx
  26  *       8(%esp) - %edx
  27  *       C(%esp) - %esi
  28  *      10(%esp) - %edi
  29  *      14(%esp) - %ebp
  30  *      18(%esp) - %eax
  31  *      1C(%esp) - %ds
  32  *      20(%esp) - %es
  33  *      24(%esp) - %fs
  34  *      28(%esp) - %gs
  35  *      2C(%esp) - orig_eax
  36  *      30(%esp) - %eip
  37  *      34(%esp) - %cs
  38  *      38(%esp) - %eflags
  39  *      3C(%esp) - %oldesp
  40  *      40(%esp) - %oldss
  41  */
  42 
  43 #include <linux/segment.h>
  44 
  45 EBX             = 0x00
  46 ECX             = 0x04
  47 EDX             = 0x08
  48 ESI             = 0x0C
  49 EDI             = 0x10
  50 EBP             = 0x14
  51 EAX             = 0x18
  52 DS              = 0x1C
  53 ES              = 0x20
  54 FS              = 0x24
  55 GS              = 0x28
  56 ORIG_EAX        = 0x2C
  57 EIP             = 0x30
  58 CS              = 0x34
  59 EFLAGS          = 0x38
  60 OLDESP          = 0x3C
  61 OLDSS           = 0x40
  62 
  63 CF_MASK         = 0x00000001
  64 IF_MASK         = 0x00000200
  65 NT_MASK         = 0x00004000
  66 VM_MASK         = 0x00020000
  67 
  68 /*
  69  * these are offsets into the task-struct.
  70  */
  71 state           =  0
  72 counter         =  4
  73 priority        =  8
  74 signal          = 12
  75 blocked         = 16
  76 flags           = 20
  77 errno           = 24
  78 dbgreg6         = 52
  79 dbgreg7         = 56
  80 
  81 ENOSYS = 38
  82 
  83 .globl _system_call,_lcall7
  84 .globl _device_not_available, _coprocessor_error
  85 .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
  86 .globl _double_fault,_coprocessor_segment_overrun
  87 .globl _invalid_TSS,_segment_not_present,_stack_segment
  88 .globl _general_protection,_reserved
  89 .globl _alignment_check,_page_fault
  90 .globl ret_from_sys_call
  91 
  92 #define SAVE_ALL \
  93         cld; \
  94         push %gs; \
  95         push %fs; \
  96         push %es; \
  97         push %ds; \
  98         pushl %eax; \
  99         pushl %ebp; \
 100         pushl %edi; \
 101         pushl %esi; \
 102         pushl %edx; \
 103         pushl %ecx; \
 104         pushl %ebx; \
 105         movl $(KERNEL_DS),%edx; \
 106         mov %dx,%ds; \
 107         mov %dx,%es; \
 108         movl $(USER_DS),%edx; \
 109         mov %dx,%fs;
 110 
 111 #define RESTORE_ALL \
 112         cmpw $(KERNEL_CS),CS(%esp); \
 113         je 1f;   \
 114         movl _current,%eax; \
 115         movl dbgreg7(%eax),%ebx; \
 116         movl %ebx,%db7; \
 117 1:      popl %ebx; \
 118         popl %ecx; \
 119         popl %edx; \
 120         popl %esi; \
 121         popl %edi; \
 122         popl %ebp; \
 123         popl %eax; \
 124         pop %ds; \
 125         pop %es; \
 126         pop %fs; \
 127         pop %gs; \
 128         addl $4,%esp; \
 129         iret
 130 
 131 .align 4
 132 _lcall7:
 133         pushfl                  # We get a different stack layout with call gates,
 134         pushl %eax              # which has to be cleaned up later..
 135         SAVE_ALL
 136         movl EIP(%esp),%eax     # due to call gates, this is eflags, not eip..
 137         movl CS(%esp),%edx      # this is eip..
 138         movl EFLAGS(%esp),%ecx  # and this is cs..
 139         movl %eax,EFLAGS(%esp)  #
 140         movl %edx,EIP(%esp)     # Now we move them to their "normal" places
 141         movl %ecx,CS(%esp)      #
 142         movl %esp,%eax
 143         pushl %eax
 144         call _iABI_emulate
 145         popl %eax
 146         jmp ret_from_sys_call
 147 
 148 .align 4
 149 handle_bottom_half:
 150         pushfl
 151         incl _intr_count
 152         sti
 153         call _do_bottom_half
 154         popfl
 155         decl _intr_count
 156         jmp 9f
 157 .align 4
 158 reschedule:
 159         pushl $ret_from_sys_call
 160         jmp _schedule
 161 .align 4
 162 _system_call:
 163         pushl %eax                      # save orig_eax
 164         SAVE_ALL
 165         movl $-ENOSYS,EAX(%esp)
 166         cmpl _NR_syscalls,%eax
 167         jae ret_from_sys_call
 168         movl _current,%ebx
 169         andl $~CF_MASK,EFLAGS(%esp)     # clear carry - assume no errors
 170         movl $0,errno(%ebx)
 171         movl %db6,%edx
 172         movl %edx,dbgreg6(%ebx)  # save current hardware debugging status
 173         testb $0x20,flags(%ebx)         # PF_TRACESYS
 174         jne 1f
 175         call _sys_call_table(,%eax,4)
 176         movl %eax,EAX(%esp)             # save the return value
 177         movl errno(%ebx),%edx
 178         negl %edx
 179         je ret_from_sys_call
 180         movl %edx,EAX(%esp)
 181         orl $(CF_MASK),EFLAGS(%esp)     # set carry to indicate error
 182         jmp ret_from_sys_call
 183 .align 4
 184 1:      call _syscall_trace
 185         movl ORIG_EAX(%esp),%eax
 186         call _sys_call_table(,%eax,4)
 187         movl %eax,EAX(%esp)             # save the return value
 188         movl _current,%eax
 189         movl errno(%eax),%edx
 190         negl %edx
 191         je 1f
 192         movl %edx,EAX(%esp)
 193         orl $(CF_MASK),EFLAGS(%esp)     # set carry to indicate error
 194 1:      call _syscall_trace
 195 
 196         .align 4,0x90
 197 ret_from_sys_call:
 198         cmpl $0,_intr_count
 199         jne 2f
 200         movl _bh_mask,%eax
 201         andl _bh_active,%eax
 202         jne handle_bottom_half
 203 9:      movl EFLAGS(%esp),%eax          # check VM86 flag: CS/SS are
 204         testl $(VM_MASK),%eax           # different then
 205         jne 1f
 206         cmpw $(KERNEL_CS),CS(%esp)      # was old code segment supervisor ?
 207         je 2f
 208 1:      sti
 209         orl $(IF_MASK),%eax             # these just try to make sure
 210         andl $~NT_MASK,%eax             # the program doesn't do anything
 211         movl %eax,EFLAGS(%esp)          # stupid
 212         cmpl $0,_need_resched
 213         jne reschedule
 214         movl _current,%eax
 215         cmpl _task,%eax                 # task[0] cannot have signals
 216         je 2f
 217         cmpl $0,state(%eax)             # state
 218         jne reschedule
 219         cmpl $0,counter(%eax)           # counter
 220         je reschedule
 221         movl blocked(%eax),%ecx
 222         movl %ecx,%ebx                  # save blocked in %ebx for signal handling
 223         notl %ecx
 224         andl signal(%eax),%ecx
 225         jne signal_return
 226 2:      RESTORE_ALL
 227 .align 4
 228 signal_return:
 229         movl %esp,%ecx
 230         pushl %ecx
 231         testl $(VM_MASK),EFLAGS(%ecx)
 232         jne v86_signal_return
 233         pushl %ebx
 234         call _do_signal
 235         popl %ebx
 236         popl %ebx
 237         RESTORE_ALL
 238 .align 4
 239 v86_signal_return:
 240         call _save_v86_state
 241         movl %eax,%esp
 242         pushl %eax
 243         pushl %ebx
 244         call _do_signal
 245         popl %ebx
 246         popl %ebx
 247         RESTORE_ALL
 248 
 249 .align 4
 250 _divide_error:
 251         pushl $0                # no error code
 252         pushl $_do_divide_error
 253 .align 4,0x90
 254 error_code:
 255         push %fs
 256         push %es
 257         push %ds
 258         pushl %eax
 259         pushl %ebp
 260         pushl %edi
 261         pushl %esi
 262         pushl %edx
 263         pushl %ecx
 264         pushl %ebx
 265         movl $0,%eax
 266         movl %eax,%db7                  # disable hardware debugging...
 267         cld
 268         movl $-1, %eax
 269         xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
 270         xorl %ebx,%ebx                  # zero ebx
 271         mov %gs,%bx                     # get the lower order bits of gs
 272         xchgl %ebx, GS(%esp)            # get the address and save gs.
 273         pushl %eax                      # push the error code
 274         lea 4(%esp),%edx
 275         pushl %edx
 276         movl $(KERNEL_DS),%edx
 277         mov %dx,%ds
 278         mov %dx,%es
 279         movl $(USER_DS),%edx
 280         mov %dx,%fs
 281         pushl %eax
 282         movl _current,%eax
 283         movl %db6,%edx
 284         movl %edx,dbgreg6(%eax)  # save current hardware debugging status
 285         popl %eax
 286         call *%ebx
 287         addl $8,%esp
 288         jmp ret_from_sys_call
 289 
 290 .align 4
 291 _coprocessor_error:
 292         pushl $0
 293         pushl $_do_coprocessor_error
 294         jmp error_code
 295 
 296 .align 4
 297 _device_not_available:
 298         pushl $-1               # mark this as an int
 299         SAVE_ALL
 300         pushl $ret_from_sys_call
 301         movl %cr0,%eax
 302         testl $0x4,%eax                 # EM (math emulation bit)
 303         je _math_state_restore
 304         pushl $0                # temporary storage for ORIG_EIP
 305         call _math_emulate
 306         addl $4,%esp
 307         ret
 308 
 309 .align 4
 310 _debug:
 311         pushl $0
 312         pushl $_do_debug
 313         jmp error_code
 314 
 315 .align 4
 316 _nmi:
 317         pushl $0
 318         pushl $_do_nmi
 319         jmp error_code
 320 
 321 .align 4
 322 _int3:
 323         pushl $0
 324         pushl $_do_int3
 325         jmp error_code
 326 
 327 .align 4
 328 _overflow:
 329         pushl $0
 330         pushl $_do_overflow
 331         jmp error_code
 332 
 333 .align 4
 334 _bounds:
 335         pushl $0
 336         pushl $_do_bounds
 337         jmp error_code
 338 
 339 .align 4
 340 _invalid_op:
 341         pushl $0
 342         pushl $_do_invalid_op
 343         jmp error_code
 344 
 345 .align 4
 346 _coprocessor_segment_overrun:
 347         pushl $0
 348         pushl $_do_coprocessor_segment_overrun
 349         jmp error_code
 350 
 351 .align 4
 352 _reserved:
 353         pushl $0
 354         pushl $_do_reserved
 355         jmp error_code
 356 
 357 .align 4
 358 _double_fault:
 359         pushl $_do_double_fault
 360         jmp error_code
 361 
 362 .align 4
 363 _invalid_TSS:
 364         pushl $_do_invalid_TSS
 365         jmp error_code
 366 
 367 .align 4
 368 _segment_not_present:
 369         pushl $_do_segment_not_present
 370         jmp error_code
 371 
 372 .align 4
 373 _stack_segment:
 374         pushl $_do_stack_segment
 375         jmp error_code
 376 
 377 .align 4
 378 _general_protection:
 379         pushl $_do_general_protection
 380         jmp error_code
 381 
 382 .align 4
 383 _alignment_check:
 384         pushl $_do_alignment_check
 385         jmp error_code
 386 
 387 .align 4
 388 _page_fault:
 389         pushl $_do_page_fault
 390         jmp error_code

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