您的位置:首页 > 运维架构 > Linux

ARM Linux 内核启动总结 之 创建临时页表

2016-08-11 14:47 246 查看
硬件平台:S5PV210   内核版本:Linux2.6.32   文件:head.S(linux/arch/arm/kernel/)

#include <**********>

#define KERNEL_RAM_VADDR    (PAGE_OFFSET + TEXT_OFFSET) 

#define KERNEL_RAM_PADDR    (PHYS_OFFSET + TEXT_OFFSET)

//PAGE_OFFSET是内核虚拟地址空间的起始地址,一般为0xC000_0000

//PHYS_OFFSET 是硬件物理内存的起始地址,在文件memory.h(linux/arch/arm/mach-s5pv210/include/mach/)中定义,为0x2000_0000

//TEXT_OFFSET是内核代码相对于起始地址的偏移量,一般为0x8000

//KERNEL_RAM_VADDR=0xC000_8000;     KERNEL_RAM_PADDR=0x2000_8000

//刚开始的这32k(0x8000)空间用来存放页表,启动参数等

 

 .globl swapper_pg_dir

 .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000

//equ相当于C语言中的#define

 

 .macro pgtbl, rd

 ldr \rd, =(KERNEL_RAM_PADDR - 0x4000)

 .endm

//这里定义了一个宏,把物理地址0x2000_4000赋值给rd寄存器,一般这个地址用来存放临时页表

 

#ifdef CONFIG_XIP_KERNEL(未定义)

#define KERNEL_START XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)

#define KERNEL_END _edata_loc

#else

#define KERNEL_START KERNEL_RAM_VADDR

#define KERNEL_END _end

#endif

//KERNEL_START=0xC000_8000, KERNEL_END=具体是多少没搞懂

 .section ".text.head", "ax"

ENTRY(stext)

********************************* 

 bl __create_page_tables

//跳过其他的启动过程,直接看创建页表的过程__create_page_tables

 

__create_page_tables:

 pgtbl r4                                 //宏展开,把物理地址0x2000_4000赋值给r4寄存器

 mov r0, r4                             //r0=r4=0x2000_4000

 mov r3, #0                            //r3=0

 add r6, r0, #0x4000              //r6=0x2000_8000; r0和r6一起限定了页表的范围

1: str r3, [r0], #4

 str r3, [r0], #4

 str r3, [r0], #4

 str r3, [r0], #4                      

 teq r0, r6                             

 bne 1b                                   //将0x2000_4000开始到0x2000_8000之间的物理内存初始化为0,为后面的填充页表做准备

 ldr r7, [r10, #PROCINFO_MM_MMUFLAGS]         //r10存放的是procinfo结构的地址,里面包含了内存管理相关的参数

 mov r6, pc                          //这时候PC值是物理值,因为还没有开MMU。内核启动阶段,PC值应该处于物理内存开始的部分,是0x200*_****

 mov r6, r6, lsr #20              //右移20位,r6=0x200,用r6来指示内核所处的段。

 orr r3, r7, r6, lsl #20           //把内存管理的一些参数加进去赋值给r3。注意r6还是0x200,r3=0x2000_****(flags)

 str r3, [r4, r6, lsl #2]           

//从0x2000_4000开始存放页表,这里使用的是段页表,4G=4K*1M,所以一共有4096个页表项,每个页表项代表1M空间。虚拟地址的高12位用来在这个页表中找到具体的页表项,2^12=4096,也就是0x000~0xfff。每个页表项占4个字节,刚刚好是4*4096=16K,也就是0x2000_4000到(0x2000_8000-1)这个区间大小。虚拟地址的低20位用来在1M的空间里定位某个具体的字节2^20=1M。

//为什么还要把物理地址进行映射呢?我在其他高手的博客中看到过,好像是因为:CPU流水线取指令,在开MMU后,PC地址应该全部是虚拟地址,但是预取指令功能导致开MMU的时候既有虚拟地址,又有物理地址,如果我们只建立虚拟地址的映射,那么PC物理地址送到MMU之后就会找不到相应的页表,会出错。大概是这样,这部分理解还有待深入确认。

//注意一下这里的 r6, lsl #2,就是r6*4=0x200*4=0x800,0x200相对于0x000的偏移量是0x200,每个页表项占4个字节,所以这个1M的段对应的页表项地址就是0x2000_4800,最后把r3的值存进这个页表项中。

 

 add r0, r4,  #(KERNEL_START & 0xff000000) >> 18       //KERNEL_START=0xC000_8000,所以r0=0x2000_4000+0xC00*4=0x2000_7000

//提取内核虚拟地址空间的段地址,右移18位就是右移20位,然后左移2位,找到对应的页表项

 str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!  //KERNEL_START & 0x00f00000=0,对0x2000_7000处的页表项进行填充

 ldr r6, =(KERNEL_END - 1)               //r6存放要映射的虚拟地址的终点,假设r6=0xC03*_****

 add r0, r0, #4                                    //r0=0x2000_7000+4=0x2000_7004

 add r6, r4, r6, lsr #18                        //找到虚拟地址终点所在段对应的页表项地址r6=0x2000_4000+0xC03*4=0x2000_700C

1: cmp r0, r6

 add r3, r3, #1 << 20                          //0xC00段对应0x200段,0xC01段对应0x201段,0xC02段对应0x202段。。。

 strls r3, [r0], #4

 bls 1b                                                //对整个内核代码段(表述不确切,这个范围由KERNEL_END 决定)进行映射,填充相应的页表项

 add r0, r4, #PAGE_OFFSET >> 18                     //PAGE_OFFSET=0xC000_0000,r0=0x2000_7000 

 orr r6, r7, #(PHYS_OFFSET & 0xff000000)         //r7里面存放的是内存管理参数,r6=0x2000_****

 .if (PHYS_OFFSET & 0x00f00000)

 orr r6, r6, #(PHYS_OFFSET & 0x00f00000)

 .endif

 str r6, [r0]                                                            //对0x2000_7000处的页表项再次进行填充。填充的数值是一样的,都是0x2000_****(flags)

//对于上面的重复操作,摘录了“海枫”博客中的解释  (http://blog.csdn.net/linyt/article/details/6582399 )

   通常kernel的启动参数由bootloader放到了物理内存的第1个M上,所以需要为RAM上的第1个M建立映射。 

* 上面已为PHYS_OFFSET + TEXT_OFFSET建立了映射,如果TEXT_OFFSET小于0x00100000的话, 

* 上面代码应该也为SDRAM的第一个M建立了映射,但如果大于0x0010000则不会。 

* 所以这里无论如何均为SDRAM的第一个M建立映射(不知分析对否,还请指正)。 

mov pc, lr                      //结束

转自 :http://blog.163.com/q_n_b/blog/static/214798216201301495346679/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: