arm-linux启动过程(2)

来源:互联网 发布:php入门到精通源码 编辑:程序博客网 时间:2024/05/07 23:41

5. 为kernel建立临时页表

前面提及到,kernel里面的所有符号在链接时,都使用了虚拟地址值。在完成基本的初始化后,kernel代码将跳到第一个C语言函数start_kernl来执行,在哪个时候,这些虚拟地址必须能够对它所存放在真正内存位置,否则运行将为出错。为此,CPU必须开启MMU,但在开启MMU前,必须为虚拟地址到物理地址的映射建立相应的面表。在开启MMU后,kernel指并不马上将PC值指向start_kernl,而是要做一些C语言运行期的设置,如堆栈,重定义等工作后才跳到start_kernel去执行。在此过程中,PC值还是物理地址,因此还需要为这段内存空间建立va=pa的内存映射关系。当然,本函数建立的所有页表都会在将来paging_init销毁再重建,这是临时过度性的映射关系和页表。

 

在介绍__create_table_pages前,先认识一个macropgtbl,它将KERNL_RAM_PADDR –0x4000的值赋给rd寄存器,从下面的使用中可以看它,该值是页表在物理内存的基础,也即页表放在kernel开始地址下的16K的地方。

[cpp] viewplaincopyprint?
  1.    
  2.   
  3. .macro    pgtbl, rd  
  4.   
  5.        ldr   \rd, =(KERNEL_RAM_PADDR 0x4000)  
  6.   
  7. .endm  


 

[cpp] viewplaincopyprint?
  1.   
  2. __create_page_tables:  
  3.     
  4.        pgtbl       r4                         page table address  
  5.   
  6.      
  7.   
  8.        mov r0, r4  
  9.        mov r3, #0  
  10.        add r6, r0, #0x4000  
  11.   
  12. 1:     str   r3, [r0], #4  
  13.        str   r3, [r0], #4  
  14.        str   r3, [r0], #4  
  15.        str   r3, [r0], #4  
  16.        teq  r0, r6  
  17.        bne  1b  
  18.   
  19.    
  20.        
  21.   
  22.        ldr   r7, [r10, #PROCINFO_MM_MMUFLAGS] mm_mmuflags  
  23.   
  24.          
  25.   
  26.          
  27.    
  28.        str   r3, [r4, r6, lsl #2]         identity mapping  
  29.   
  30.    
  31.          
  32.   
  33.          
  34.   
  35.   
  36.          
  37.   
  38.        str   r3, [r0, #(KERNEL_START 0x00f00000) >> 18]!  
  39.   
  40.         
  41.   
  42.        ldr   r6, =(KERNEL_END 1)  
  43.   
  44.         
  45.   
  46.        add r0, r0, #4  
  47.   
  48.         
  49.   
  50.       add r6, r4, r6, lsr #18  
  51. 1:    cmp       r0, r6  
  52.   
  53.         
  54.       add r3, r3, #1 << 20  
  55.       strls r3, [r0], #4  
  56.       bls   1b  
  57.   
  58.  #ifdef CONFIG_XIP_KERNEL  
  59.          
  60. #endif  
  61.   
  62.       
  63.        add r0, r4, #PAGE_OFFSET >> 18  
  64.        orr   r6, r7, #(PHYS_OFFSET 0xff000000)  
  65.        .if    (PHYS_OFFSET 0x00f00000)  
  66.        orr   r6, r6, #(PHYS_OFFSET 0x00f00000)  
  67.        .endif  
  68.        str   r6, [r0]  
  69.   
  70. #ifdef CONFIG_DEBUG_LL  
  71.          
  72. #if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)  
  73.          
  74. #endif  
  75.   
  76. #ifdef CONFIG_ARCH_RPC  
  77.    
  78. #endif  
  79.   
  80. #endif  
  81.   
  82.        mov pc, lr  
  83. ENDPROC(__create_page_tables)  
 

一口气将__create_pages_table分析完,但里涉及的代码还是需要细细品读。尤其是右移20位和18位两个地方与页表目录项的地址关系比较复杂。执行完该函数后,虚拟内存和物理内存的映射关系如下图所示:

 

 

6. 开启MMU

 

看完页表的建立,想必开启MMU的代码也是小菜一碟吧。此函数的主要功能是将页表的基址加到cp15中的面表指针寄存器,同时设置域访问(domainaccess)寄存器。

 

[cpp] viewplaincopyprint?
  1.   
  2. __enable_mmu:  
  3.    
  4. #ifdef CONFIG_ALIGNMENT_TRAP  
  5.        orr   r0, r0, #CR_A  
  6. #else  
  7.        bic   r0, r0, #CR_A  
  8. #endif  
  9.    
  10. #ifdef CONFIG_CPU_DCACHE_DISABLE  
  11.        bic   r0, r0, #CR_C  
  12. #endif  
  13.    
  14. #ifdef CONFIG_CPU_BPREDICT_DISABLE  
  15.        bic   r0, r0, #CR_Z  
  16. #endif  
  17.    
  18. #ifdef CONFIG_CPU_ICACHE_DISABLE  
  19.        bic   r0, r0, #CR_I  
  20. #endif  
  21.   
  22.         
  23.   
  24.        mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER)  
  25.                     domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER)  
  26.                     domain_val(DOMAIN_TABLE, DOMAIN_MANAGER)  
  27.                     domain_val(DOMAIN_IO, DOMAIN_CLIENT))  
  28.        mcr p15, 0, r5, c3, c0,           load domain access register  
  29.        mcr p15, 0, r4, c2, c0,           load page table pointer  
  30.            __turn_mmu_on  
  31. ENDPROC(__enable_mmu)  
  32.   
  33.   
  34.   
  35.        .align       
  36. __turn_mmu_on:  
  37.        mov r0, r0  
  38.   
  39.         
  40.   
  41.        mcr p15, 0, r0, c1, c0,           write control reg  
  42.        mrc p15, 0, r3, c0, c0,           read id reg  
  43.   
  44.        
  45.        mov r3, r3  
  46.        mov r3, r3  
  47.   
  48.        
  49.   
  50.        mov pc, r13  
  51. ENDPROC(__turn_mmu_on)  


