home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / arch / i386 / kernel / entry.S < prev    next >
Encoding:
Text File  |  1995-01-03  |  10.6 KB  |  545 lines

  1. /*
  2.  *  linux/arch/i386/entry.S
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6.  
  7. /*
  8.  * entry.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/sys.h>
  44. #include <asm/segment.h>
  45.  
  46. EBX        = 0x00
  47. ECX        = 0x04
  48. EDX        = 0x08
  49. ESI        = 0x0C
  50. EDI        = 0x10
  51. EBP        = 0x14
  52. EAX        = 0x18
  53. DS        = 0x1C
  54. ES        = 0x20
  55. FS        = 0x24
  56. GS        = 0x28
  57. ORIG_EAX    = 0x2C
  58. EIP        = 0x30
  59. CS        = 0x34
  60. EFLAGS        = 0x38
  61. OLDESP        = 0x3C
  62. OLDSS        = 0x40
  63.  
  64. CF_MASK        = 0x00000001
  65. IF_MASK        = 0x00000200
  66. NT_MASK        = 0x00004000
  67. VM_MASK        = 0x00020000
  68.  
  69. /*
  70.  * these are offsets into the task-struct.
  71.  */
  72. state        =  0
  73. counter        =  4
  74. priority    =  8
  75. signal        = 12
  76. blocked        = 16
  77. flags        = 20
  78. errno        = 24
  79. dbgreg6        = 52
  80. dbgreg7        = 56
  81. exec_domain    = 60
  82.  
  83. ENOSYS = 38
  84.  
  85. .globl _system_call,_lcall7
  86. .globl _device_not_available, _coprocessor_error
  87. .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
  88. .globl _double_fault,_coprocessor_segment_overrun
  89. .globl _invalid_TSS,_segment_not_present,_stack_segment
  90. .globl _general_protection,_reserved
  91. .globl _alignment_check,_page_fault
  92. .globl ret_from_sys_call, _sys_call_table
  93.  
  94. #define SAVE_ALL \
  95.     cld; \
  96.     push %gs; \
  97.     push %fs; \
  98.     push %es; \
  99.     push %ds; \
  100.     pushl %eax; \
  101.     pushl %ebp; \
  102.     pushl %edi; \
  103.     pushl %esi; \
  104.     pushl %edx; \
  105.     pushl %ecx; \
  106.     pushl %ebx; \
  107.     movl $(KERNEL_DS),%edx; \
  108.     mov %dx,%ds; \
  109.     mov %dx,%es; \
  110.     movl $(USER_DS),%edx; \
  111.     mov %dx,%fs;
  112.  
  113. #define RESTORE_ALL \
  114.     cmpw $(KERNEL_CS),CS(%esp); \
  115.     je 1f;   \
  116.     movl _current,%eax; \
  117.     movl dbgreg7(%eax),%ebx; \
  118.     movl %ebx,%db7;    \
  119. 1:    popl %ebx; \
  120.     popl %ecx; \
  121.     popl %edx; \
  122.     popl %esi; \
  123.     popl %edi; \
  124.     popl %ebp; \
  125.     popl %eax; \
  126.     pop %ds; \
  127.     pop %es; \
  128.     pop %fs; \
  129.     pop %gs; \
  130.     addl $4,%esp; \
  131.     iret
  132.  
  133. .align 4
  134. _lcall7:
  135.     pushfl            # We get a different stack layout with call gates,
  136.     pushl %eax        # which has to be cleaned up later..
  137.     SAVE_ALL
  138.     movl EIP(%esp),%eax    # due to call gates, this is eflags, not eip..
  139.     movl CS(%esp),%edx    # this is eip..
  140.     movl EFLAGS(%esp),%ecx    # and this is cs..
  141.     movl %eax,EFLAGS(%esp)    #
  142.     movl %edx,EIP(%esp)    # Now we move them to their "normal" places
  143.     movl %ecx,CS(%esp)    #
  144.     movl %esp,%eax
  145.     movl _current,%edx
  146.     pushl %eax
  147.     movl exec_domain(%edx),%edx    # Get the execution domain
  148.     movl 4(%edx),%edx    # Get the lcall7 handler for the domain
  149.     call *%edx
  150.     popl %eax
  151.     jmp ret_from_sys_call
  152.  
  153. .align 4
  154. handle_bottom_half:
  155.     pushfl
  156.     incl _intr_count
  157.     sti
  158.     call _do_bottom_half
  159.     popfl
  160.     decl _intr_count
  161.     jmp 9f
  162. .align 4
  163. reschedule:
  164.     pushl $ret_from_sys_call
  165.     jmp _schedule
  166. .align 4
  167. _system_call:
  168.     pushl %eax            # save orig_eax
  169.     SAVE_ALL
  170.     movl $-ENOSYS,EAX(%esp)
  171.     cmpl $(NR_syscalls),%eax
  172.     jae ret_from_sys_call
  173.     movl _sys_call_table(,%eax,4),%eax
  174.     testl %eax,%eax
  175.     je ret_from_sys_call
  176.     movl _current,%ebx
  177.     andl $~CF_MASK,EFLAGS(%esp)    # clear carry - assume no errors
  178.     movl $0,errno(%ebx)
  179.     movl %db6,%edx
  180.     movl %edx,dbgreg6(%ebx)  # save current hardware debugging status
  181.     testb $0x20,flags(%ebx)        # PF_TRACESYS
  182.     jne 1f
  183.     call *%eax
  184.     movl %eax,EAX(%esp)        # save the return value
  185.     movl errno(%ebx),%edx
  186.     negl %edx
  187.     je ret_from_sys_call
  188.     movl %edx,EAX(%esp)
  189.     orl $(CF_MASK),EFLAGS(%esp)    # set carry to indicate error
  190.     jmp ret_from_sys_call
  191. .align 4
  192. 1:    call _syscall_trace
  193.     movl ORIG_EAX(%esp),%eax
  194.     call _sys_call_table(,%eax,4)
  195.     movl %eax,EAX(%esp)        # save the return value
  196.     movl _current,%eax
  197.     movl errno(%eax),%edx
  198.     negl %edx
  199.     je 1f
  200.     movl %edx,EAX(%esp)
  201.     orl $(CF_MASK),EFLAGS(%esp)    # set carry to indicate error
  202. 1:    call _syscall_trace
  203.  
  204.     .align 4,0x90
  205. ret_from_sys_call:
  206.     cmpl $0,_intr_count
  207.     jne 2f
  208. 9:    movl _bh_mask,%eax
  209.     andl _bh_active,%eax
  210.     jne handle_bottom_half
  211.     movl EFLAGS(%esp),%eax        # check VM86 flag: CS/SS are
  212.     testl $(VM_MASK),%eax        # different then
  213.     jne 1f
  214.     cmpw $(KERNEL_CS),CS(%esp)    # was old code segment supervisor ?
  215.     je 2f
  216. 1:    sti
  217.     orl $(IF_MASK),%eax        # these just try to make sure
  218.     andl $~NT_MASK,%eax        # the program doesn't do anything
  219.     movl %eax,EFLAGS(%esp)        # stupid
  220.     cmpl $0,_need_resched
  221.     jne reschedule
  222.     movl _current,%eax
  223.     cmpl _task,%eax            # task[0] cannot have signals
  224.     je 2f
  225.     cmpl $0,state(%eax)        # state
  226.     jne reschedule
  227.     cmpl $0,counter(%eax)        # counter
  228.     je reschedule
  229.     movl blocked(%eax),%ecx
  230.     movl %ecx,%ebx            # save blocked in %ebx for signal handling
  231.     notl %ecx
  232.     andl signal(%eax),%ecx
  233.     jne signal_return
  234. 2:    RESTORE_ALL
  235. .align 4
  236. signal_return:
  237.     movl %esp,%ecx
  238.     pushl %ecx
  239.     testl $(VM_MASK),EFLAGS(%ecx)
  240.     jne v86_signal_return
  241.     pushl %ebx
  242.     call _do_signal
  243.     popl %ebx
  244.     popl %ebx
  245.     RESTORE_ALL
  246. .align 4
  247. v86_signal_return:
  248.     call _save_v86_state
  249.     movl %eax,%esp
  250.     pushl %eax
  251.     pushl %ebx
  252.     call _do_signal
  253.     popl %ebx
  254.     popl %ebx
  255.     RESTORE_ALL
  256.  
  257. .align 4
  258. _divide_error:
  259.     pushl $0        # no error code
  260.     pushl $_do_divide_error
  261. .align 4,0x90
  262. error_code:
  263.     push %fs
  264.     push %es
  265.     push %ds
  266.     pushl %eax
  267.     pushl %ebp
  268.     pushl %edi
  269.     pushl %esi
  270.     pushl %edx
  271.     pushl %ecx
  272.     pushl %ebx
  273.     movl $0,%eax
  274.     movl %eax,%db7            # disable hardware debugging...
  275.     cld
  276.     movl $-1, %eax
  277.     xchgl %eax, ORIG_EAX(%esp)    # orig_eax (get the error code. )
  278.     xorl %ebx,%ebx            # zero ebx
  279.     mov %gs,%bx            # get the lower order bits of gs
  280.     xchgl %ebx, GS(%esp)        # get the address and save gs.
  281.     pushl %eax            # push the error code
  282.     lea 4(%esp),%edx
  283.     pushl %edx
  284.     movl $(KERNEL_DS),%edx
  285.     mov %dx,%ds
  286.     mov %dx,%es
  287.     movl $(USER_DS),%edx
  288.     mov %dx,%fs
  289.     pushl %eax
  290.     movl _current,%eax
  291.     movl %db6,%edx
  292.     movl %edx,dbgreg6(%eax)  # save current hardware debugging status
  293.     popl %eax
  294.     call *%ebx
  295.     addl $8,%esp
  296.     jmp ret_from_sys_call
  297.  
  298. .align 4
  299. _coprocessor_error:
  300.     pushl $0
  301.     pushl $_do_coprocessor_error
  302.     jmp error_code
  303.  
  304. .align 4
  305. _device_not_available:
  306.     pushl $-1        # mark this as an int
  307.     SAVE_ALL
  308.     pushl $ret_from_sys_call
  309.     movl %cr0,%eax
  310.     testl $0x4,%eax            # EM (math emulation bit)
  311.     je _math_state_restore
  312.     pushl $0        # temporary storage for ORIG_EIP
  313.     call _math_emulate
  314.     addl $4,%esp
  315.     ret
  316.  
  317. .align 4
  318. _debug:
  319.     pushl $0
  320.     pushl $_do_debug
  321.     jmp error_code
  322.  
  323. .align 4
  324. _nmi:
  325.     pushl $0
  326.     pushl $_do_nmi
  327.     jmp error_code
  328.  
  329. .align 4
  330. _int3:
  331.     pushl $0
  332.     pushl $_do_int3
  333.     jmp error_code
  334.  
  335. .align 4
  336. _overflow:
  337.     pushl $0
  338.     pushl $_do_overflow
  339.     jmp error_code
  340.  
  341. .align 4
  342. _bounds:
  343.     pushl $0
  344.     pushl $_do_bounds
  345.     jmp error_code
  346.  
  347. .align 4
  348. _invalid_op:
  349.     pushl $0
  350.     pushl $_do_invalid_op
  351.     jmp error_code
  352.  
  353. .align 4
  354. _coprocessor_segment_overrun:
  355.     pushl $0
  356.     pushl $_do_coprocessor_segment_overrun
  357.     jmp error_code
  358.  
  359. .align 4
  360. _reserved:
  361.     pushl $0
  362.     pushl $_do_reserved
  363.     jmp error_code
  364.  
  365. .align 4
  366. _double_fault:
  367.     pushl $_do_double_fault
  368.     jmp error_code
  369.  
  370. .align 4
  371. _invalid_TSS:
  372.     pushl $_do_invalid_TSS
  373.     jmp error_code
  374.  
  375. .align 4
  376. _segment_not_present:
  377.     pushl $_do_segment_not_present
  378.     jmp error_code
  379.  
  380. .align 4
  381. _stack_segment:
  382.     pushl $_do_stack_segment
  383.     jmp error_code
  384.  
  385. .align 4
  386. _general_protection:
  387.     pushl $_do_general_protection
  388.     jmp error_code
  389.  
  390. .align 4
  391. _alignment_check:
  392.     pushl $_do_alignment_check
  393.     jmp error_code
  394.  
  395. .align 4
  396. _page_fault:
  397.     pushl $_do_page_fault
  398.     jmp error_code
  399.  
  400. .data
  401. .align 4
  402. _sys_call_table:
  403.     .long _sys_setup        /* 0 */
  404.     .long _sys_exit
  405.     .long _sys_fork
  406.     .long _sys_read
  407.     .long _sys_write
  408.     .long _sys_open            /* 5 */
  409.     .long _sys_close
  410.     .long _sys_waitpid
  411.     .long _sys_creat
  412.     .long _sys_link
  413.     .long _sys_unlink        /* 10 */
  414.     .long _sys_execve
  415.     .long _sys_chdir
  416.     .long _sys_time
  417.     .long _sys_mknod
  418.     .long _sys_chmod        /* 15 */
  419.     .long _sys_chown
  420.     .long _sys_break
  421.     .long _sys_stat
  422.     .long _sys_lseek
  423.     .long _sys_getpid        /* 20 */
  424.     .long _sys_mount
  425.     .long _sys_umount
  426.     .long _sys_setuid
  427.     .long _sys_getuid
  428.     .long _sys_stime        /* 25 */
  429.     .long _sys_ptrace
  430.     .long _sys_alarm
  431.     .long _sys_fstat
  432.     .long _sys_pause
  433.     .long _sys_utime        /* 30 */
  434.     .long _sys_stty
  435.     .long _sys_gtty
  436.     .long _sys_access
  437.     .long _sys_nice
  438.     .long _sys_ftime        /* 35 */
  439.     .long _sys_sync
  440.     .long _sys_kill
  441.     .long _sys_rename
  442.     .long _sys_mkdir
  443.     .long _sys_rmdir        /* 40 */
  444.     .long _sys_dup
  445.     .long _sys_pipe
  446.     .long _sys_times
  447.     .long _sys_prof
  448.     .long _sys_brk            /* 45 */
  449.     .long _sys_setgid
  450.     .long _sys_getgid
  451.     .long _sys_signal
  452.     .long _sys_geteuid
  453.     .long _sys_getegid        /* 50 */
  454.     .long _sys_acct
  455.     .long _sys_phys
  456.     .long _sys_lock
  457.     .long _sys_ioctl
  458.     .long _sys_fcntl        /* 55 */
  459.     .long _sys_mpx
  460.     .long _sys_setpgid
  461.     .long _sys_ulimit
  462.     .long _sys_olduname
  463.     .long _sys_umask        /* 60 */
  464.     .long _sys_chroot
  465.     .long _sys_ustat
  466.     .long _sys_dup2
  467.     .long _sys_getppid
  468.     .long _sys_getpgrp        /* 65 */
  469.     .long _sys_setsid
  470.     .long _sys_sigaction
  471.     .long _sys_sgetmask
  472.     .long _sys_ssetmask
  473.     .long _sys_setreuid        /* 70 */
  474.     .long _sys_setregid
  475.     .long _sys_sigsuspend
  476.     .long _sys_sigpending
  477.     .long _sys_sethostname
  478.     .long _sys_setrlimit        /* 75 */
  479.     .long _sys_getrlimit
  480.     .long _sys_getrusage
  481.     .long _sys_gettimeofday
  482.     .long _sys_settimeofday
  483.     .long _sys_getgroups        /* 80 */
  484.     .long _sys_setgroups
  485.     .long _sys_select
  486.     .long _sys_symlink
  487.     .long _sys_lstat
  488.     .long _sys_readlink        /* 85 */
  489.     .long _sys_uselib
  490.     .long _sys_swapon
  491.     .long _sys_reboot
  492.     .long _sys_readdir
  493.     .long _sys_mmap            /* 90 */
  494.     .long _sys_munmap
  495.     .long _sys_truncate
  496.     .long _sys_ftruncate
  497.     .long _sys_fchmod
  498.     .long _sys_fchown        /* 95 */
  499.     .long _sys_getpriority
  500.     .long _sys_setpriority
  501.     .long _sys_profil
  502.     .long _sys_statfs
  503.     .long _sys_fstatfs        /* 100 */
  504.     .long _sys_ioperm
  505.     .long _sys_socketcall
  506.     .long _sys_syslog
  507.     .long _sys_setitimer
  508.     .long _sys_getitimer        /* 105 */
  509.     .long _sys_newstat
  510.     .long _sys_newlstat
  511.     .long _sys_newfstat
  512.     .long _sys_uname
  513.     .long _sys_iopl            /* 110 */
  514.     .long _sys_vhangup
  515.     .long _sys_idle
  516.     .long _sys_vm86
  517.     .long _sys_wait4
  518.     .long _sys_swapoff        /* 115 */
  519.     .long _sys_sysinfo
  520.     .long _sys_ipc
  521.     .long _sys_fsync
  522.     .long _sys_sigreturn
  523.     .long _sys_clone        /* 120 */
  524.     .long _sys_setdomainname
  525.     .long _sys_newuname
  526.     .long _sys_modify_ldt
  527.     .long _sys_adjtimex
  528.     .long _sys_mprotect        /* 125 */
  529.     .long _sys_sigprocmask
  530.     .long _sys_create_module
  531.     .long _sys_init_module
  532.     .long _sys_delete_module
  533.     .long _sys_get_kernel_syms    /* 130 */
  534.     .long _sys_quotactl
  535.     .long _sys_getpgid
  536.     .long _sys_fchdir
  537.     .long _sys_bdflush
  538.     .long _sys_sysfs        /* 135 */
  539.     .long _sys_personality
  540.     .long 0                /* for afs_syscall */
  541.     .long _sys_setfsuid
  542.     .long _sys_setfsgid
  543.     .long _sys_llseek        /* 140 */
  544.     .space (NR_syscalls-140)*4
  545.