linux内存管理 (三) 2 压缩与未压缩的内核镜像启动粗略解析

1. uboot引导内核的必要条件

// 推荐一本书 Booting ARM Linux.pdf ,可在网络搜索.
Configure the memory system.
Load the kernel image at the correct memory address.
Optionally load an initial RAM disk at the correct memory address.
Initialise the boot parameters to pass to the kernel.
Obtain the ARM Linux machine type
Enter the kernel with the appropriate register values.

1.配置内存系统
2.加载内核映像到正确的内存地址
//可选择在正确的内存地址加载初始RAM磁盘。
3.初始化引导参数,并将地址写到r2
4.获取ARM Linux机器类型,并写到r1
5.r0 为0
6.让内核运行

通常除了这些基本任务外,引导加载程序还会为内核初始化一个串行或视频控制台。实际上,在大多数系统配置中,串行端口几乎被认为是必需的。

2.1如果uboot 引导了一个压缩的内核

像以下内核镜像都是被压缩的,压缩格式可以为 GZIP,LZO,LZMA,当前为gzip.
  arch/arm/boot/compressed/vmlinux
  arch/arm/boot/zImage
  arch/arm/boot/uImage
  
 这些文件的组成如下
 	1.前缀
 	2.解压代码
 	3.gzip压缩的二进制内核
入口
	linux的第一行代码从 linux-3.0.1/arch/arm/boot/compressed/head.S 中的 start 标号地址的 mov r0, r0 开始
出口
	到 mov pc, r4 跳转到 linux-3.0.1/arch/arm/kernel/head.S 中的 75ENTRY(stext)

linux-3.0.1/arch/arm/boot/compressed/head.S 中 115.section ".start", #alloc, #execinstr // line 115
start:
        .type   start,#function                                                  
        .rept   7                                                                
        mov r0, r0                                                               
        .endr
		...
1:      mov r7, r1          @ save architecture ID
		mov r8, r2          @ save atags pointer
		...
/*                                                                               
 * The C runtime environment should now be setup sufficiently.                       
 * Set up some pointers, and start decompressing.                                
 *   r4  = kernel execution address                                              
 *   r7  = architecture ID                                                       
 *   r8  = atags pointer                                                         
 */                                                                              
        mov r0, r4                                                               
        mov r1, sp          @ malloc space above stack                           
        add r2, sp, #0x10000    @ 64k max                                        
        mov r3, r7                                                               
        bl  decompress_kernel                                                    
        bl  cache_clean_flush                                                    
        bl  cache_off                                                            
        mov r0, #0          @ must be zero                                       
        mov r1, r7          @ restore architecture number                        
        mov r2, r8          @ restore atags pointer                              
        mov pc, r4          @ call kernel
这里不讲述linux-3.0.1/arch/arm/kernel/head.S 的意图

2.2如果uboot 引导了一个未压缩的内核

// 这些文件都是没被压缩的.
  vmlinux // 该文件在编译过程中,生成与顶层目录,和 arch/arm/boot/compressed/vmlinux 有区别
  arch/arm/boot/Image
入口
	linux-3.0.1/arch/arm/kernel/head.S 中的 75ENTRY(stext)
	
出口过程 // TODO
	ldr r13, =__mmap_switched       @ address to jump to after
	adr lr, BSYM(1f)            @ return (PIC) address
	add pc, r10, #PROCINFO_INITFUNC
		r10 是 变量 __v6_proc_info 的 首地址 ,变量的类型是 struct proc_info_list
		arch/arm/kernel/asm-offsets.c DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush)); 
		r10+#PROCINFO_INITFUNC 的 值 是 变量 __v6_proc_info  中的 __cpu_flush 成员的地址
		在arch/arm/mm/proc-v6.S中查找到 __v6_proc_info  的赋值, 该变量的__cpu_flush成员 为 b   __v6_setup 
		综上: 
			1.该句就是调用了__v6_proc_info 的  __cpu_flush  成员 ,该成员为b   __v6_setup
			2.也就是说调用了 __v6_setup 函数
			
	__v6_setup // arch/arm/mm/proc-v6.S
		mov pc, lr // 通过将lr寄存器赋给pc,导致对__enable_mmu的调用
		
	1:  b   __enable_mmu
	
	__enable_mmu
		__turn_mmu_on
		
	__turn_mmu_on
		mov r3, r13 // r13 中 为 __mmap_switched 的地址
		mov pc, r3 //  将r13寄存器值赋给pc,调用__mmap_switched
		
	__mmap_switched // arch/arm/kernel/head-common.S
		b   start_kernel // 调用在init/main.c文件中的 start_kernel


    __HEAD                                                                       
ENTRY(stext)                                                                        
    setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode                  
                        @ and irqs disabled                                         
    mrc p15, 0, r9, c0, c0      @ get processor id                                  
    bl  __lookup_processor_type     @ r5=procinfo r9=cpuid                          
    movs    r10, r5             @ invalid processor (r5=0)?                         
 THUMB( it  eq )        @ force fixup-able long branch encoding                     
    beq __error_p           @ yes, error 'p'                                        
                                                                                    
#ifndef CONFIG_XIP_KERNEL                                                           
    adr r3, 2f                                                                      
    ldmia   r3, {r4, r8}                                                            
    sub r4, r3, r4          @ (PHYS_OFFSET - PAGE_OFFSET)                           
    add r8, r8, r4          @ PHYS_OFFSET                                           
#else                                                                               
    ldr r8, =PLAT_PHYS_OFFSET                                                       
#endif                                                                              
                                                                                    
    /*                                                                              
     * r1 = machine no, r2 = atags or dtb,                                          
     * r8 = phys_offset, r9 = cpuid, r10 = procinfo                                 
     */                                                                             
    bl  __vet_atags
#ifdef CONFIG_SMP_ON_UP                                                          
    bl  __fixup_smp                                                              
#endif                                                                           
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT                                                
    bl  __fixup_pv_table                                                         
#endif                                                                           
    bl  __create_page_tables                                                     
                                                                                 
    /*                                                                           
     * The following calls CPU specific code in a position independent           
     * manner.  See arch/arm/mm/proc-*.S for details.  r10 = base of             
     * xxx_proc_info structure selected by __lookup_processor_type               
     * above.  On return, the CPU will be ready for the MMU to be                
     * turned on, and r0 will hold the CPU control register value.               
     */                                                                          
    ldr r13, =__mmap_switched       @ address to jump to after                   
                        @ mmu has been enabled                                   
    adr lr, BSYM(1f)            @ return (PIC) address                           
    mov r8, r4              @ set TTBR1 to swapper_pg_dir                        
 ARM(   add pc, r10, #PROCINFO_INITFUNC )                                        
 THUMB( add r12, r10, #PROCINFO_INITFUNC    )                                    
 THUMB( mov pc, r12             )                                                
1:  b   __enable_mmu                                                             
ENDPROC(stext)




你可能感兴趣的:(Linux内存管理)