7.__mmap_switched函数

__mmap_switched函数专用来设置C语言的执行环境,比如重定位工作,堆栈,以及BSS段的清零。 

__switch_data变量先定义了一系里面处量的数据,如重定位和数据段的地址,BSS段的地址,pocessor_id和__mach_arch_type变量的地址等。

 

[cpp] viewplaincopyprint?
  1.        .type       __switch_data, %object  
  2. __switch_data:  
  3.        .long       __mmap_switched  
  4.        .long       __data_loc                  r4  
  5.        .long       _data                           r5  
  6.        .long       __bss_start                  r6  
  7.        .long       _end                            r7  
  8.        .long       processor_id               r4  
  9.        .long       __machine_arch_type         r5  
  10.        .long       __atags_pointer                  r6  
  11.        .long       cr_alignment                r7  
  12.        .long       init_thread_union THREAD_START_SP sp  
  13.    
  14.   
  15. __mmap_switched:  
  16.        adr  r3, __switch_data  
  17.          
  18.        ldmia      r3!, {r4, r5, r6, r7}  
  19.   
  20.         
  21.   
  22.        cmp      r4, r5                           Copy data segment if needed  
  23. 1:     cmpne    r5, r6  
  24.        ldrne       fp, [r4], #4  
  25.        strne       fp, [r5], #4  
  26.        bne  1b  
  27.   
  28.          
  29.   
  30.        mov fp, #0                          Clear BSS (and zero fp)  
  31. 1:     cmp     r6, r7  
  32.        strcc       fp, [r6],#4  
  33.        bcc  1b  
  34.   
  35.      
  36.    
  37.        ldmia      r3, {r4, r5, r6, r7, sp}  
  38.        str   r9, [r4]                 Save processor ID  
  39.        str   r1, [r5]                 Save machine type  
  40.        str   r2, [r6]                 Save atags pointer  
  41.        bic   r4, r0, #CR_A                    Clear 'A' bit  
  42.   
  43.       
  44.   
  45.        stmia      r7, {r0, r4}                  Save control register values  
  46.   
  47.        
  48.   
  49.            start_kernel  
  50. ENDPROC(__mmap_switched)  

 

全文完, by linyt

[cpp] viewplaincopyprint?
  1.   
0 0
原创粉丝点击