📄 mpx386.s.cpp
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/kernel/mpx386.s
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
05900 #
05901 ! This file contains the assembler startup code for Minix and the 32-bit
05902 ! interrupt handlers. It cooperates with start.c to set up a good
05903 ! environment for main().
05904
05905 ! This file is part of the lowest layer of the MINIX kernel. The other part
05906 ! is "proc.c". The lowest layer does process switching and message handling.
05907
05908 ! Every transition to the kernel goes through this file. Transitions are
05909 ! caused by sending/receiving messages and by most interrupts. (RS232
05910 ! interrupts may be handled in the file "rs2.s" and then they rarely enter
05911 ! the kernel.)
05912
05913 ! Transitions to the kernel may be nested. The initial entry may be with a
05914 ! system call, exception or hardware interrupt; reentries may only be made
05915 ! by hardware interrupts. The count of reentries is kept in "k_reenter".
05916 ! It is important for deciding whether to switch to the kernel stack and
05917 ! for protecting the message passing code in "proc.c".
05918
05919 ! For the message passing trap, most of the machine state is saved in the
05920 ! proc table. (Some of the registers need not be saved.) Then the stack is
05921 ! switched to "k_stack", and interrupts are reenabled. Finally, the system
05922 ! call handler (in C) is called. When it returns, interrupts are disabled
05923 ! again and the code falls into the restart routine, to finish off held-up
05924 ! interrupts and run the process or task whose pointer is in "proc_ptr".
05925
05926 ! Hardware interrupt handlers do the same, except (1) The entire state must
05927 ! be saved. (2) There are too many handlers to do this inline, so the save
05928 ! routine is called. A few cycles are saved by pushing the address of the
05929 ! appropiate restart routine for a return later. (3) A stack switch is
05930 ! avoided when the stack is already switched. (4) The (master) 8259 interrupt
05931 ! controller is reenabled centrally in save(). (5) Each interrupt handler
05932 ! masks its interrupt line using the 8259 before enabling (other unmasked)
05933 ! interrupts, and unmasks it after servicing the interrupt. This limits the
05934 ! nest level to the number of lines and protects the handler from itself.
05935
05936 ! For communication with the boot monitor at startup time some constant
05937 ! data are compiled into the beginning of the text segment. This facilitates
05938 ! reading the data at the start of the boot process, since only the first
05939 ! sector of the file needs to be read.
05940
05941 ! Some data storage is also allocated at the end of this file. This data
05942 ! will be at the start of the data segment of the kernel and will be read
05943 ! and modified by the boot monitor before the kernel starts.
05944
05945 ! sections
05946
05947 .sect .text
05948 begtext:
05949 .sect .rom
05950 begrom:
05951 .sect .data
05952 begdata:
05953 .sect .bss
05954 begbss:
05955
05956 #include <minix/config.h>
05957 #include <minix/const.h>
05958 #include <minix/com.h>
05959 #include "const.h"
05960 #include "protect.h"
05961 #include "sconst.h"
05962
05963 /* Selected 386 tss offsets. */
05964 #define TSS3_S_SP0 4
05965
05966 ! Exported functions
05967 ! Note: in assembly language the .define statement applied to a function name
05968 ! is loosely equivalent to a prototype in C code -- it makes it possible to
05969 ! link to an entity declared in the assembly code but does not create
05970 ! the entity.
05971
05972 .define _idle_task
05973 .define _restart
05974 .define save
05975
05976 .define _divide_error
05977 .define _single_step_exception
05978 .define _nmi
05979 .define _breakpoint_exception
05980 .define _overflow
05981 .define _bounds_check
05982 .define _inval_opcode
05983 .define _copr_not_available
05984 .define _double_fault
05985 .define _copr_seg_overrun
05986 .define _inval_tss
05987 .define _segment_not_present
05988 .define _stack_exception
05989 .define _general_protection
05990 .define _page_fault
05991 .define _copr_error
05992
05993 .define _hwint00 ! handlers for hardware interrupts
05994 .define _hwint01
05995 .define _hwint02
05996 .define _hwint03
05997 .define _hwint04
05998 .define _hwint05
05999 .define _hwint06
06000 .define _hwint07
06001 .define _hwint08
06002 .define _hwint09
06003 .define _hwint10
06004 .define _hwint11
06005 .define _hwint12
06006 .define _hwint13
06007 .define _hwint14
06008 .define _hwint15
06009
06010 .define _s_call
06011 .define _p_s_call
06012 .define _level0_call
06013
06014 ! Imported functions.
06015
06016 .extern _cstart
06017 .extern _main
06018 .extern _exception
06019 .extern _interrupt
06020 .extern _sys_call
06021 .extern _unhold
06022
06023 ! Exported variables.
06024 ! Note: when used with a variable the .define does not reserve storage,
06025 ! it makes the name externally visible so it may be linked to.
06026
06027 .define begbss
06028 .define begdata
06029 .define _sizes
06030
06031 ! Imported variables.
06032
06033 .extern _gdt
06034 .extern _code_base
06035 .extern _data_base
06036 .extern _held_head
06037 .extern _k_reenter
06038 .extern _pc_at
06039 .extern _proc_ptr
06040 .extern _ps_mca
06041 .extern _tss
06042 .extern _level0_func
06043 .extern _mon_sp
06044 .extern _mon_return
06045 .extern _reboot_code
06046
06047 .sect .text
06048 !*===========================================================================*
06049 !* MINIX *
06050 !*===========================================================================*
06051 MINIX: ! this is the entry point for the MINIX kernel
06052 jmp over_flags ! skip over the next few bytes
06053 .data2 CLICK_SHIFT ! for the monitor: memory granularity
06054 flags:
06055 .data2 0x002D ! boot monitor flags:
06056 ! call in 386 mode, make stack,
06057 ! load high, will return
06058 nop ! extra byte to sync up disassembler
06059 over_flags:
06060
06061 ! Set up a C stack frame on the monitor stack. (The monitor sets cs and ds
06062 ! right. The ss descriptor still references the monitor data segment.)
06063 movzx esp, sp ! monitor stack is a 16 bit stack
06064 push ebp
06065 mov ebp, esp
06066 push esi
06067 push edi
06068 cmp 4(ebp), 0 ! nonzero if return possible
06069 jz noret
06070 inc (_mon_return)
06071 noret: mov (_mon_sp), esp ! save stack pointer for later return
06072
06073 ! Copy the monitor global descriptor table to the address space of kernel and
06074 ! switch over to it. Prot_init() can then update it with immediate effect.
06075
06076 sgdt (_gdt+GDT_SELECTOR) ! get the monitor gdtr
06077 mov esi, (_gdt+GDT_SELECTOR+2) ! absolute address of GDT
06078 mov ebx, _gdt ! address of kernel GDT
06079 mov ecx, 8*8 ! copying eight descriptors
06080 copygdt:
06081 eseg movb al, (esi)
06082 movb (ebx), al
06083 inc esi
06084 inc ebx
06085 loop copygdt
06086 mov eax, (_gdt+DS_SELECTOR+2) ! base of kernel data
06087 and eax, 0x00FFFFFF ! only 24 bits
06088 add eax, _gdt ! eax = vir2phys(gdt)
06089 mov (_gdt+GDT_SELECTOR+2), eax ! set base of GDT
06090 lgdt (_gdt+GDT_SELECTOR) ! switch over to kernel GDT
06091
06092 ! Locate boot parameters, set up kernel segment registers and stack.
06093 mov ebx, 8(ebp) ! boot parameters offset
06094 mov edx, 12(ebp) ! boot parameters length
06095 mov ax, ds ! kernel data
06096 mov es, ax
06097 mov fs, ax
06098 mov gs, ax
06099 mov ss, ax
06100 mov esp, k_stktop ! set sp to point to the top of kernel stack
06101
06102 ! Call C startup code to set up a proper environment to run main().
06103 push edx
06104 push ebx
06105 push SS_SELECTOR
06106 push MON_CS_SELECTOR
06107 push DS_SELECTOR
06108 push CS_SELECTOR
06109 call _cstart ! cstart(cs, ds, mcs, mds, parmoff, parmlen)
06110 add esp, 6*4
06111
06112 ! Reload gdtr, idtr and the segment registers to global descriptor table set
06113 ! up by prot_init().
06114
06115 lgdt (_gdt+GDT_SELECTOR)
06116 lidt (_gdt+IDT_SELECTOR)
06117
06118 jmpf CS_SELECTOR:csinit
06119 csinit:
06120 o16 mov ax, DS_SELECTOR
06121 mov ds, ax
06122 mov es, ax
06123 mov fs, ax
06124 mov gs, ax
06125 mov ss, ax
06126 o16 mov ax, TSS_SELECTOR ! no other TSS is used
06127 ltr ax
06128 push 0 ! set flags to known good state
06129 popf ! esp, clear nested task and int enable
06130
06131 jmp _main ! main()
06132
06133
06134 !*===========================================================================*
06135 !* interrupt handlers *
06136 !* interrupt handlers for 386 32-bit protected mode *
06137 !*===========================================================================*
06138
06139 !*===========================================================================*
06140 !* hwint00 - 07 *
06141 !*===========================================================================*
06142 ! Note this is a macro, it looks like a subroutine.
06143 #define hwint_master(irq) \
06144 call save /* save interrupted process state */;\
06145 inb INT_CTLMASK ;\
06146 orb al, [1<<irq] ;\
06147 outb INT_CTLMASK /* disable the irq */;\
06148 movb al, ENABLE ;\
06149 outb INT_CTL /* reenable master 8259 */;\
06150 sti /* enable interrupts */;\
06151 push irq /* irq */;\
06152 call (_irq_table + 4*irq) /* eax = (*irq_table[irq])(irq) */;\
06153 pop ecx ;\
06154 cli /* disable interrupts */;\
06155 test eax, eax /* need to reenable irq? */;\
06156 jz 0f ;\
06157 inb INT_CTLMASK ;\
06158 andb al, ~[1<<irq] ;\
06159 outb INT_CTLMASK /* enable the irq */;\
06160 0: ret /* restart (another) process */
06161
06162 ! Each of these entry points is an expansion of the hwint_master macro
06163 .align 16
06164 _hwint00: ! Interrupt routine for irq 0 (the clock).
06165 hwint_master(0)
06166
06167 .align 16
06168 _hwint01: ! Interrupt routine for irq 1 (keyboard)
06169 hwint_master(1)
06170
06171 .align 16
06172 _hwint02: ! Interrupt routine for irq 2 (cascade!)
06173 hwint_master(2)
06174
06175 .align 16
06176 _hwint03: ! Interrupt routine for irq 3 (second serial)
06177 hwint_master(3)
06178
06179 .align 16
06180 _hwint04: ! Interrupt routine for irq 4 (first serial)
06181 hwint_master(4)
06182
06183 .align 16
06184 _hwint05: ! Interrupt routine for irq 5 (XT winchester)
06185 hwint_master(5)
06186
06187 .align 16
06188 _hwint06: ! Interrupt routine for irq 6 (floppy)
06189 hwint_master(6)
06190
06191 .align 16
06192 _hwint07: ! Interrupt routine for irq 7 (printer)
06193 hwint_master(7)
06194
06195 !*===========================================================================*
06196 !* hwint08 - 15 *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -