From kernel startup entry point to start_kernel (2)

1. The whole process

crash> dis stext
0xc0008000 <stext>:     msr     CPSR_c, #211    ; 0xd3
0xc0008004 <stext+4>:   mrc     15, 0, r9, cr0, cr0, {0}
0xc0008008 <stext+8>:   bl      0xc044c880 <__lookup_processor_type>
0xc000800c <stext+12>:  movs    r10, r5
0xc0008010 <stext+16>:  beq     0xc044c8c4 <__error>
0xc0008014 <stext+20>:  add     r3, pc, #44     ; 0x2c
0xc0008018 <stext+24>:  ldm     r3, {r4, r8}
0xc000801c <stext+28>:  sub     r4, r3, r4
0xc0008020 <stext+32>:  add     r8, r8, r4
0xc0008024 <stext+36>:  bl      0xc0008110 <__vet_atags>
0xc0008028 <stext+40>:  bl      0xc058d000 <__fixup_smp>
0xc000802c <stext+44>:  bl      0xc0008050 <__create_page_tables>

0xc0008030 <stext+48>:  ldr     sp, [pc, #12]   ; 0xc0008044
0xc0008034 <stext+52>:  add     lr, pc, #4
0xc0008038 <stext+56>:  mov     r8, r4
0xc000803c <stext+60>:  add     pc, r10, #16
0xc0008040 <stext+64>:  b       0xc044c854 <__enable_mmu>
    mrc    p15, 0, r9, c0, c0        @ get processor id
    bl    __lookup_processor_type        @ r5=procinfo r9=cpuid


2. __lookup_processor_type

/*
 * Read processor ID register (CP#15, CR0), and look up in the linker-built
 * supported processor list.  Note that we can't use the absolute addresses
 * for the __proc_info lists since we aren't running with the MMU on
 * (and therefore, we are not in the correct address space).  We have to
 * calculate the offset.
 *
 *    r9 = cpuid
 * Returns:
 *    r3, r4, r6 corrupted
 *    r5 = proc_info pointer in physical address space
 *    r9 = cpuid (preserved)
 */
crash> dis __lookup_processor_type
/*此时pc的内容是物理地址,而不是这里显示的标号 0xc044c880【该值是静态编译生成的,不是运行是决定的】
 *而PC时运行时决定的。
 *r3的内容也是物理地址,间接寻址把内容load 到r4,5,6
 *r4的内容是当前地址的虚拟地址, r3是当前地址的物理地址
 */
0xc044c880 <__lookup_processor_type>:   add     r3, pc, #48     ; 0x30
0xc044c884 <__lookup_processor_type+4>: ldm     r3, {r4, r5, r6}
/*mean: r3-r4 not r4-r3
 *convert virt addresses to physical address space
 */
0xc044c888 <__lookup_processor_type+8>: sub     r3, r3, r4
0xc044c88c <__lookup_processor_type+12>:        add     r5, r5, r3
0xc044c890 <__lookup_processor_type+16>:        add     r6, r6, r3
0xc044c894 <__lookup_processor_type+20>:        ldm     r5, {r3, r4}
0xc044c898 <__lookup_processor_type+24>:        and     r4, r4, r9
0xc044c89c <__lookup_processor_type+28>:        teq     r3, r4
0xc044c8a0 <__lookup_processor_type+32>:        beq     0xc044c8b4 <__lookup_processor_type+52>
0xc044c8a4 <__lookup_processor_type+36>:        add     r5, r5, #52     ; 0x34
0xc044c8a8 <__lookup_processor_type+40>:        cmp     r5, r6
0xc044c8ac <__lookup_processor_type+44>:        bcc     0xc044c894 <__lookup_processor_type+20>
0xc044c8b0 <__lookup_processor_type+48>:        mov     r5, #0
0xc044c8b4 <__lookup_processor_type+52>:        mov     pc, lr

/*具体细节不再关注,这个代码的意思是:
 *1】此时是物理地址,而不是这些的虚拟地址,如果寻址此时只能使用PC寻址;
 *2】此函数的输入值r5 = proc_info pointer in physical address space
 *3】此函数的返回值r9 = cpuid
 *4】至于,cpuid和proc_info的对应关系,不再关注。
 */


3. __vet_atags

r2 = atags or dtb pointer.
/* Determine validity of the r2 atags pointer.  The heuristic requires
 * that the pointer be aligned, in the first 16k of physical RAM and
 * that the ATAG_CORE marker is first and present.  If CONFIG_OF_FLATTREE
 * is selected, then it will also accept a dtb pointer.  Future revisions
 * of this function may be more lenient with the physical address and
 * may also be able to move the ATAGS block if necessary.
 *
 * Returns:
 *  r2 either valid atags pointer, valid dtb pointer, or zero
 *  r5, r6 corrupted
 * 该函数只是判断r2的有效性,并没有做其他处理
 */
crash> dis __vet_atags
0xc0008110 <__vet_atags>:       tst     r2, #3
0xc0008114 <__vet_atags+4>:     bne     0xc000813c <__vet_atags+44>
0xc0008118 <__vet_atags+8>:     ldr     r5, [r2]
0xc000811c <__vet_atags+12>:    cmp     r5, #5
0xc0008120 <__vet_atags+16>:    cmpne   r5, #2
0xc0008124 <__vet_atags+20>:    bne     0xc000813c <__vet_atags+44>
0xc0008128 <__vet_atags+24>:    ldr     r5, [r2, #4]
0xc000812c <__vet_atags+28>:    ldr     r6, [pc, #16]   ; 0xc0008144
0xc0008130 <__vet_atags+32>:    cmp     r5, r6
0xc0008134 <__vet_atags+36>:    bne     0xc000813c <__vet_atags+44>
0xc0008138 <__vet_atags+40>:    mov     pc, lr
0xc000813c <__vet_atags+44>:    mov     r2, #0
0xc0008140 <__vet_atags+48>:    mov     pc, lr


4. __fixup_smp

/*
 *what about the __fixup_smp??
 */
__fixup_smp:
    and    r3, r9, #0x000f0000    @ architecture version
    teq    r3, #0x000f0000        @ CPU ID supported?
    bne    __fixup_smp_on_up    @ no, assume UP

    bic    r3, r9, #0x00ff0000
    bic    r3, r3, #0x0000000f    @ mask 0xff00fff0
    mov    r4, #0x41000000
    orr    r4, r4, #0x0000b000
    orr    r4, r4, #0x00000020    @ val 0x4100b020
    teq    r3, r4            @ ARM 11MPCore?
    moveq    pc, lr            @ yes, assume SMP

    mrc    p15, 0, r0, c0, c0, 5    @ read MPIDR
    and    r0, r0, #0xc0000000    @ multiprocessing extensions and
    teq    r0, #0x80000000        @ not part of a uniprocessor system?

    moveq    pc, lr            @ yes, assume SMP

5. __create_page_tables


/*
 * Setup the initial page tables.  We only setup the barest
 * amount which are required to get the kernel running, which
 * generally means mapping in the kernel code.
 *
 * r8 = phys_offset, r9 = cpuid, r10 = procinfo
 *
 * Returns:
 *  r0, r3, r5-r7 corrupted
 *  r4 = physical page table address
 */
crash> dis __create_page_tables
/*
 * make the region of [phys_offset+0x4000, phys_offset+0x4000+0x4000] clean
 * Clear the swapper page table
 */
0xc0008050 <__create_page_tables>:      add     r4, r8, #16384  ; 0x4000
0xc0008054 <__create_page_tables+0x4>:  mov     r0, r4
0xc0008058 <__create_page_tables+0x8>:  mov     r3, #0
0xc000805c <__create_page_tables+0xc>:  add     r6, r0, #16384  ; 0x4000
0xc0008060 <__create_page_tables+0x10>: str     r3, [r0], #4
0xc0008064 <__create_page_tables+0x14>: str     r3, [r0], #4
0xc0008068 <__create_page_tables+0x18>: str     r3, [r0], #4
0xc000806c <__create_page_tables+0x1c>: str     r3, [r0], #4
0xc0008070 <__create_page_tables+0x20>: teq     r0, r6
0xc0008074 <__create_page_tables+0x24>: bne     0xc0008060 <__create_page_tables+16>


5.1 Create identity mapping to cater for __enable_mmu

/* r10 = procinfo, mm_mmuflags
 */
0xc0008078 <__create_page_tables+0x28>: ldr     r7, [r10, #8]

/*
* Create identity mapping to cater for __enable_mmu.
* This identity mapping will be removed by paging_init().
*/
0xc000807c <__create_page_tables+0x2c>: add     r0, pc, #128    ; 0x80
0xc0008080 <__create_page_tables+0x30>: ldm     r0, {r3, r5, r6}
0xc0008084 <__create_page_tables+0x34>: sub     r0, r0, r3
0xc0008088 <__create_page_tables+0x38>: add     r5, r5, r0
0xc000808c <__create_page_tables+0x3c>: add     r6, r6, r0
/*
 *r5,r6寄存器的内容分别是代码__turn_mmu_on的开始,结束地址
 *r5,r6寄存器的内容右移20位:SECTION_SHIFT
 */
0xc0008090 <__create_page_tables+0x40>: lsr     r5, r5, #20
0xc0008094 <__create_page_tables+0x44>: lsr     r6, r6, #20
/*
 *r5右移20位后,再左移20位,然后和procinfo中的mm_mmuflags逻辑或操作

 *把r3的内容存放在位置PHY_OFFSET + address >> 20 << 20 << 2

*物理地址的来源当前PC和相对地址,它的内容的前20位在 pte中;

*怎样得到个表项那?虚拟地址的高12位再左移2位,这14位形成index和18位的基地址,形成表项的虚拟地址

*注意每个表项占2*2=4个字节,每个pte也是用4个字节描述;14形成的index: 2的14次幂就是16K:0x4000

 *#define PG_DIR_SIZE    0x4000
 *#define PMD_ORDER    2
 */
0xc0008098 <__create_page_tables+0x48>: orr     r3, r7, r5, lsl #20
0xc000809c <__create_page_tables+0x4c>: str     r3, [r4, r5, lsl #2]
0xc00080a0 <__create_page_tables+0x50>: cmp     r5, r6
0xc00080a4 <__create_page_tables+0x54>: addcc   r5, r5, #1
0xc00080a8 <__create_page_tables+0x58>: bcc     0xc0008098 <__create_page_tables+72>


5.2 setup the pagetables for our kernel direct mapped region

/*
* Now setup the pagetables for our kernel direct
* mapped region.
*/
0xc00080ac <__create_page_tables+0x5c>: mov     r3, pc
0xc00080b0 <__create_page_tables+0x60>: lsr     r3, r3, #20
0xc00080b4 <__create_page_tables+0x64>: orr     r3, r7, r3, lsl #20
0xc00080b8 <__create_page_tables+0x68>: add     r0, r4, #12288  ; 0x3000
0xc00080bc <__create_page_tables+0x6c>: str     r3, [r0, #0]!
0xc00080c0 <__create_page_tables+0x70>: ldr     r6, [pc, #56]   ; 0xc0008100
0xc00080c4 <__create_page_tables+0x74>: add     r0, r0, #4
0xc00080c8 <__create_page_tables+0x78>: add     r6, r4, r6, lsr #18
0xc00080cc <__create_page_tables+0x7c>: cmp     r0, r6
0xc00080d0 <__create_page_tables+0x80>: add     r3, r3, #1048576        ; 0x100000
0xc00080d4 <__create_page_tables+0x84>: strls   r3, [r0], #4
0xc00080d8 <__create_page_tables+0x88>: bls     0xc00080cc <__create_page_tables+124>


5.3 map boot params address

/*
* Then map boot params address in r2 or the first 1MB (2MB with LPAE)
* of ram if boot params address is not specified.
*/
0xc00080dc <__create_page_tables+0x8c>: lsr     r0, r2, #20
0xc00080e0 <__create_page_tables+0x90>: lsls    r0, r0, #20
0xc00080e4 <__create_page_tables+0x94>: moveq   r0, r8
0xc00080e8 <__create_page_tables+0x98>: sub     r3, r0, r8
0xc00080ec <__create_page_tables+0x9c>: add     r3, r3, #-1073741824    ; 0xc0000000
0xc00080f0 <__create_page_tables+0xa0>: add     r3, r4, r3, lsr #18
0xc00080f4 <__create_page_tables+0xa4>: orr     r6, r7, r0
0xc00080f8 <__create_page_tables+0xa8>: str     r6, [r3]
0xc00080fc <__create_page_tables+0xac>: mov     pc, lr

__turn_mmu_on_loc:
    .long    .
    .long    __turn_mmu_on

    .long    __turn_mmu_on_end

6 __enable_mmu


/*
 * Setup common bits before finally enabling the MMU.  Essentially
 * this is just loading the page table pointer and domain access
 * registers.
 *
 *  r0  = cp#15 control register
 *  r1  = machine ID
 *  r2  = atags or dtb pointer
 *  r4  = page table pointer
 *  r9  = processor ID
 *  r13 = *virtual* address to jump to upon completion
 */
crash> dis __enable_mmu
0xc044c854 <__enable_mmu>:      bic     r0, r0, #2
0xc044c858 <__enable_mmu+0x4>:  mov     r5, #21
/*
 *@ load domain access register, load page table pointer
 */
0xc044c85c <__enable_mmu+0x8>:  mcr     15, 0, r5, cr3, cr0, {0}
0xc044c860 <__enable_mmu+0xc>:  mcr     15, 0, r4, cr2, cr0, {0}

0xc044c864 <__enable_mmu+0x10>: b       0xc0452870 <__turn_mmu_on>


7__turn_mmu_on


/*
 * Enable the MMU.  This completely changes the structure of the visible
 * memory space.  You will not be able to trace execution through this.
 * If you have an enquiry about this, *please* check the linux-arm-kernel
 * mailing list archives BEFORE sending another post to the list.
 *
 *  r0  = cp#15 control register
 *  r1  = machine ID
 *  r2  = atags or dtb pointer
 *  r9  = processor ID
 *  r13 = *virtual* address to jump to upon completion
 *
 * other registers depend on the function called upon completion
 */
crash> dis __turn_mmu_on
0xc0452870 <__idmap_text_start>:        nop                     ; (mov r0, r0)
0xc0452874 <__turn_mmu_on+0x4>: isb     sy
0xc0452878 <__turn_mmu_on+0x8>: mcr     15, 0, r0, cr1, cr0, {0}
0xc045287c <__turn_mmu_on+0xc>: mrc     15, 0, r3, cr0, cr0, {0}
0xc0452880 <__turn_mmu_on+0x10>:        isb     sy
0xc0452884 <__turn_mmu_on+0x14>:        mov     r3, r3
0xc0452888 <__turn_mmu_on+0x18>:        mov     r3, sp

0xc045288c <__turn_mmu_on+0x1c>:        mov     pc, r3


8 __mmap_switched


/*
 * The following fragment of code is executed with the MMU on in MMU mode,
 * and uses absolute addresses; this is not position independent.
 *
 *  r0  = cp#15 control register
 *  r1  = machine ID
 *  r2  = atags/dtb pointer
 *  r9  = processor ID
 */
    __INIT
__mmap_switched:
    adr    r3, __mmap_switched_data

    ldmia    r3!, {r4, r5, r6, r7}
    cmp    r4, r5                @ Copy data segment if needed
1:    cmpne    r5, r6
    ldrne    fp, [r4], #4
    strne    fp, [r5], #4
    bne    1b

    mov    fp, #0                @ Clear BSS (and zero fp)
1:    cmp    r6, r7
    strcc    fp, [r6],#4
    bcc    1b

 ARM(    ldmia    r3, {r4, r5, r6, r7, sp})
    str    r9, [r4]            @ Save processor ID
    str    r1, [r5]            @ Save machine type
    str    r2, [r6]            @ Save atags pointer
    bic    r4, r0, #CR_A            @ Clear 'A' bit
    stmia    r7, {r0, r4}            @ Save control register values
    b    start_kernel



你可能感兴趣的:(kernel)