内核


1、压缩和非压缩内核映像


非压缩内核映像是真正的Linux内核代码。压缩内核映像是把非压缩内核映像作为数据进行压缩打包,并加入了解压缩代码。也就是说,他是一个自解压的可执行映像。压缩内核映像执行时,先解压内部包含的数据块(即非压缩内核映像),再去执行非压缩内核映像。


非压缩内核映像由make Image命令产生。其生成过程是:
(1)内核的各个模块经过编译,链接,在内核源代码的顶层目录下生成vmlinux文件,这是一个ELF格式的映像
(2)用arm-linux-objcopy命令把vmlinux转换为二进制映像 arch/arm/boot/Image


压缩内核隐形由make zImage命令产生,其生成过程是:
(1)用gzip对非压缩内核二进制映像arch/arm/boot/Image 进行压缩,生成 arch/arm/boot/compressed/piggy.gz文件
(2)arch/arm/boot/compressed/目录下有三个文件:
     piggy.s,定义了一个包含./piggy.gz文件的数据段;
     head.S包含了对gzip压缩过的内核新型解压的代码;
     vmlinux-lds是链接脚本。
   这几个文件经过编译链接,在arch/arm/boot/compressed/目录下产生vmlinux文件,这是一个ELF格式的映像;
(3)用arm-linux-objcopy命令把 arch/arm/boot/compressed/vmlinux 转换成二进制格式映像:arch/arm/boot/compressed/zImage


1)重要常量


PAGE_OFFSET: 内核空间起点,0xC0000000(3GB)
TEXT_OFFSET: 内核代码段偏移量,0x8000(32KB)
PHYS_OFFSET: 物理内存其实地址,对于AT91SAM9260EK,为0x20000000
KERNEL_RAM_VADDR: 内核起始虚拟地址 = 0xC0008000(3GB+32KB)
KERNEL_RAM_PADDR: 内核起始物理地址 = 0x20008000


从代码中还可以看出,Linux内核的起始虚拟地址的低16位必须为0x800,起始页目录表swapper_pg_dir的虚拟地址在0xC0004000(3GB+16KB)


2)内核启动的执行流程


--设置处理器为SVC模式,关中断
--读取CPUID,调用__lookup_processor_type查找处理器信息结构proc_info
--调用__lookup_machine_type查找机器类型信息结构machine_desc
--调用__create_page_tables函数为内核创建页面映射表
--调用处理器底层初始化函数,初始化MMU,Cache,TLB
--跳转到__enable_mmu函数,打开mmu
--跳转到__mmap_switched函数,建立C语言运行环境(搬移数据段,清理BSS段),保存CPUID和机器类型代码,最后跳转到C语言入口函数start_kernel()


3)处理器信息结构和机器类型信息结构的查找


所有CPU的信息结构都放在名为".proc.info.init"的段中,链接后形成一个完整的段,段的起始地址为__proc_info_begin,结束地址为__proc_info_end。按关键字在__proc_info_begin和__proc_info_end之间进行搜索就可以找到指定CPU的信息结构。CPU信息结构的第一个数据成员就是关键字(CPUID)。搜索过程中要使用物理地址,因为此时MMU还没有打开,所以代码中有一个把__proc_info_begin和__proc_info_end从虚拟地址转换为物理地址的过程,处理的十分巧妙,详情可以参见源代码及其注释。


机器类型信息结构的查找也采用类似的办法。所有的及其类型信息结构都放在".arch.info.init"段中,段的起始地址为__arch_info_begin,结束地址为__arch_info_end。搜索的关键字是机器类型代码,也保存在机器类型信息结构machine_desc的第一个数据成员中。


4)存储映射
对于AT91SAM9260EK,内核启动过程中通过__create_page_tables函数创建了一下两个地址区间的映射:
序号      起始虚拟地址        起始物理地址         长度
1         0x20000000          0x20000000            1MB
2         0xC0000000          0x20000000            内核总长度向上调整到1MB的整数倍
其中第一个地址区间的映射是为了实现打开MMU前后地址空间的平稳过渡。


5)处理器底层初始化函数
代码中通过以下指令转移到处理器底层初始化函数:
   add pc,r10,#PROCINFO_INITFUNC
此时r10为CPU信息结构的指针,常量PROCINFO_INITFUNC定义为16,程序调转到CPU信息结构块偏移16字节的地址,这里存放的是一条转向CPU底层初始化函数的跳转指令。对于AT91SAM9260EK,CPU信息结构和底层初始化函数都在arch/arm/mm/proc-arm926.S中:

Logo

更多推荐