📄 mpx386.s
字号:
!*===========================================================================*
! Note this is a macro, it looks like a subroutine.
#define hwint_slave(irq) \
call save /* save interrupted process state */;\
inb INT2_CTLMASK ;\
orb al, [1<<[irq-8]] ;\
outb INT2_CTLMASK /* disable the irq */;\
movb al, ENABLE ;\
outb INT_CTL /* reenable master 8259 */;\
jmp .+2 /* delay */;\
outb INT2_CTL /* reenable slave 8259 */;\
sti /* enable interrupts */;\
push irq /* irq */;\
call (_irq_table + 4*irq) /* eax = (*irq_table[irq])(irq) */;\
pop ecx ;\
cli /* disable interrupts */;\
test eax, eax /* need to reenable irq? */;\
jz 0f ;\
inb INT2_CTLMASK ;\
andb al, ~[1<<[irq-8]] ;\
outb INT2_CTLMASK /* enable the irq */;\
0: ret /* restart (another) process */
! Each of these entry points is an expansion of the hwint_slave macro
.align 16
_hwint08: ! Interrupt routine for irq 8 (realtime clock)
hwint_slave(8)
.align 16
_hwint09: ! Interrupt routine for irq 9 (irq 2 redirected)
hwint_slave(9)
.align 16
_hwint10: ! Interrupt routine for irq 10
hwint_slave(10)
.align 16
_hwint11: ! Interrupt routine for irq 11
hwint_slave(11)
.align 16
_hwint12: ! Interrupt routine for irq 12
hwint_slave(12)
.align 16
_hwint13: ! Interrupt routine for irq 13 (FPU exception)
hwint_slave(13)
.align 16
_hwint14: ! Interrupt routine for irq 14 (AT winchester)
hwint_slave(14)
.align 16
_hwint15: ! Interrupt routine for irq 15
hwint_slave(15)
!*===========================================================================*
!* save *
!*===========================================================================*
! Save for protected mode.
! This is much simpler than for 8086 mode, because the stack already points
! into the process table, or has already been switched to the kernel stack.
.align 16
save:
cld ! set direction flag to a known value
pushad ! save "general" registers
o16 push ds ! save ds
o16 push es ! save es
o16 push fs ! save fs
o16 push gs ! save gs
mov dx, ss ! ss is kernel data segment
mov ds, dx ! load rest of kernel segments
mov es, dx ! kernel does not use fs, gs
mov eax, esp ! prepare to return
incb (_k_reenter) ! from -1 if not reentering
jnz set_restart1 ! stack is already kernel stack
mov esp, k_stktop
push _restart ! build return address for int handler
xor ebp, ebp ! for stacktrace
jmp RETADR-P_STACKBASE(eax)
.align 4
set_restart1:
push restart1
jmp RETADR-P_STACKBASE(eax)
!*===========================================================================*
!* _s_call *
!*===========================================================================*
.align 16
_s_call:
_p_s_call:
cld ! set direction flag to a known value
sub esp, 6*4 ! skip RETADR, eax, ecx, edx, ebx, est
push ebp ! stack already points into proc table
push esi
push edi
o16 push ds
o16 push es
o16 push fs
o16 push gs
mov dx, ss
mov ds, dx
mov es, dx
incb (_k_reenter)
mov esi, esp ! assumes P_STACKBASE == 0
mov esp, k_stktop
xor ebp, ebp ! for stacktrace
! end of inline save
sti ! allow SWITCHER to be interrupted
! now set up parameters for sys_call()
push ebx ! pointer to user message
push eax ! src/dest
push ecx ! SEND/RECEIVE/BOTH
call _sys_call ! sys_call(function, src_dest, m_ptr)
! caller is now explicitly in proc_ptr
mov AXREG(esi), eax ! sys_call MUST PRESERVE si
cli ! disable interrupts
! Fall into code to restart proc/task running.
!*===========================================================================*
!* restart *
!*===========================================================================*
_restart:
! Flush any held-up interrupts.
! This reenables interrupts, so the current interrupt handler may reenter.
! This does not matter, because the current handler is about to exit and no
! other handlers can reenter since flushing is only done when k_reenter == 0.
cmp (_held_head), 0 ! do fast test to usually avoid function call
jz over_call_unhold
call _unhold ! this is rare so overhead acceptable
over_call_unhold:
mov esp, (_proc_ptr) ! will assume P_STACKBASE == 0
lldt P_LDT_SEL(esp) ! enable segment descriptors for task
lea eax, P_STACKTOP(esp) ! arrange for next interrupt
mov (_tss+TSS3_S_SP0), eax ! to save state in process table
restart1:
decb (_k_reenter)
o16 pop gs
o16 pop fs
o16 pop es
o16 pop ds
popad
add esp, 4 ! skip return adr
iretd ! continue process
!*===========================================================================*
!* exception handlers *
!*===========================================================================*
_divide_error:
push DIVIDE_VECTOR
jmp exception
_single_step_exception:
push DEBUG_VECTOR
jmp exception
_nmi:
push NMI_VECTOR
jmp exception
_breakpoint_exception:
push BREAKPOINT_VECTOR
jmp exception
_overflow:
push OVERFLOW_VECTOR
jmp exception
_bounds_check:
push BOUNDS_VECTOR
jmp exception
_inval_opcode:
push INVAL_OP_VECTOR
jmp exception
_copr_not_available:
push COPROC_NOT_VECTOR
jmp exception
_double_fault:
push DOUBLE_FAULT_VECTOR
jmp errexception
_copr_seg_overrun:
push COPROC_SEG_VECTOR
jmp exception
_inval_tss:
push INVAL_TSS_VECTOR
jmp errexception
_segment_not_present:
push SEG_NOT_VECTOR
jmp errexception
_stack_exception:
push STACK_FAULT_VECTOR
jmp errexception
_general_protection:
push PROTECTION_VECTOR
jmp errexception
_page_fault:
push PAGE_FAULT_VECTOR
jmp errexception
_copr_error:
push COPROC_ERR_VECTOR
jmp exception
!*===========================================================================*
!* exception *
!*===========================================================================*
! This is called for all exceptions which do not push an error code.
.align 16
exception:
sseg mov (trap_errno), 0 ! clear trap_errno
sseg pop (ex_number)
jmp exception1
!*===========================================================================*
!* errexception *
!*===========================================================================*
! This is called for all exceptions which push an error code.
.align 16
errexception:
sseg pop (ex_number)
sseg pop (trap_errno)
exception1: ! Common for all exceptions.
push eax ! eax is scratch register
mov eax, 0+4(esp) ! old eip
sseg mov (old_eip), eax
movzx eax, 4+4(esp) ! old cs
sseg mov (old_cs), eax
mov eax, 8+4(esp) ! old eflags
sseg mov (old_eflags), eax
pop eax
call save
push (old_eflags)
push (old_cs)
push (old_eip)
push (trap_errno)
push (ex_number)
call _exception ! (ex_number, trap_errno, old_eip,
! old_cs, old_eflags)
add esp, 5*4
cli
ret
!*===========================================================================*
!* level0_call *
!*===========================================================================*
_level0_call:
call save
jmp (_level0_func)
!*===========================================================================*
!* idle_task *
!*===========================================================================*
_idle_task: ! executed when there is no work
jmp _idle_task ! a "hlt" before this fails in protected mode
!*===========================================================================*
!* data *
!*===========================================================================*
! These declarations assure that storage will be allocated at the very
! beginning of the kernel data section, so the boot monitor can be easily
! told how to patch these locations. Note that the magic number is put
! here by the compiler, but will be read by, and then overwritten by,
! the boot monitor. When the kernel starts the sizes array will be
! found here, as if it had been initialized by the compiler.
.sect .rom ! Before the string table please
_sizes: ! sizes of kernel, mm, fs filled in by boot
.data2 0x526F ! this must be the first data entry (magic #)
.space 16*2*2-2 ! monitor uses previous word and this space
! extra space allows for additional servers
.sect .bss
k_stack:
.space K_STACK_BYTES ! kernel stack
k_stktop: ! top of kernel stack
.comm ex_number, 4
.comm trap_errno, 4
.comm old_eip, 4
.comm old_cs, 4
.comm old_eflags, 4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -