Linux中断导读之一--初始化<2>

代码在init/main.c-start_kernel/setup_arch(&command_line);

early_trap_init

调用arch/arm/kernel/traps.c中

void __init early_trap_init(void)
{
#if defined(CONFIG_CPU_USE_DOMAINS)
    unsigned long vectors = CONFIG_VECTORS_BASE;         //可以配置trap基地址
#else
    unsigned long vectors = (unsigned long)vectors_page;
#endif
    extern char __stubs_start[], __stubs_end[];
    extern char __vectors_start[], __vectors_end[];
    extern char __kuser_helper_start[], __kuser_helper_end[];
    int kuser_sz = __kuser_helper_end - __kuser_helper_start;

    /*
     * Copy the vectors, stubs and kuser helpers (in entry-armv.S)
     * into the vector page, mapped at 0xffff0000, and ensure these
     * are visible to the instruction stream.
     */

        //将entry-armv.s对应部分copy到该地址,
    memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
    memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
    memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);

    /*
     * Do processor specific fixups for the kuser helpers
     */
    kuser_get_tls_init(vectors);

    /*
     * Copy signal return handlers into the vector page, and
     * set sigreturn to be a pointer to these.
     */
    memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
           sigreturn_codes, sizeof(sigreturn_codes));
    memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
           syscall_restart_code, sizeof(syscall_restart_code));

    flush_icache_range(vectors, vectors + PAGE_SIZE);
    modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
}

#在arch/arm/kernel/entry-armv.s中
__vectors_start:
 ARM(    swi    SYS_ERROR0    )
 THUMB(    svc    #0        )
 THUMB(    nop            )                        //复位
    W(b)    vector_und + stubs_offset       //未定义模式
    W(ldr)    pc, .LCvswi + stubs_offset   //swi,系统调用进入
    W(b)    vector_pabt + stubs_offset       //指令预取
    W(b)    vector_dabt + stubs_offset       //data
    W(b)    vector_addrexcptn + stubs_offset //reserve
    W(b)    vector_irq + stubs_offset       //irq
    W(b)    vector_fiq + stubs_offset       //fiq,没有用到

    .globl    __vectors_end
__vectors_end:

.equ    stubs_offset, __vectors_start + 0x200 - __stubs_start

#先看宏:
/*
 * Vector stubs.
 *
 * This code is copied to 0xffff0200 so we can use branches in the
 * vectors, rather than ldr's.  Note that this code must not
 * exceed 0x300 bytes.
 *
 * Common stub entry macro:
 *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
 *
 * SP points to a minimal amount of processor-private memory, the address
 * of which is copied into r0 for the mode specific abort handler.
 */
    .macro    vector_stub, name, mode, correction=0
    .align    5

vector_\name:
    .if \correction
    sub    lr, lr, #\correction
    .endif

    @
    @ Save r0, lr_<exception> (parent PC) and spsr_<exception>
    @ (parent CPSR)
    @
    stmia    sp, {r0, lr}        @ save r0, lr
    mrs    lr, spsr
    str    lr, [sp, #8]        @ save spsr

    @
    @ Prepare for SVC32 mode.  IRQs remain disabled.
    @
    mrs    r0, cpsr
    eor    r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
    msr    spsr_cxsf, r0

    @
    @ the branch table must immediately follow this code
    @
    and    lr, lr, #0x0f
 THUMB(    adr    r0, 1f            )
 THUMB(    ldr    lr, [r0, lr, lsl #2]    )
    mov    r0, sp
 ARM(    ldr    lr, [pc, lr, lsl #2]    )
    movs    pc, lr            @ branch to handler in SVC mode

相关推荐