📄 vectors.s
字号:
pusha # save registers hal_fpu_push_int # save FPU state#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) || \ defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) # Save the context just to be able to set a breakpoint # when we have a CTRL-C .extern hal_saved_interrupt_state movl %esp,hal_saved_interrupt_state#endif#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ !defined(CYGPKG_HAL_SMP_SUPPORT) # Increment scheduler lock .extern cyg_scheduler_sched_lock incl cyg_scheduler_sched_lock#endif movl %esp,%ebp # EBP = copy of ESP # adjust ESP by 16 for the state stored before the pusha add $16,i386reg_esp(%esp) hal_to_intstack hal_fpu_push_int_annex # save extra FPU state #ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING # If we are allowing nested interrupts, restore the flags pushed # by the hardware when this interrupt was taken. movl i386reg_eflags(%ebp), %eax btrl $8,%eax # Clear TF bit pushl %eax popfl#endif#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR) # Call cyg_instrument to record that this interrupt is being raised. movl i386reg_vector(%ebp), %ecx # vector number from saved state movl %ecx,%edi # EDI = copy of vector subl $0x20,%edi # EDI = interrupt table offset pushl %edi # arg3 = interrupt number pushl %ecx # arg2 = vector number pushl $0x0301 # arg1 = type = INTR.RAISE call cyg_instrument # call instrument function add $12,%esp # skip arguments#endif # Call hal_interrupt_handlers[vector](vector, cyg_hal_interrupt_data[vector]) movl i386reg_vector(%ebp), %ecx # vector number from saved state movl %ecx,%edi # EDI = copy of vector subl $0x20,%edi # EDI = interrupt table offset movl $hal_interrupt_handlers, %ebx movl (%ebx, %edi, 4), %edx # EDX = interrupt routine movl $hal_interrupt_data, %ebx movl (%ebx, %edi, 4), %eax # EAX = interrupt data pushl %eax # arg2 = data pushl %ecx # arg1 = vector call *%edx # EAX = return value, needed for interrupt_end() addl $8,%esp # pop args # At this point: # EAX = ISR return code (returned by call) # EDI = ISR table offset (saved across call) # EBP = State pointer (saved across call) hal_fpu_pop_int_annex # Pop any saved interrupt state # If we are returning from the last nested interrupt, move back # to the thread stack. interrupt_end() must be called on the # thread stack since it potentially causes a context switch. hal_from_intstack #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT # Call interrupt_end(r, cyg_hal_interrupt_objects[vector], regs) # - r is the return value from the ISR # - regs points to saved CPU context movl $hal_interrupt_objects, %ebx movl (%ebx, %edi, 4), %edx # EDX = interrupt object ptr pushl %ebp # arg3 = ptr to saved registers pushl %edx # arg2 = object pushl %eax # arg1 = ISR return code call interrupt_end # Call it addl $12, %esp # pop args #endif # Now pull saved state from stack and return to # what thread was originally doing. hal_fpu_pop_int # restore FPU state popa # restore all our registers. addl $4, %esp # skip the vector number. iret # and return to the thread.#==============================================================================## Execute pending DSRs on the interrupt stack with interrupts enabled.## Note: this can only be called from code running on a thread stack so we ## can always just jump to the interrupt stack without looking.#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK .extern cyg_interrupt_call_pending_DSRs .global hal_interrupt_stack_call_pending_DSRs hal_interrupt_stack_call_pending_DSRs: pushl %ebp # save EBP pushfl # save flags movl %esp,%ebp # EBP = saved SP hal_load_istack %edx # load new SP into EDX movl %edx,%esp # move it to ESP sti # Enable interrupts # Call back to kernel to run DSRs call cyg_interrupt_call_pending_DSRs # On return EBP will still contain the old ESP since # it is a callee saved register. movl %ebp,%esp # restore saved SP # Now merge the original IF bit into the current # EFLAGS. popl %eax # EAX = saved flags pushfl # 0(%esp) = current flags btrl $9,0(%esp) # clear IF bit in current flags andl $0x00000200,%eax # isolate saved IF bit orl %eax,0(%esp) # OR it in to the saved flags popfl # restore flags popl %ebp # restore EBP ret # and return #endif #==============================================================================# FPU lazy state switch VSR# This is invoked via hardware exception 7 (FPU unavailable) as a result of# setting the TS bit in CR0 whenever we context switch. If we discover here# that a different context from the current owner of the FPU has attempted# a floating point operation, we save the old context and load the new before # allowing it to proceed. #ifdef CYGHWR_HAL_I386_FPU_SWITCH_LAZY #ifndef CYGPKG_HAL_SMP_CPU_MAX#define CYGPKG_HAL_SMP_CPU_MAX 1#endif .data .global cyg_hal_fpustate_ownercyg_hal_fpustate_owner: .rept CYGPKG_HAL_SMP_CPU_MAX .long 0 # pointer to FPU owning context .endr .global cyg_hal_fpustate_current cyg_hal_fpustate_current: .rept CYGPKG_HAL_SMP_CPU_MAX .long 0 # pointer to current threads FPU context .endr .text __fpu_switch_vsr: ## We enter here with the CPU state still in the registers and: ## 0(%esp) vector number pushed by trampoline ## 4(%esp) PC pushed by hardware ## 8(%esp) CS pushed by hardware ## 12(%esp) EFLAGS pushed by hardware clts # clear CR0:TS bit pusha # save all regs hal_smp_cpu %ecx # ECX = CPU id movl $cyg_hal_fpustate_owner,%eax # EAX = FPU context owner table leal 0(%eax,%ecx,4),%esi # ESI = address of owner pointer movl $cyg_hal_fpustate_current,%ebx # EBX = current threads context table leal 0(%ebx,%ecx,4),%edi # EDI = address of context pointer movl 0(%esi),%eax # EAX = Current FPU context owner movl 0(%edi),%ebx # EBX = Current threads FPU context cmpl %ebx,%eax # current == owner ? je 9f # yes, nothing else to do cmpl $0,%eax # is FPU even in use? je 1f # if not, skip save fnsave i386reg_fpucontext_state(%eax) # save FPU state#ifdef CYGHWR_HAL_I386_PENTIUM_SSE # Save SIMD state. # FIXME. This is awfully inefficient. Need to use FXSAVE to # save FPU and SIMD at same time. FXSAVE requires a 16 byte # alignment and does not have an implicit finit as does FSAVE. stmxcsr i386reg_simd_mxcsr(%eax) movups %xmm0,i386reg_simd_xmm0(%eax) movups %xmm1,i386reg_simd_xmm1(%eax) movups %xmm2,i386reg_simd_xmm2(%eax) movups %xmm3,i386reg_simd_xmm3(%eax) movups %xmm4,i386reg_simd_xmm4(%eax) movups %xmm5,i386reg_simd_xmm5(%eax) movups %xmm6,i386reg_simd_xmm6(%eax) movups %xmm7,i386reg_simd_xmm7(%eax)#endif movl $1,i386reg_fpucontext_valid(%eax) # mark valid1: movl %ebx,0(%esi) # Set new owner btl $0,i386reg_fpucontext_valid(%ebx) # Valid state? jc 2f # If yes, go to restore it finit # Otherwise init FPU#ifdef CYGHWR_HAL_I386_PENTIUM_SSE # FIXME. Anything needed here?#endif jmp 9f # skip restore2: frstor i386reg_fpucontext_state(%ebx) # restore FPU state#ifdef CYGHWR_HAL_I386_PENTIUM_SSE # Restore SIMD state. # FIXME. This is awfully inefficient. Need to use FXRSTOR to # restore FPU and SIMD at same time. FXRSTOR requires a 16 byte # alignment. movups i386reg_simd_xmm0(%ebx),%xmm0 movups i386reg_simd_xmm1(%ebx),%xmm1 movups i386reg_simd_xmm2(%ebx),%xmm2 movups i386reg_simd_xmm3(%ebx),%xmm3 movups i386reg_simd_xmm4(%ebx),%xmm4 movups i386reg_simd_xmm5(%ebx),%xmm5 movups i386reg_simd_xmm6(%ebx),%xmm6 movups i386reg_simd_xmm7(%ebx),%xmm7 ldmxcsr i386reg_simd_mxcsr(%ebx)#endif9: popa # restore all our registers. addl $4, %esp # skip the vector number. iret # and return to the thread. #endif#if 0 #==============================================================================# Assembler swap routines # x = CPU_swap_u16(x) .align 4 .global CPU_swap_u16CPU_swap_u16: xorl %eax, %eax movb 4(%esp), %ah movb 5(%esp), %al ret# x = CPU_swap_u32(x) .align 4 .global CPU_swap_u32CPU_swap_u32: xorl %eax, %eax movb 4(%esp), %ah movb 5(%esp), %al sall $16, %eax movb 6(%esp), %ah movb 7(%esp), %al ret#endif #==============================================================================# Exception trampolines# IDT exception gates point to short code sequences that push the vector# number on to the stack and then indirect via the VSR table to a handler.# # Just for yuks we keep a count of the number of times each # vector is called. .bss .globl hal_vsr_statshal_vsr_stats: .rept 64 // Default VSR table is 64 entries long .long 0 .endr # When an exception which supplies an error code is generated, # we move the code here. hal_trap_error_code: .long 0 .text # macro to create exception handler (no error code) .macro hal_pc_exception_noerr idxhal_pc_exception_\idx: movl $0,hal_trap_error_code pushl $\idx incl (hal_vsr_stats+\idx*4) jmp *(hal_vsr_table+\idx*4) .endm # macro to create exception handler (with error code) .macro hal_pc_exception_err idxhal_pc_exception_\idx: popl hal_trap_error_code pushl $\idx incl (hal_vsr_stats+\idx*4) jmp *(hal_vsr_table+\idx*4) .endm # Now generate all the default exception VSR trampolines. hal_pc_exception_noerr 0 hal_pc_exception_noerr 1 hal_pc_exception_noerr 2 hal_pc_exception_noerr 3 hal_pc_exception_noerr 4 hal_pc_exception_noerr 5 hal_pc_exception_noerr 6 hal_pc_exception_noerr 7 hal_pc_exception_err 8 hal_pc_exception_noerr 9 hal_pc_exception_err 10 hal_pc_exception_err 11 hal_pc_exception_err 12 hal_pc_exception_err 13 hal_pc_exception_err 14 hal_pc_exception_noerr 15 hal_pc_exception_noerr 16 hal_pc_exception_err 17 hal_pc_exception_noerr 18 hal_pc_exception_noerr 19 hal_pc_exception_noerr 20 hal_pc_exception_noerr 21 hal_pc_exception_noerr 22 hal_pc_exception_noerr 23 hal_pc_exception_noerr 24 hal_pc_exception_noerr 25 hal_pc_exception_noerr 26 hal_pc_exception_noerr 27 hal_pc_exception_noerr 28 hal_pc_exception_noerr 29 hal_pc_exception_noerr 30 hal_pc_exception_noerr 31 #==============================================================================# IRQ handler trampolines # macro to create exception handler (no error code) .macro hal_pc_irq_handler idxhal_pc_irq_\idx: pushl $\idx incl (hal_vsr_stats+\idx*4) jmp *(hal_vsr_table+\idx*4) .endm hal_pc_irq_handler 32 hal_pc_irq_handler 33 hal_pc_irq_handler 34 hal_pc_irq_handler 35 hal_pc_irq_handler 36 hal_pc_irq_handler 37 hal_pc_irq_handler 38 hal_pc_irq_handler 39 hal_pc_irq_handler 40 hal_pc_irq_handler 41 hal_pc_irq_handler 42 hal_pc_irq_handler 43 hal_pc_irq_handler 44 hal_pc_irq_handler 45 hal_pc_irq_handler 46 hal_pc_irq_handler 47#ifdef CYGPKG_HAL_SMP_SUPPORT # Extra interrupt vectors for IOAPIc routed PCI and # other interrupt sources hal_pc_irq_handler 48 hal_pc_irq_handler 49 hal_pc_irq_handler 50 hal_pc_irq_handler 51 hal_pc_irq_handler 52 hal_pc_irq_handler 53 hal_pc_irq_handler 54 hal_pc_irq_handler 55 hal_pc_irq_handler 56 hal_pc_irq_handler 57 hal_pc_irq_handler 58 hal_pc_irq_handler 59 hal_pc_irq_handler 60 hal_pc_irq_handler 61 hal_pc_irq_handler 62 hal_pc_irq_handler 63 # Inter-CPU interrupts start at 64 hal_pc_irq_handler 64 hal_pc_irq_handler 65 hal_pc_irq_handler 66 hal_pc_irq_handler 67#endif # default vsr entries: pop the vector code from the stack and return.default_vsr_iret: add $4,%esp iret # GNUPro apps use "int $0x80" for syscalls. # There is no vsr table entry for this. .global __syscall_tramp__syscall_tramp: pushl $0x80 jmp __default_exception_vsr#==============================================================================# Initial and interrupt stack#ifndef CYG_HAL_I386_INTERRUPT_STACK_DEFINED .bss#ifndef CYGPKG_HAL_SMP_SUPPORT .balign 16 .global cyg_interrupt_stack_basecyg_interrupt_stack_base:__interrupt_stack_base: .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE .byte 0 .endr .balign 16 .global cyg_interrupt_stackcyg_interrupt_stack:__interrupt_stack: .long 0,0,0,0,0,0,0,0#else // CYGPKG_HAL_SMP_SUPPORT __interrupt_stack_vector: .rept CYGPKG_HAL_SMP_CPU_MAX .long 0 .endr .balign 16 .global cyg_interrupt_stack_basecyg_interrupt_stack_base:__interrupt_stack_base:__interrupt_stack_first: .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE .byte 0 .endr .global cyg_interrupt_stackcyg_interrupt_stack:__interrupt_stack: .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE*(CYGPKG_HAL_SMP_CPU_MAX-1) .byte 0 .endr #endif // CYGPKG_HAL_SMP_SUPPORT #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS .global __stub_stack_base__stub_stack_base: .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE .byte 0 .endr .balign 16 .global __stub_stack__stub_stack: .long 0,0,0,0,0,0,0,0#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS #endif // CYG_HAL_I386_INTERRUPT_STACK_DEFINED #------------------------------------------------------------------------------# end of vectors.S
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -