linux版本:linux-3.10.65,ARM64
在分析 __pfn_to_page 时,其定义为:kernel-3.10\include\asm-generic\memory_model.h(先以FLATMEM为例分析)
#define __pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET))
#define __page_to_pfn(page) ((unsigned long)((page) - mem_map) + ARCH_PFN_OFFSET)
发现关键的这个宏定义ARCH_PFN_OFFSET
kernel-3.10/arch/arm64/include/asm/memory.h:137:#define ARCH_PFN_OFFSET ((unsigned long)PHYS_PFN_OFFSET)
kernel-3.10/arch/arm64/include/asm/memory.h:109:#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
kernel-3.10/arch/arm64/include/asm/memory.h:99:#define PHYS_OFFSET ({ memstart_addr; })
通过搜索,发现最终需要确定memstart_addr的值,整个内核中搜索,发现只有在 kernel-3.10/arch/arm64/kernel/head.S 文件中
有定义:
.align 3
.type __switch_data, %object
__switch_data:
.quad __mmap_switched // .quad为8字节,quard word也就是4字(8字节)
.quad __data_loc // x4
.quad _data // x5
.quad __bss_start // x6
.quad _end // x7
.quad processor_id // x4
.quad __fdt_pointer // x5
.quad memstart_addr // x6
.quad init_thread_union + THREAD_START_SP // sp
此函数中,将 x24 寄存器中的值保存到 memstart_addr 变量中
__mmap_switched:
adr x3, __switch_data + 8 // x3 = __data_loc,此处用" = "表示指向,即x3指向__data_loc
ldp x4, x5, [x3], #16 // x4 = __data_loc , x5 = _data
ldp x6, x7, [x3], #16 // x6 = __bss_start , x7 = _end
cmp x4, x5 // Copy data segment if needed
1: ccmp x5, x6, #4, ne
b.eq 2f
ldr x16, [x4], #8
str x16, [x5], #8
b 1b
2:
1: cmp x6, x7
b.hs 2f
str xzr, [x6], #8 // Clear BSS
b 1b
2:
ldp x4, x5, [x3], #16 // x4 = processor_id , x5 = __fdt_pointer
ldr x6, [x3], #8 // x6 = memstart_addr
ldr x16, [x3] // x16 = init_thread_union + THREAD_START_SP
mov sp, x16
str x22, [x4] // Save processor ID
str x21, [x5] // Save FDT pointer
str x24, [x6] // Save PHYS_OFFSET,此处将 x24 寄存器中的内容保存到 x6 指向的内存
// 中,即 变量 memstart_addr,那么 x24 寄存器中是什么东西呢?
mov x29, #0
b start_kernel
ENDPROC(__mmap_switched)
ENTRY(stext)
mov x21, x0 // x21=FDT
bl __calc_phys_offset // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
bl el2_setup // Drop to EL1
mrs x22, midr_el1 // x22=cpuid
mov x0, x22
bl lookup_processor_type
mov x23, x0 // x23=current cpu_table
cbz x23, __error_p // invalid processor (x23=0)?
bl __vet_fdt
bl __create_page_tables // x25=TTBR0, x26=TTBR1
/*
* The following calls CPU specific code in a position independent
* manner. See arch/arm64/mm/proc.S for details. x23 = base of
* cpu_info structure selected by lookup_processor_type above.
* On return, the CPU will be ready for the MMU to be turned on and
* the TCR will have been set.
*/
ldr x27, __switch_data // address to jump to after
// MMU has been enabled
adr lr, __enable_mmu // return (PIC) address
ldr x12, [x23, #CPU_INFO_SETUP]
add x12, x12, x28 // __virt_to_phys
br x12 // initialise processor
ENDPROC(stext)
从stext -> __calc_phys_offset 调用名称可知, x24 = PHYS_OFFSET