📄 mpx386.s
字号:
# ! This file, mpx386.s, is included by mpx.s when Minix is compiled for ! 32-bit Intel CPUs. The alternative mpx88.s is compiled for 16-bit CPUs.! This file is part of the lowest layer of the MINIX kernel. (The other part! is "proc.c".) The lowest layer does process switching and message handling.! Furthermore it contains the assembler startup code for Minix and the 32-bit! interrupt handlers. It cooperates with the code in "start.c" to set up a ! good environment for main().! Every transition to the kernel goes through this file. Transitions to the ! kernel may be nested. The initial entry may be with a system call (i.e., ! send or receive a message), an exception or a hardware interrupt; kernel ! reentries may only be made by hardware interrupts. The count of reentries ! is kept in "k_reenter". It is important for deciding whether to switch to ! the kernel stack and for protecting the message passing code in "proc.c".! For the message passing trap, most of the machine state is saved in the! proc table. (Some of the registers need not be saved.) Then the stack is! switched to "k_stack", and interrupts are reenabled. Finally, the system! call handler (in C) is called. When it returns, interrupts are disabled! again and the code falls into the restart routine, to finish off held-up! interrupts and run the process or task whose pointer is in "proc_ptr".! Hardware interrupt handlers do the same, except (1) The entire state must! be saved. (2) There are too many handlers to do this inline, so the save! routine is called. A few cycles are saved by pushing the address of the! appropiate restart routine for a return later. (3) A stack switch is! avoided when the stack is already switched. (4) The (master) 8259 interrupt! controller is reenabled centrally in save(). (5) Each interrupt handler! masks its interrupt line using the 8259 before enabling (other unmasked)! interrupts, and unmasks it after servicing the interrupt. This limits the! nest level to the number of lines and protects the handler from itself.! For communication with the boot monitor at startup time some constant! data are compiled into the beginning of the text segment. This facilitates ! reading the data at the start of the boot process, since only the first! sector of the file needs to be read.! Some data storage is also allocated at the end of this file. This data ! will be at the start of the data segment of the kernel and will be read! and modified by the boot monitor before the kernel starts.! sections.sect .textbegtext:.sect .rombegrom:.sect .databegdata:.sect .bssbegbss:#include <minix/config.h>#include <minix/const.h>#include <minix/com.h>#include <ibm/interrupt.h>#include <archconst.h>#include "../../const.h"#include "sconst.h"/* Selected 386 tss offsets. */#define TSS3_S_SP0 4! Exported functions! Note: in assembly language the .define statement applied to a function name ! is loosely equivalent to a prototype in C code -- it makes it possible to! link to an entity declared in the assembly code but does not create! the entity..define _restart.define save.define _divide_error.define _single_step_exception.define _nmi.define _breakpoint_exception.define _overflow.define _bounds_check.define _inval_opcode.define _copr_not_available.define _double_fault.define _copr_seg_overrun.define _inval_tss.define _segment_not_present.define _stack_exception.define _general_protection.define _page_fault.define _copr_error.define _hwint00 ! handlers for hardware interrupts.define _hwint01.define _hwint02.define _hwint03.define _hwint04.define _hwint05.define _hwint06.define _hwint07.define _hwint08.define _hwint09.define _hwint10.define _hwint11.define _hwint12.define _hwint13.define _hwint14.define _hwint15.define _s_call.define _p_s_call.define _level0_call! Exported variables..define begbss.define begdata.sect .text!*===========================================================================*!* MINIX *!*===========================================================================*MINIX: ! this is the entry point for the MINIX kernel jmp over_flags ! skip over the next few bytes .data2 CLICK_SHIFT ! for the monitor: memory granularityflags: .data2 0x01FD ! boot monitor flags: ! call in 386 mode, make bss, make stack, ! load high, don't patch, will return, ! uses generic INT, memory vector, ! new boot code return nop ! extra byte to sync up disassemblerover_flags:! Set up a C stack frame on the monitor stack. (The monitor sets cs and ds! right. The ss descriptor still references the monitor data segment.) movzx esp, sp ! monitor stack is a 16 bit stack push ebp mov ebp, esp push esi push edi cmp 4(ebp), 0 ! monitor return vector is jz noret ! nonzero if return possible inc (_mon_return)noret: mov (_mon_sp), esp ! save stack pointer for later return! Copy the monitor global descriptor table to the address space of kernel and! switch over to it. Prot_init() can then update it with immediate effect. sgdt (_gdt+GDT_SELECTOR) ! get the monitor gdtr mov esi, (_gdt+GDT_SELECTOR+2) ! absolute address of GDT mov ebx, _gdt ! address of kernel GDT mov ecx, 8*8 ! copying eight descriptorscopygdt: eseg movb al, (esi) movb (ebx), al inc esi inc ebx loop copygdt mov eax, (_gdt+DS_SELECTOR+2) ! base of kernel data and eax, 0x00FFFFFF ! only 24 bits add eax, _gdt ! eax = vir2phys(gdt) mov (_gdt+GDT_SELECTOR+2), eax ! set base of GDT lgdt (_gdt+GDT_SELECTOR) ! switch over to kernel GDT! Locate boot parameters, set up kernel segment registers and stack. mov ebx, 8(ebp) ! boot parameters offset mov edx, 12(ebp) ! boot parameters length mov eax, 16(ebp) ! address of a.out headers mov (_aout), eax mov ax, ds ! kernel data mov es, ax mov fs, ax mov gs, ax mov ss, ax mov esp, k_stktop ! set sp to point to the top of kernel stack! Call C startup code to set up a proper environment to run main(). push edx push ebx push SS_SELECTOR push DS_SELECTOR push CS_SELECTOR call _cstart ! cstart(cs, ds, mds, parmoff, parmlen) add esp, 5*4! Reload gdtr, idtr and the segment registers to global descriptor table set! up by prot_init(). lgdt (_gdt+GDT_SELECTOR) lidt (_gdt+IDT_SELECTOR) jmpf CS_SELECTOR:csinitcsinit: o16 mov ax, DS_SELECTOR mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax o16 mov ax, TSS_SELECTOR ! no other TSS is used ltr ax push 0 ! set flags to known good state popf ! esp, clear nested task and int enable jmp _main ! main()!*===========================================================================*!* interrupt handlers *!* interrupt handlers for 386 32-bit protected mode *!*===========================================================================*!*===========================================================================*!* hwint00 - 07 *!*===========================================================================*! Note this is a macro, it just looks like a subroutine.#define hwint_master(irq) \ call save /* save interrupted process state */;\ push (_irq_handlers+4*irq) /* irq_handlers[irq] */;\ call _intr_handle /* intr_handle(irq_handlers[irq]) */;\ pop ecx ;\ cmp (_irq_actids+4*irq), 0 /* interrupt still active? */;\ jz 0f ;\ inb INT_CTLMASK /* get current mask */ ;\ orb al, [1<<irq] /* mask irq */ ;\ outb INT_CTLMASK /* disable the irq */;\0: movb al, END_OF_INT ;\ outb INT_CTL /* reenable master 8259 */;\ ret /* restart (another) process */! Each of these entry points is an expansion of the hwint_master macro .align 16_hwint00: ! Interrupt routine for irq 0 (the clock). hwint_master(0) .align 16_hwint01: ! Interrupt routine for irq 1 (keyboard) hwint_master(1) .align 16_hwint02: ! Interrupt routine for irq 2 (cascade!) hwint_master(2) .align 16_hwint03: ! Interrupt routine for irq 3 (second serial) hwint_master(3) .align 16_hwint04: ! Interrupt routine for irq 4 (first serial) hwint_master(4) .align 16_hwint05: ! Interrupt routine for irq 5 (XT winchester) hwint_master(5) .align 16_hwint06: ! Interrupt routine for irq 6 (floppy) hwint_master(6) .align 16_hwint07: ! Interrupt routine for irq 7 (printer) hwint_master(7)!*===========================================================================*!* hwint08 - 15 *!*===========================================================================*! Note this is a macro, it just looks like a subroutine.#define hwint_slave(irq) \ call save /* save interrupted process state */;\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -