arm linux 启动之一:汇编启动到start_kernel
一、arm linux的引导
uboot在引导arm linux(uImage镜像)到SDRAM之后,通过bootm命令对uImage镜像的64个字节头进行解释,获取linux的entry入口地址,并赋值给theKernel函数指针(一般该值是0x38),并将uboot的环境变量参数(如平台的内存块区域信息、linux启动命令信息bootargs等)按linux要求的tags形式放置在0x30100起始的地方。接着关掉MMU,清除icache,dcache,最后通过该函数将控制权交给arm linux:
theKernel (0, machid, bd->bi_boot_params);
其中,machid是平台的id,其需要与arch/arm/tools/mach_types 中定义的机器ID一致,否则无法启动。bd->bi_boot_params即0x30100,描述了linux启动所需要的信息。
二、arm linux启动的第一部分
该部分是体系相关的汇编部分,代码位于arch\arm\kernel\head.S,入口是ENTRY(stext),其主要完成的工作包括:
1) 设置当前arm工作模式是svc mode,关中断
2)__lookup_processor_type获取对应的CPU信息数据结构地址,主要是arm v7架构相关的信息,如MMU,cache标志值等,数据结构如下:
struct proc_info_list {
unsigned int cpu_val;
unsigned int cpu_mask;
unsigned long__cpu_mm_mmu_flags; /* used by head.S */
unsigned long__cpu_io_mmu_flags; /* used by head.S */
unsigned long__cpu_flush; /* used by head.S */
const char *arch_name;
const char *elf_name;
unsigned int elf_hwcap;
const char *cpu_name;
struct processor *proc;
struct cpu_tlb_fns *tlb;
struct cpu_user_fns *user;
struct cpu_cache_fns *cache;
};
arm linux支持各种CPU体系架构,其描述在.proc.info.init 段,对应S5PV210即arch\arm\mm\proc-v7.S,lookup_processor_type先通过协处理器CP15读出CPU ID并跟cpu_val比较,匹配即可得到数据结构地址。该地址是链接到虚拟地址,而此时MMU是关闭的,需要将该地址转为物理地址访问。
3)__lookup_machine_type获取对应平台机器的数据结构地址,主要是平台板子相关的数据信息,如内存起始地址和大小,中断和timer初始化函数等,如下:
struct machine_desc {
unsigned intnr; /* architecture number */
unsigned int phys_io; /* start of physicalio */
unsigned int io_pg_offst; /* byte offsetfor io * page tabe entry */
const char *name;/* architecture name */
unsigned long boot_params; /*tagged list */
unsigned int video_start; /* start of videoRAM */
unsigned int video_end; /* end ofvideo RAM */
unsigned int reserve_lp0 :1; /* never haslp0 */
unsigned int reserve_lp1 :1; /* never haslp1 */
unsigned int reserve_lp2 :1; /* never haslp2 */
unsigned int soft_reboot :1; /* softreboot */
void(*fixup)(struct machine_desc *, struct tag *, char **, struct meminfo *);
void(*map_io)(void);/* IO mapping function */
void(*init_irq)(void);
struct sys_timer *timer;/* system tick timer */
void(*init_machine)(void);
};
arm linux支持各种平台板子,其描述在.arch.info.init 段,对应S5PV210即\arch\arm\mach-s5pv210\mach-smdkv210.c。UBOOT的machid即用于搜索匹配nr,以取到机器信息。
4)检查uboot传递过来的tags是否符合标准,并检测machine数据结构的boot_params的值是否等于theKernel传递过来的第三个参数(0x30100)
5)create_page_tables 创建临时页表,均是以1M为单位进行映射,所以4G空间需要16K,从0x34到0X38。共映射三个部分:
i. linux内核镜像空间的映射(0xc8***开始的内核空间映射到0x38***)
ii. 创建页表到开启mmu之间还有一段代码需要运行,因为还需要为linux启动的初始1M空间创建一段直接映射,此时还是0X38+的地址运行,所以映射是0X38+映射到0X38+
iii. uboot传递过来的tags参数也需要进行映射(虚拟0XC**映射到0X3**),以进行访问。
6)ldr r13, __switch_data,将__switch_data数据结构的地址入栈。
7)add pc,r10, #PROCINFO_INITFUNC,即将PC改到arch\arm\mm\proc-v7.S的__v7_setup去执行,跳转前将__enable_mmu放到lr,即__v7_setup执行完就返回到__enable_mmu。__v7_setup主要是CPU体系相关的初始化,如icache,dcache等。
8)__enable_mmu打开MMU,
armlinux启 相关文章:
- ARM Linux 更新启动画面(11-21)
- ARM Linux启动分析headarmv.S内幕(11-09)
- ARM linux的启动部分源代码简略分析(11-09)
- arm linux 启动流程(11-09)
- ARM Linux 的启动过程(11-09)
- arm linux 启动流程之 进入内核(11-09)