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

ARM LINUX内核如何确定自己的实际物理地址

2017-06-27 13:04 323 查看
新旧内核有所不同

在旧的内核是通过宏KERNEL_RAM_PADDR来确定

.macro    pgtbl, rd  

  

       ldr   \rd, =(KERNEL_RAM_PADDR - 0x4000)  

  

.endm  

__create_page_tables:  

  /* r4 = KERNEL_RAM_PADDR – 0x4000 = 0x30004000 

   * 后面的C代码中的swapper_pg_dir变量,它的值也指向0x30004000 

   * 内存地址,不过它的值是虚拟内存地址,即0xc0004000 

   */  

       pgtbl       r4                         @ page table address  

  

   /* 将从r4到KERNEL_RAP_PADDR的16K页表空间清空。 */  

在新的内核中创建临时页表的时候,得到实际的物理内存地址是通过计算得到的,见下面加粗字体

44         .macro  pgtbl, rd, phys
 45         add     \rd, \phys, #TEXT_OFFSET - 0x4000
 46         .endm

 48 #ifdef CONFIG_XIP_KERNEL
 49 #define KERNEL_START    XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
 50 #define KERNEL_END      _edata_loc
 51 #else
 52 #define KERNEL_START    KERNEL_RAM_VADDR
 53 #define KERNEL_END      _end
 54 #endif

139 __create_page_tables:   @R8是实际的物理地址 R4是16K页表大小。
140         pgtbl   r4, r8            @ page table address通过宏 pgtbl 将r4设置成页表的基地址(物理地址),宏pgtbl 在 arch/arm/kernel/head.S第44定义,可以看到,页表是位于 TEXT_OFFSET下面 16k 的位置,r4 =  0x30004000 这是转换表的物理基地址,最终将写入CP15
的寄存器 2 , C2 。这个值必须是 16K 对齐的。
141 

74         __HEAD
 75 ENTRY(stext)
 76         setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ 确保进入管理(svc)模式
 77                                               @ 并且禁止中断
 78         mrc     p15, 0, r9, c0, c0              @ 读取CPU ID,存入r9寄存器
 79         bl      __lookup_processor_type      @ 调用函数,输入参数r9=cpuid,
                                                  @ 返回值r5=procinfo 
 80         movs    r10, r5                       @ 如果不支持当前CPU,则返回 (r5=0)
 81  THUMB( it      eq )            @ force fixup-able long branch encoding
 82         beq     __error_p                       @ 如果r5=0,则打印错误

 83 
 84 #ifndef CONFIG_XIP_KERNEL   
  @ 在调用__enable_mmu前使用的都是物理地址,而内核却是以虚拟地 址连接的,这里进行一次转换
 85         adr     r3, 2f              @ r3= 第124行代码的物理地址
 86         ldmia   r3, {r4, r8}         @ r4= 第124行代码的虚似地址,r8=PAGE_OFFSET
 87         sub     r4, r3, r4     @ (PHYS_OFFSET - PAGE_OFFSET)即物理地址与虚似地址差值
 88         add     r8, r8, r4     @ PHYS_OFFSET r8=PAGE_OFFSET对应的物理地址

 89 #else
 90         ldr     r8, =PLAT_PHYS_OFFSET    @ RAM的起始物理地址,值为0x30000000

  91 #endif
 92 
 93         /*
 94          * r1 = machine no, r2 = atags or dtb,
 95          * r8 = phys_offset, r9 = cpuid, r10 = procinfo
 96          */
 97         bl      __vet_atags  @ 检查bootloader传入的参数列表atags的合法性
 98 #ifdef CONFIG_SMP_ON_UP   @ 2410没有定义
 99         bl      __fixup_smp
 100 #endif
 101 #ifdef CONFIG_ARM_PATCH_PHYS_VIRT  @ 2410没有定义
 102         bl      __fixup_pv_table
 103 #endif
 在2.6.39版本前,还增加了__lookup_machine_type板级类型支持的检查,这里已经被取消,却增加了84-91行的代码,并且除第97行外,其它有些是没有的,
 104         bl      __create_page_tables  @创建初始页表

105 
106         /*
107          * The following calls CPU specific code in a position independent
108          * manner.  See arch/arm/mm/proc-*.S for details.  r10 = base of
109          * xxx_proc_info structure selected by __lookup_processor_type
110          * above.  On return, the CPU will be ready for the MMU to be
111          * turned on, and r0 will hold the CPU control register value.
112          */
113         ldr     r13, =__mmap_switched    @ 将列表__switch_data存到r13中后面会跳到该列表出
114                                          @ mmu has been enabled
115         adr     lr, BSYM(1f)  @ return (PIC) address将程序段 __enable_mmu的地址存到 lr中。 
116         mov     r8, r4                          @ set TTBR1 to swapper_pg_dir
    @ r10中存放的基地址是从__lookup_processor_type中得到的,如上面movs r10, r5
117  ARM(   add     pc, r10, #PROCINFO_INITFUNC     )
118  THUMB( add     r12, r10, #PROCINFO_INITFUNC    )
119  THUMB( mov     pc, r12                         )
120 1:      b       __enable_mmu
121 ENDPROC(stext)
122         .ltorg
123 #ifndef CONFIG_XIP_KERNEL
124 2:      .long   .   @ "."号表示当前这行代码编译连接后的虚似地址
125         .long   PAGE_OFFSET

126 #endif

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