本文主要是介绍arm-linux内核start_kernel之前启动分析(3)-开启MMU,走进新时代,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
最近在忙一款PPC处理器的芯片验证和内核移植工作,导致arm-linux启动分析最后一部一直没有写,今天将arm-linux start_kernel之前的最后一部分分析记录下。之前2篇文章链接如下:
http://blog.csdn.net/skyflying2012/article/details/41344377
http://blog.csdn.net/skyflying2012/article/details/41447843
kernel版本号:3.4.55
之前分析到__create_page_tables在内核代码区TEXT_OFF下部的16KB区域内进行页表的配置,完成turn_mmu_on的平映射以及kernel image的线性映射。接下来就需要开启MMU,让整个CPU进入虚拟地址运行的新阶段。head.S中stext最后一段代码如下:
/** 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 enabledadr lr, BSYM(1f) @ return (PIC) addressmov r8, r4 @ set TTBR1 to swapper_pg_dirARM( add pc, r10, #PROCINFO_INITFUNC )THUMB( add r12, r10, #PROCINFO_INITFUNC )THUMB( mov pc, r12 )
1: b __enable_mmu
ENDPROC(stext)
看注释也可以明白接下来要完成的2件工作:执行CPU特定处理代码,开启MMU。
在第一篇分析中我们知道r10中存储着本CPU的proc_info_list首地址。到这里需要再详细解释下内核的proc
info机制。在kernel image中定义有一个.proc.info.init的段。在arch/arm/kernel/vmlinux.lds.S中,如下:
#define PROC_INFO \
. = ALIGN(4); \
VMLINUX_SYMBOL(__proc_info_begin) = .; \
*(.proc.info.init) \
VMLINUX_SYMBOL(__proc_info_end) = .;
__proc_info_begin和__pro_info_end分别代表该段的头尾。.proc.info.init段中存储的数据是在arch/arm/mm/proc-xxx.S中定义的。到底使用哪个proc-xxx.S则由处理器的指令集版本号决定。
以我的cortex-A8处理器为例,是armv7指令集,根据arch/arm/mm/Makefile。
obj-$(CONFIG_CPU_V6) += proc-v6.o
obj-$(CONFIG_CPU_V6K) += proc-v6.o
obj-$(CONFIG_CPU_V7) += proc-v7.o
编译的是proc-v7.S,在该文件中有如下一段汇编:
.section ".rodata"string cpu_arch_name, "armv7"string cpu_elf_name, "v7".align//接下来定义的数据都在.proc.info.init段中.section ".proc.info.init", #alloc, #execinstr/** Standard v7 proc info content*///定义了宏定义__v7_proc,这个宏定义非常重要!
.macro __v7_proc initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \PMD_SECT_AF | PMD_FLAGS_SMP | \mm_mmuflags)ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \PMD_SECT_AF | PMD_FLAGS_UP | \mm_mmuflags).long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | \PMD_SECT_AP_READ | PMD_SECT_AF | \io_mmuflagsW(b) \initfunc.long cpu_arch_name.long cpu_elf_name.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | \HWCAP_EDSP | HWCAP_TLS | \hwcaps.long cpu_v7_name.long v7_processor_functions.long v7wbi_tlb_fns.long v6_user_fns.long v7_cache_fns
.endm//没有选择LPAE
#ifndef CONFIG_ARM_LPAE/** ARM Ltd. Cortex A5 processor.*/.type __v7_ca5mp_proc_info, #object
__v7_ca5mp_proc_info:.long 0x410fc050.long 0xff0ffff0__v7_proc __v7_ca5mp_setup.size __v7_ca5mp_proc_info, . - __v7_ca5mp_proc_info/** ARM Ltd. Cortex A9 processor.*/.type __v7_ca9mp_proc_info, #object
__v7_ca9mp_proc_info:.long 0x410fc090.long 0xff0ffff0__v7_proc __v7_ca9mp_setup.size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
#endif /* CONFIG_ARM_LPAE *//** ARM Ltd. Cortex A7 processor.*/.type __v7_ca7mp_proc_info, #object
__v7_ca7mp_proc_info:.long 0x410fc070.long 0xff0ffff0__v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV.size __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info/** ARM Ltd. Cortex A15 processor.*/.type __v7_ca15mp_proc_info, #object
__v7_ca15mp_proc_info:.long 0x410fc0f0.long 0xff0ffff0__v7_proc __v7_ca15mp_setup, hwcaps = HWCAP_IDIV.size __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info/** Match any ARMv7 processor core.*/.type __v7_proc_info, #object
__v7_proc_info:.long 0x000f0000 @ Required ID value.long 0x000f0000 @ Mask for ID__v7_proc __v7_setup.size __v7_proc_info, . - __v7_proc_info
这段汇编看出,指定.proc.info.init段中存储的是一些结构体,定义了V7指令集特定处理器的属性和处理函数。在C文件中我们找到了这些结构体的定义&
这篇关于arm-linux内核start_kernel之前启动分析(3)-开启MMU,走进新时代的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!