📄 msx686.s
字号:
test (esp), RING0 ;\ je 1f /* if ring0 */;\ call [handler] /* call interrupt handler */;\ add esp, 4*2 /* pop used C arguments */;\ 2: cli /* disable interrupts */;\ cmpb (_runrun), 0 ;\ je 2f ;\ sti /* unlock */;\ call _swtch ;\ jmp 2b ;\ 2: pop gs /* return to user mode */;\ pop fs ;\ pop es ;\ pop ds ;\ popad ;\ add esp, 4*2 /* pop padding space */;\ inb INT2_CTLMASK ;\ andb al, ~[1<<[irq-8]] ;\ outb INT2_CTLMASK /* enable irq */;\ iretd ;\ 1: call [handler] /* call interrupt handler */;\ add esp, 4*2 /* pop used C arguemts */;\ cli /* disable interrupts */;\ pop gs /* return to kernel mode */;\ pop fs ;\ pop es ;\ pop ds ;\ popad ;\ add esp, 4*2 /* pop padding space */;\ inb INT2_CTLMASK ;\ andb al, ~[1<<[irq-8]] ;\ outb INT2_CTLMASK /* enable irq */;\ iretd ;\! Each of tese entry points is an expansion of the hwint_master macro .align 16_hwint08: hwint_slave(8, _nohandler) .align 16_hwint09: hwint_slave(9, _nohandler) .align 16_hwint10: hwint_slave(10, _nohandler) .align 16_hwint11: hwint_slave(11, _nohandler) .align 16_hwint12: hwint_slave(12, _nohandler) .align 16_hwint13: hwint_slave(13, _nohandler) .align 16_hwint14: hwint_slave(14, _nohandler) .align 16_hwint15: hwint_slave(15, _nohandler)!*===========================================================================*!* exception handlers *!*===========================================================================*! If an exception vector doesn't have an error code to be pushed by processor, ! we would like to fill this space with a padding value, so that we can use one! routine to handle them all. See src/type.h for the layout of the stackframe_divide_error: push 0 ! padding for error code push DIVIDE_VECTOR jmp trap_single_step_exception: push 0 ! padding for error code push DEBUG_VECTOR jmp trap_nmi: push 0 ! padding for error code push NMI_VECTOR jmp trap_breakpoint_exception: push 0 ! padding for error code push BREAKPOINT_VECTOR jmp trap_overflow: push 0 ! padding for error code push OVERFLOW_VECTOR jmp trap_bounds_check: push 0 ! padding for error code push BOUNDS_VECTOR jmp trap_inval_opcode: push 0 ! padding for error code push INVAL_OP_VECTOR jmp trap_copr_not_available: push 0 ! padding for error code push COPROC_NOT_VECTOR jmp trap_double_fault: push DOUBLE_FAULT_VECTOR jmp trap_copr_seg_overrun: push 0 ! padding for error code push COPROC_SEG_VECTOR jmp trap_inval_tss: push INVAL_TSS_VECTOR jmp trap_segment_not_present: push SEG_NOT_VECTOR jmp trap_stack_exception: push STACK_FAULT_VECTOR jmp trap_general_protection: push PROTECTION_VECTOR jmp trap_page_fault: push PAGE_FAULT_VECTOR jmp trap_copr_error: push 0 ! padding for error code push COPROC_ERR_VECTOR jmp trap!*===========================================================================*!* system call *!*===========================================================================*! It shares the same interface with exception_s_call: push 0 push SYS386_VECTOR jmp trap!*===========================================================================*!* trap *!*===========================================================================*! Called from all exceptions, no matter it has pushed an error code or not.! Remember to pop the error code from stack before execute iretd instruction! because iretd won't pop it. .align 16trap: cld ! set direction flag to a know value pushad ! save general registers push ds ! save ds push es ! save es push fs ! save fs push gs ! save gs o16 mov ax, KERNEL_VDATA_SELECTOR mov ds, ax ! we don't touch ss, becasue it was mov es, ax ! already setup by kernel TSS if the mov fs, ax ! previous mode is user. If the previous mov gs, ax ! mode is kernel, reload is trivial. mov eax,esp ! use eax as a base pointer. push esp ! esp points to common stack frame push 60(eax) ! get cs pushed. sti ! allow interrupts test (esp), RING0 je 1f ! if ring0 call _trap ! C verion trap routine add esp, 4*2 ! pop used C arguments 2: cli ! disable interrupts cmpb (_runrun), 0 je 2f sti ! unlock call _swtch jmp 2b 2: pop gs ! return to user mode pop fs pop es pop ds popad add esp, 4*2 ! pop padding space iretd 1: call _trap ! C verion trap routine add esp, 4*2 ! pop used C arguemts cli ! disable interrupts pop gs ! return to kernel mode pop fs pop es pop ds popad add esp, 4*2 ! pop padding space iretd!*===========================================================================*!* savu *!*===========================================================================*! PUBLIC void savu(reg_t *kenv);! Save the kernel mode environment into user PPDA, it is highly cooperated! with retu to switch the kernel process. .align 16_savu: cli ! atomic operating, interrupt is not allowed pop eax ! get return address mov edx, (esp) ! fetch the retiring process u_kenv pointer mov (edx), esp ! get esp saved add edx, 4 mov (edx), ebp ! get ebp saved add edx, 4 mov (edx), ebx ! get ebx saved add edx, 4 mov (edx), esi ! get esi saved add edx, 4 mov (edx), edi ! get edi saved add edx, 4 pushf pop ecx mov (edx), ecx ! get eflags saved sti ! unlock jmp (eax) ! go back !*===========================================================================*!* retu *!*===========================================================================*! PUBLIC void retu(phys_bytes usr_pagetab);! Restore the kernel mode environment from user PPDA, it is highly cooperated! with savu to switch the kernel process .align 16_retu: cli ! atomic operating, interrupt is not allowed pop eax ! get return address mov edx, (esp) ! fetch the arising process page table pointer mov eax, (edx) mov cr3, eax ! restore arising process page table mov edx, (_usr_ppda_ptr) add edx, 12 ! get the arising process u_kenv pointer mov esp, (edx) ! restore esp add edx, 4 mov ebp, (edx) ! restore ebp add edx, 4 mov ebx, (edx) ! restore ebx add edx, 4 mov esi, (edx) ! restore esi add edx, 4 mov edi, (edx) ! restore edi add edx, 4 mov ecx, (edx) push ecx popf ! restore eflags sti ! unlock jmp (eax) ! go back!*===========================================================================*!* aretu *!*===========================================================================*! PUBLIC void aretu();! Used to performance the local goto. Mainly used to abort system call. .align 16_aretu: cli ! atomic operating, interrupt is not allowed pop eax ! get return address mov edx, (esp) ! fetch the retiring process u_qenv pointer mov esp, (edx) ! restore esp add edx, 4 mov ebp, (edx) ! restore ebp add edx, 4 mov ebx, (edx) ! restore ebx add edx, 4 mov esi, (edx) ! restore esi add edx, 4 mov edi, (edx) ! restore edi add edx, 4 mov ecx, (edx) push ecx popf ! restore eflags sti ! unlock jmp (eax) ! go back!*===========================================================================*!* idle *!*===========================================================================*! PUBLIC void idle();! Used to consume the processor idle time if there's no process runnable, only! the hardware interrupt can make it back. .align 16_idle: sti ! To allow peripheral interrupt hlt ret!*===========================================================================*!* gohome *!*===========================================================================*! PUBLIC void gohome();! Called only by swtch() to return to arising process environment, it prevents! the esi, edi registers from being restored again blindly. The ACK compiler! use these registers as local register variables, it restore these registers! before discarding the local stack variables. eax can be used to hold the ! return value from subroutine, the value returned here has many subtle! implications. See the newproc comments. .align 16_gohome: mov eax, 1 leave ret