The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kernel/mpx386.s

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 # 
    2 ! This file, mpx386.s, is included by mpx.s when Minix is compiled for 
    3 ! 32-bit Intel CPUs. The alternative mpx88.s is compiled for 16-bit CPUs.
    4 
    5 ! This file is part of the lowest layer of the MINIX kernel.  (The other part
    6 ! is "proc.c".)  The lowest layer does process switching and message handling.
    7 ! Furthermore it contains the assembler startup code for Minix and the 32-bit
    8 ! interrupt handlers.  It cooperates with the code in "start.c" to set up a 
    9 ! good environment for main().
   10 
   11 ! Every transition to the kernel goes through this file.  Transitions to the 
   12 ! kernel may be nested.  The initial entry may be with a system call (i.e., 
   13 ! send or receive a message), an exception or a hardware interrupt;  kernel 
   14 ! reentries may only be made by hardware interrupts.  The count of reentries 
   15 ! is kept in "k_reenter". It is important for deciding whether to switch to 
   16 ! the kernel stack and for protecting the message passing code in "proc.c".
   17 
   18 ! For the message passing trap, most of the machine state is saved in the
   19 ! proc table.  (Some of the registers need not be saved.)  Then the stack is
   20 ! switched to "k_stack", and interrupts are reenabled.  Finally, the system
   21 ! call handler (in C) is called.  When it returns, interrupts are disabled
   22 ! again and the code falls into the restart routine, to finish off held-up
   23 ! interrupts and run the process or task whose pointer is in "proc_ptr".
   24 
   25 ! Hardware interrupt handlers do the same, except  (1) The entire state must
   26 ! be saved.  (2) There are too many handlers to do this inline, so the save
   27 ! routine is called.  A few cycles are saved by pushing the address of the
   28 ! appropiate restart routine for a return later.  (3) A stack switch is
   29 ! avoided when the stack is already switched.  (4) The (master) 8259 interrupt
   30 ! controller is reenabled centrally in save().  (5) Each interrupt handler
   31 ! masks its interrupt line using the 8259 before enabling (other unmasked)
   32 ! interrupts, and unmasks it after servicing the interrupt.  This limits the
   33 ! nest level to the number of lines and protects the handler from itself.
   34 
   35 ! For communication with the boot monitor at startup time some constant
   36 ! data are compiled into the beginning of the text segment. This facilitates 
   37 ! reading the data at the start of the boot process, since only the first
   38 ! sector of the file needs to be read.
   39 
   40 ! Some data storage is also allocated at the end of this file. This data 
   41 ! will be at the start of the data segment of the kernel and will be read
   42 ! and modified by the boot monitor before the kernel starts.
   43 
   44 ! sections
   45 
   46 .sect .text
   47 begtext:
   48 .sect .rom
   49 begrom:
   50 .sect .data
   51 begdata:
   52 .sect .bss
   53 begbss:
   54 
   55 #include <minix/config.h>
   56 #include <minix/const.h>
   57 #include <minix/com.h>
   58 #include <ibm/interrupt.h>
   59 #include "const.h"
   60 #include "protect.h"
   61 #include "sconst.h"
   62 
   63 /* Selected 386 tss offsets. */
   64 #define TSS3_S_SP0      4
   65 
   66 ! Exported functions
   67 ! Note: in assembly language the .define statement applied to a function name 
   68 ! is loosely equivalent to a prototype in C code -- it makes it possible to
   69 ! link to an entity declared in the assembly code but does not create
   70 ! the entity.
   71 
   72 .define _restart
   73 .define save
   74 
   75 .define _divide_error
   76 .define _single_step_exception
   77 .define _nmi
   78 .define _breakpoint_exception
   79 .define _overflow
   80 .define _bounds_check
   81 .define _inval_opcode
   82 .define _copr_not_available
   83 .define _double_fault
   84 .define _copr_seg_overrun
   85 .define _inval_tss
   86 .define _segment_not_present
   87 .define _stack_exception
   88 .define _general_protection
   89 .define _page_fault
   90 .define _copr_error
   91 
   92 .define _hwint00        ! handlers for hardware interrupts
   93 .define _hwint01
   94 .define _hwint02
   95 .define _hwint03
   96 .define _hwint04
   97 .define _hwint05
   98 .define _hwint06
   99 .define _hwint07
  100 .define _hwint08
  101 .define _hwint09
  102 .define _hwint10
  103 .define _hwint11
  104 .define _hwint12
  105 .define _hwint13
  106 .define _hwint14
  107 .define _hwint15
  108 
  109 .define _s_call
  110 .define _p_s_call
  111 .define _level0_call
  112 
  113 ! Exported variables.
  114 .define begbss
  115 .define begdata
  116 
  117 .sect .text
  118 !*===========================================================================*
  119 !*                              MINIX                                        *
  120 !*===========================================================================*
  121 MINIX:                          ! this is the entry point for the MINIX kernel
  122         jmp     over_flags      ! skip over the next few bytes
  123         .data2  CLICK_SHIFT     ! for the monitor: memory granularity
  124 flags:
  125         .data2  0x01FD          ! boot monitor flags:
  126                                 !       call in 386 mode, make bss, make stack,
  127                                 !       load high, don't patch, will return,
  128                                 !       uses generic INT, memory vector,
  129                                 !       new boot code return
  130         nop                     ! extra byte to sync up disassembler
  131 over_flags:
  132 
  133 ! Set up a C stack frame on the monitor stack.  (The monitor sets cs and ds
  134 ! right.  The ss descriptor still references the monitor data segment.)
  135         movzx   esp, sp         ! monitor stack is a 16 bit stack
  136         push    ebp
  137         mov     ebp, esp
  138         push    esi
  139         push    edi
  140         cmp     4(ebp), 0       ! monitor return vector is
  141         jz      noret           ! nonzero if return possible
  142         inc     (_mon_return)
  143 noret:  mov     (_mon_sp), esp  ! save stack pointer for later return
  144 
  145 ! Copy the monitor global descriptor table to the address space of kernel and
  146 ! switch over to it.  Prot_init() can then update it with immediate effect.
  147 
  148         sgdt    (_gdt+GDT_SELECTOR)             ! get the monitor gdtr
  149         mov     esi, (_gdt+GDT_SELECTOR+2)      ! absolute address of GDT
  150         mov     ebx, _gdt                       ! address of kernel GDT
  151         mov     ecx, 8*8                        ! copying eight descriptors
  152 copygdt:
  153  eseg   movb    al, (esi)
  154         movb    (ebx), al
  155         inc     esi
  156         inc     ebx
  157         loop    copygdt
  158         mov     eax, (_gdt+DS_SELECTOR+2)       ! base of kernel data
  159         and     eax, 0x00FFFFFF                 ! only 24 bits
  160         add     eax, _gdt                       ! eax = vir2phys(gdt)
  161         mov     (_gdt+GDT_SELECTOR+2), eax      ! set base of GDT
  162         lgdt    (_gdt+GDT_SELECTOR)             ! switch over to kernel GDT
  163 
  164 ! Locate boot parameters, set up kernel segment registers and stack.
  165         mov     ebx, 8(ebp)     ! boot parameters offset
  166         mov     edx, 12(ebp)    ! boot parameters length
  167         mov     eax, 16(ebp)    ! address of a.out headers
  168         mov     (_aout), eax
  169         mov     ax, ds          ! kernel data
  170         mov     es, ax
  171         mov     fs, ax
  172         mov     gs, ax
  173         mov     ss, ax
  174         mov     esp, k_stktop   ! set sp to point to the top of kernel stack
  175 
  176 ! Call C startup code to set up a proper environment to run main().
  177         push    edx
  178         push    ebx
  179         push    SS_SELECTOR
  180         push    DS_SELECTOR
  181         push    CS_SELECTOR
  182         call    _cstart         ! cstart(cs, ds, mds, parmoff, parmlen)
  183         add     esp, 5*4
  184 
  185 ! Reload gdtr, idtr and the segment registers to global descriptor table set
  186 ! up by prot_init().
  187 
  188         lgdt    (_gdt+GDT_SELECTOR)
  189         lidt    (_gdt+IDT_SELECTOR)
  190 
  191         jmpf    CS_SELECTOR:csinit
  192 csinit:
  193     o16 mov     ax, DS_SELECTOR
  194         mov     ds, ax
  195         mov     es, ax
  196         mov     fs, ax
  197         mov     gs, ax
  198         mov     ss, ax
  199     o16 mov     ax, TSS_SELECTOR        ! no other TSS is used
  200         ltr     ax
  201         push    0                       ! set flags to known good state
  202         popf                            ! esp, clear nested task and int enable
  203 
  204         jmp     _main                   ! main()
  205 
  206 
  207 !*===========================================================================*
  208 !*                              interrupt handlers                           *
  209 !*              interrupt handlers for 386 32-bit protected mode             *
  210 !*===========================================================================*
  211 
  212 !*===========================================================================*
  213 !*                              hwint00 - 07                                 *
  214 !*===========================================================================*
  215 ! Note this is a macro, it just looks like a subroutine.
  216 #define hwint_master(irq)       \
  217         call    save                    /* save interrupted process state */;\
  218         push    (_irq_handlers+4*irq)   /* irq_handlers[irq]              */;\
  219         call    _intr_handle            /* intr_handle(irq_handlers[irq]) */;\
  220         pop     ecx                                                         ;\
  221         cmp     (_irq_actids+4*irq), 0  /* interrupt still active?        */;\
  222         jz      0f                                                          ;\
  223         inb     INT_CTLMASK             /* get current mask */              ;\
  224         orb     al, [1<<irq]            /* mask irq */                      ;\
  225         outb    INT_CTLMASK             /* disable the irq                */;\
  226 0:      movb    al, END_OF_INT                                              ;\
  227         outb    INT_CTL                 /* reenable master 8259           */;\
  228         ret                             /* restart (another) process      */
  229 
  230 ! Each of these entry points is an expansion of the hwint_master macro
  231         .align  16
  232 _hwint00:               ! Interrupt routine for irq 0 (the clock).
  233         hwint_master(0)
  234 
  235         .align  16
  236 _hwint01:               ! Interrupt routine for irq 1 (keyboard)
  237         hwint_master(1)
  238 
  239         .align  16
  240 _hwint02:               ! Interrupt routine for irq 2 (cascade!)
  241         hwint_master(2)
  242 
  243         .align  16
  244 _hwint03:               ! Interrupt routine for irq 3 (second serial)
  245         hwint_master(3)
  246 
  247         .align  16
  248 _hwint04:               ! Interrupt routine for irq 4 (first serial)
  249         hwint_master(4)
  250 
  251         .align  16
  252 _hwint05:               ! Interrupt routine for irq 5 (XT winchester)
  253         hwint_master(5)
  254 
  255         .align  16
  256 _hwint06:               ! Interrupt routine for irq 6 (floppy)
  257         hwint_master(6)
  258 
  259         .align  16
  260 _hwint07:               ! Interrupt routine for irq 7 (printer)
  261         hwint_master(7)
  262 
  263 !*===========================================================================*
  264 !*                              hwint08 - 15                                 *
  265 !*===========================================================================*
  266 ! Note this is a macro, it just looks like a subroutine.
  267 #define hwint_slave(irq)        \
  268         call    save                    /* save interrupted process state */;\
  269         push    (_irq_handlers+4*irq)   /* irq_handlers[irq]              */;\
  270         call    _intr_handle            /* intr_handle(irq_handlers[irq]) */;\
  271         pop     ecx                                                         ;\
  272         cmp     (_irq_actids+4*irq), 0  /* interrupt still active?        */;\
  273         jz      0f                                                          ;\
  274         inb     INT2_CTLMASK                                                ;\
  275         orb     al, [1<<[irq-8]]                                            ;\
  276         outb    INT2_CTLMASK            /* disable the irq                */;\
  277 0:      movb    al, END_OF_INT                                              ;\
  278         outb    INT_CTL                 /* reenable master 8259           */;\
  279         outb    INT2_CTL                /* reenable slave 8259            */;\
  280         ret                             /* restart (another) process      */
  281 
  282 ! Each of these entry points is an expansion of the hwint_slave macro
  283         .align  16
  284 _hwint08:               ! Interrupt routine for irq 8 (realtime clock)
  285         hwint_slave(8)
  286 
  287         .align  16
  288 _hwint09:               ! Interrupt routine for irq 9 (irq 2 redirected)
  289         hwint_slave(9)
  290 
  291         .align  16
  292 _hwint10:               ! Interrupt routine for irq 10
  293         hwint_slave(10)
  294 
  295         .align  16
  296 _hwint11:               ! Interrupt routine for irq 11
  297         hwint_slave(11)
  298 
  299         .align  16
  300 _hwint12:               ! Interrupt routine for irq 12
  301         hwint_slave(12)
  302 
  303         .align  16
  304 _hwint13:               ! Interrupt routine for irq 13 (FPU exception)
  305         hwint_slave(13)
  306 
  307         .align  16
  308 _hwint14:               ! Interrupt routine for irq 14 (AT winchester)
  309         hwint_slave(14)
  310 
  311         .align  16
  312 _hwint15:               ! Interrupt routine for irq 15
  313         hwint_slave(15)
  314 
  315 !*===========================================================================*
  316 !*                              save                                         *
  317 !*===========================================================================*
  318 ! Save for protected mode.
  319 ! This is much simpler than for 8086 mode, because the stack already points
  320 ! into the process table, or has already been switched to the kernel stack.
  321 
  322         .align  16
  323 save:
  324         cld                     ! set direction flag to a known value
  325         pushad                  ! save "general" registers
  326     o16 push    ds              ! save ds
  327     o16 push    es              ! save es
  328     o16 push    fs              ! save fs
  329     o16 push    gs              ! save gs
  330         mov     dx, ss          ! ss is kernel data segment
  331         mov     ds, dx          ! load rest of kernel segments
  332         mov     es, dx          ! kernel does not use fs, gs
  333         mov     eax, esp        ! prepare to return
  334         incb    (_k_reenter)    ! from -1 if not reentering
  335         jnz     set_restart1    ! stack is already kernel stack
  336         mov     esp, k_stktop
  337         push    _restart        ! build return address for int handler
  338         xor     ebp, ebp        ! for stacktrace
  339         jmp     RETADR-P_STACKBASE(eax)
  340 
  341         .align  4
  342 set_restart1:
  343         push    restart1
  344         jmp     RETADR-P_STACKBASE(eax)
  345 
  346 !*===========================================================================*
  347 !*                              _s_call                                      *
  348 !*===========================================================================*
  349         .align  16
  350 _s_call:
  351 _p_s_call:
  352         cld                     ! set direction flag to a known value
  353         sub     esp, 6*4        ! skip RETADR, eax, ecx, edx, ebx, est
  354         push    ebp             ! stack already points into proc table
  355         push    esi
  356         push    edi
  357     o16 push    ds
  358     o16 push    es
  359     o16 push    fs
  360     o16 push    gs
  361         mov     dx, ss
  362         mov     ds, dx
  363         mov     es, dx
  364         incb    (_k_reenter)
  365         mov     esi, esp        ! assumes P_STACKBASE == 0
  366         mov     esp, k_stktop
  367         xor     ebp, ebp        ! for stacktrace
  368                                 ! end of inline save
  369                                 ! now set up parameters for sys_call()
  370         push    ebx             ! pointer to user message
  371         push    eax             ! src/dest
  372         push    ecx             ! SEND/RECEIVE/BOTH
  373         call    _sys_call       ! sys_call(function, src_dest, m_ptr)
  374                                 ! caller is now explicitly in proc_ptr
  375         mov     AXREG(esi), eax ! sys_call MUST PRESERVE si
  376 
  377 ! Fall into code to restart proc/task running.
  378 
  379 !*===========================================================================*
  380 !*                              restart                                      *
  381 !*===========================================================================*
  382 _restart:
  383 
  384 ! Restart the current process or the next process if it is set. 
  385 
  386         cmp     (_next_ptr), 0          ! see if another process is scheduled
  387         jz      0f
  388         mov     eax, (_next_ptr)
  389         mov     (_proc_ptr), eax        ! schedule new process 
  390         mov     (_next_ptr), 0
  391 0:      mov     esp, (_proc_ptr)        ! will assume P_STACKBASE == 0
  392         lldt    P_LDT_SEL(esp)          ! enable process' segment descriptors 
  393         lea     eax, P_STACKTOP(esp)    ! arrange for next interrupt
  394         mov     (_tss+TSS3_S_SP0), eax  ! to save state in process table
  395 restart1:
  396         decb    (_k_reenter)
  397     o16 pop     gs
  398     o16 pop     fs
  399     o16 pop     es
  400     o16 pop     ds
  401         popad
  402         add     esp, 4          ! skip return adr
  403         iretd                   ! continue process
  404 
  405 !*===========================================================================*
  406 !*                              exception handlers                           *
  407 !*===========================================================================*
  408 _divide_error:
  409         push    DIVIDE_VECTOR
  410         jmp     exception
  411 
  412 _single_step_exception:
  413         push    DEBUG_VECTOR
  414         jmp     exception
  415 
  416 _nmi:
  417         push    NMI_VECTOR
  418         jmp     exception
  419 
  420 _breakpoint_exception:
  421         push    BREAKPOINT_VECTOR
  422         jmp     exception
  423 
  424 _overflow:
  425         push    OVERFLOW_VECTOR
  426         jmp     exception
  427 
  428 _bounds_check:
  429         push    BOUNDS_VECTOR
  430         jmp     exception
  431 
  432 _inval_opcode:
  433         push    INVAL_OP_VECTOR
  434         jmp     exception
  435 
  436 _copr_not_available:
  437         push    COPROC_NOT_VECTOR
  438         jmp     exception
  439 
  440 _double_fault:
  441         push    DOUBLE_FAULT_VECTOR
  442         jmp     errexception
  443 
  444 _copr_seg_overrun:
  445         push    COPROC_SEG_VECTOR
  446         jmp     exception
  447 
  448 _inval_tss:
  449         push    INVAL_TSS_VECTOR
  450         jmp     errexception
  451 
  452 _segment_not_present:
  453         push    SEG_NOT_VECTOR
  454         jmp     errexception
  455 
  456 _stack_exception:
  457         push    STACK_FAULT_VECTOR
  458         jmp     errexception
  459 
  460 _general_protection:
  461         push    PROTECTION_VECTOR
  462         jmp     errexception
  463 
  464 _page_fault:
  465         push    PAGE_FAULT_VECTOR
  466         jmp     errexception
  467 
  468 _copr_error:
  469         push    COPROC_ERR_VECTOR
  470         jmp     exception
  471 
  472 !*===========================================================================*
  473 !*                              exception                                    *
  474 !*===========================================================================*
  475 ! This is called for all exceptions which do not push an error code.
  476 
  477         .align  16
  478 exception:
  479  sseg   mov     (trap_errno), 0         ! clear trap_errno
  480  sseg   pop     (ex_number)
  481         jmp     exception1
  482 
  483 !*===========================================================================*
  484 !*                              errexception                                 *
  485 !*===========================================================================*
  486 ! This is called for all exceptions which push an error code.
  487 
  488         .align  16
  489 errexception:
  490  sseg   pop     (ex_number)
  491  sseg   pop     (trap_errno)
  492 exception1:                             ! Common for all exceptions.
  493         push    eax                     ! eax is scratch register
  494         mov     eax, 0+4(esp)           ! old eip
  495  sseg   mov     (old_eip), eax
  496         movzx   eax, 4+4(esp)           ! old cs
  497  sseg   mov     (old_cs), eax
  498         mov     eax, 8+4(esp)           ! old eflags
  499  sseg   mov     (old_eflags), eax
  500         pop     eax
  501         call    save
  502         push    (old_eflags)
  503         push    (old_cs)
  504         push    (old_eip)
  505         push    (trap_errno)
  506         push    (ex_number)
  507         call    _exception              ! (ex_number, trap_errno, old_eip,
  508                                         !       old_cs, old_eflags)
  509         add     esp, 5*4
  510         ret
  511 
  512 !*===========================================================================*
  513 !*                              level0_call                                  *
  514 !*===========================================================================*
  515 _level0_call:
  516         call    save
  517         jmp     (_level0_func)
  518 
  519 !*===========================================================================*
  520 !*                              data                                         *
  521 !*===========================================================================*
  522 
  523 .sect .rom      ! Before the string table please
  524         .data2  0x526F          ! this must be the first data entry (magic #)
  525 
  526 .sect .bss
  527 k_stack:
  528         .space  K_STACK_BYTES   ! kernel stack
  529 k_stktop:                       ! top of kernel stack
  530         .comm   ex_number, 4
  531         .comm   trap_errno, 4
  532         .comm   old_eip, 4
  533         .comm   old_cs, 4
  534         .comm   old_eflags, 4

Cache object: 2e845b1a977fb8483b76f8744726488a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.