📄 vectors.s
字号:
##=============================================================================
##
## vectors.S
##
## x86 exception vectors
##
##=============================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
##=============================================================================
#######DESCRIPTIONBEGIN####
##
## Author(s): jskov
## Contributors:jskov
## Date: 1999-01-07
## Purpose: x86 exception vectors
## Description: This file defines the code placed into the exception
## vectors. It also contains the first level default VSRs
## that save and restore state for both exceptions and
## interrupts.
##
######DESCRIPTIONEND####
##
##=============================================================================
#include <pkgconf/system.h>
#include <pkgconf/hal.h>
#include CYGBLD_HAL_PLATFORM_H
#ifdef CYGPKG_KERNEL
#include <pkgconf/kernel.h>
#endif /* CYGPKG_KERNEL */
#include <cyg/hal/arch.inc>
#==============================================================================
// .file "vectors.S"
#==============================================================================
# Real startup code. We jump here from the various reset vectors to set up the
# world.
.text
.globl _start
_start:
hal_cpu_init
hal_smp_init
hal_diag_init
hal_mmu_init
hal_memc_init
hal_intc_init
hal_cache_init
hal_timer_init
# Loading the stack pointer seems appropriate now.
# In SMP systems, this may not be the interrupt stack we
# actually need to use for this CPU. We fix that up later.
movl $__interrupt_stack, %esp
#if defined(CYG_HAL_STARTUP_FLOPPY) \
|| defined(CYG_HAL_STARTUP_ROM) \
|| defined(CYG_HAL_STARTUP_GRUB)
# If we are here first, initialize the IDT. RAM startup
# configurations can assume that Redboot has already set
# the IDT up.
hal_idt_init
#endif
hal_mon_init
# Init FPU
# Do this after the monitor init so that we can plant our
# own FPU unavailable VSR.
hal_fpu_init # WARNING: may adjust stack pointer
# Zero the BSS. If the BSS is not a whole number of words
# long we will write up to 3 extra bytes at the end.
# (This should not be a problem usually).
movl $__bss_end,%ecx # ECX = end of BSS
movl $__bss_start,%edi # EDI = base of BSS
subl %edi,%ecx # ECX = size of BSS
addl $3,%ecx # ECX += sizeof(long)-1
shrl $2,%ecx # ECX >>= 2 = number of words to fill
xorl %eax,%eax # EAX = 0 = fill value
rep stosl # Fill it in
#ifdef CYG_HAL_STARTUP_ROM
# In a ROM booted system, we also need to copy the data section
# out to the RAM.
movl $__rom_data_start,%esi # ESI = base of ROM data area
movl $__ram_data_start,%edi # EDI = base of RAM data area
movl $__ram_data_end,%ecx # ECX = end of data
subl %edi,%ecx # ECX = size of data in bytes
shrl $2,%ecx # ECX >>= 2 = number of words to copy
rep movsl # Copy it over
#endif
.extern hal_variant_init
call hal_variant_init
.extern hal_platform_init
call hal_platform_init
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
// This is here so we can debug the constructors.
.extern initialize_stub
call initialize_stub
#endif
.extern cyg_hal_invoke_constructors
call cyg_hal_invoke_constructors
#ifdef CYGPKG_HAL_SMP_SUPPORT
# Now move SP to actual interrupt stack we will use for this
# processor.
hal_init_istack %esp
#ifndef CYG_HAL_STARTUP_RAM
# Only start other CPUs when we are the original boot executable.
# RAM executables are loaded via RedBoot, so only FLOPPY, GRUB
# and ROM startups count here.
.extern cyg_hal_smp_cpu_start_all
call cyg_hal_smp_cpu_start_all
#endif
#endif
#ifdef CYGDBG_HAL_DEBUG_GDB_INITIAL_BREAK
.extern breakpoint
call breakpoint
#endif
.extern cyg_start
call cyg_start
# Hmm. Not expecting to return from cyg_start.
1: hlt
jmp 1b
##-----------------------------------------------------------------------------
## SMP entry point
#if defined(CYGPKG_HAL_SMP_SUPPORT)
.extern cyg_hal_smp_startup
.global cyg_hal_smp_start
cyg_hal_smp_start:
# Finalize CPU init?
# Interrupts?
# hal_cpu_init
# hal_intc_init
hal_init_istack %esp
# Init flags register
pushl $0
popfl
hal_fpu_cpu_init
call cyg_hal_smp_startup
1:
jmp 1b
#ifdef CYG_HAL_STARTUP_RAM
.align 4, 0xFF
gdtStart:
/* Selector 0x00 == invalid. */
.word 0x0000
.word 0x0000
.byte 0x00
.byte 0x00
.byte 0x00
.byte 0x00
/* Selector 0x08 == code. */
.word 0xFFFF
.word 0x0000
.byte 0x00
.byte 0x9B
.byte 0xCF
.byte 0x00
/* Selector 0x10 == data. */
.word 0xFFFF
.word 0x0000
.byte 0x00
.byte 0x93
.byte 0xCF
.byte 0x00
/* Selector 0x18 == shorter code: faults any code
* access 0xF0000000-0xFFFFFFFF.
*/
.word 0xFFFF
.word 0x0000
.byte 0x00
.byte 0x9B
.byte 0xC7
.byte 0x00
/* Selector 0x20 == data; faults any access 0xF0000000-0xFFFFFFFF. */
.word 0xFFFF
.word 0x0000
.byte 0x00
.byte 0x93
.byte 0xC7
.byte 0x00
.align 4, 0xFF
gdtEnd:
#endif // CYG_HAL_STARTUP_RAM
##-----------------------------------------------------------------------------
## Slave processor startup code
## This code is copied into low RAM, at 0x2000 and is the destination of the
## startup interrupt that is sent to get the slaves running.
.data
.code16
.global cyg_hal_slave_trampoline
.global cyg_hal_slave_trampoline_end
cyg_hal_slave_trampoline:
slave_base = .
cld /* always count up. */
cli /* disable interrupts */
# Load up selector registers
# Set DS == CS
movw %cs,%ax
movw %ax,%ds
# load GDTR
lgdt slave_gdt - slave_base
lidt slave_idt - slave_base
/* Switch to protected mode. */
movl %cr0,%eax
orb $1, %al
movl %eax,%cr0
ljmp $8, $3f-slave_base+0x2000
hlt
.align 4, 0xFF
slave_gdt:
.word gdtEnd - gdtStart
# .word 39
.long gdtStart
.align 4, 0xFF
slave_idt:
.extern idtStart
.word 0x07FF # space for 256 entries
.long idtStart
.code32
3:
# Load up selector registers
movw $0x10, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
# Go to real HAL entry point
movl $cyg_hal_smp_start,%eax
jmp *%eax
cyg_hal_slave_trampoline_end:
.text
#endif // defined(CYGPKG_HAL_SMP_SUPPORT)
#==============================================================================
# Default exception VSR
.align 4, 0xCC
.globl __default_exception_vsr
__default_exception_vsr:
## We enter here with the CPU state still in the registers and:
## 12(%esp) EFLAGS pushed by hardware
## 8(%esp) CS pushed by hardware
## 4(%esp) PC pushed by hardware
## 0(%esp) vector number pushed by trampoline
pusha # save all registers
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
mov %esp,%ebp # save SP
cmpl $__stub_stack_base,%esp # compare SP with stub stack base
jb 1f # if sp < istack base, switch
cmpl $__stub_stack,%esp # compare SP with stub stack top
jbe 2f # if sp < stack top, dont switch
1:
movl $__stub_stack,%esp # move to stub stack
## We switched stacks with previous ESP in EBP
## 44(%ebp) EFLAGS pushed by hardware
## 40(%ebp) CS pushed by hardware
## 36(%ebp) PC pushed by hardware
## 32(%ebp) vector number pushed by trampoline
## 28(%ebp) EAX
## 24(%ebp) ECX
## 20(%ebp) EDX
## 16(%ebp) EBX
## 12(%ebp) (ESP - 16)
## 8(%ebp) EBP
## 4(%ebp) ESI
## 0(%ebp) EDI
pushl 44(%ebp) # copy EFLAGS from original stack
pushl 40(%ebp) # copy CS
pushl 36(%ebp) # copy PC
pushl 32(%ebp) # copy vector number
pusha
movl 8(%ebp),%eax # copy EBP
movl %eax,8(%esp)
movl 12(%ebp),%eax # copy ESP
movl %eax,12(%esp)
2:
#endif
hal_fpu_push_exc # save FPU state
mov %esp,%edi # save state pointer in EDI
# adjust ESP by 16 for the state stored before the pusha
add $16,i386reg_esp(%edi)
#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) && defined(CYGPKG_HAL_SMP_SUPPORT)
.extern cyg_hal_smp_cpu_sync
.extern cyg_hal_smp_cpu_sync_flag
.extern cyg_hal_smp_vsr_sync_flag
# An SMP ROM monitor needs to suspend all other CPUs when
# taking an exception.
1:
lock btsl $0,cyg_hal_smp_vsr_sync_flag # test serialization bit
jnc 9f # if it was zero we are first here
# Some other CPU is already handling an exception. We need to spin until
# released.
hal_smp_cpu %eax # get CPU index
movl $cyg_hal_smp_cpu_sync,%ebx
movl $cyg_hal_smp_cpu_sync_flag,%ecx
lock incl 0(%ecx,%eax,4) # inc cpu sync flag
2:
cmpl $0,0(%ebx,%eax,4) # test sync location
je 2b # loop while value is zero
lock decl 0(%ecx,%eax,4) # dec cpu sync flag
# Jump to return from this VSR. If the exception was genuine,
# we will re-execute the cause and come back here. If it was
# just a duplicate, or a halt NMI, we will continue as if
# nothing had happened.
jmp __default_exception_vsr_return
9:
# Stop all other CPUs
.extern cyg_hal_smp_halt_other_cpus
call cyg_hal_smp_halt_other_cpus
#endif
hal_fpu_push_exc_annex
# Call exception handler
.extern cyg_hal_exception_handler
pushl %edi # arg1 = saved state
call cyg_hal_exception_handler
addl $4,%esp # pop arg
hal_fpu_pop_exc_annex
#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) && defined(CYGPKG_HAL_SMP_SUPPORT)
.extern cyg_hal_smp_release_other_cpus
call cyg_hal_smp_release_other_cpus
lock btrl $0,cyg_hal_smp_vsr_sync_flag # clear serialization bit
__default_exception_vsr_return:
#endif
hal_fpu_pop_exc # restore FPU state
## At this point, the stack contains:
## 44(%esp) EFLAGS pushed by hardware
## 40(%esp) CS pushed by hardware
## 36(%esp) PC pushed by hardware
## 32(%esp) vector number pushed by trampoline
## 28(%esp) EAX
## 24(%esp) ECX
## 20(%esp) EDX
## 16(%esp) EBX
## 12(%esp) ESP
## 8(%esp) EBP
## 4(%esp) ESI
## 0(%esp) EDI
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
movl 12(%esp),%ebp # pre-exception ESP
sub $48,%ebp # adjust for current stack frame
cmpl %esp,%ebp
je 1f
## need to switch stacks
xchg %esp,%ebp
add $48,%esp
pushl 44(%ebp) # EFLAGS
pushl 40(%ebp) # CS
pushl 36(%ebp) # PC
mov %ebp,%esp
popa
movl -20(%esp),%esp # popa does not restore %esp
sub $12,%esp # adjust for EFLAGS, CS, and PC
iret
1:
#endif
popa # restore all our registers.
addl $4, %esp # skip the vector number
# Note: we do not need to re-adjust ESP
# back by 16 as popa does not pop ESP.
iret # and return to the program.
#==============================================================================
# Default interrupt VSR
#
#
.extern __interrupt_stack
.align 4, 0xCC
.globl __default_interrupt_vsr
__default_interrupt_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -