微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 装载ARM Linux内核启动过程

装载ARM Linux内核启动过程

时间:11-09 来源:互联网 点击:
LinuxKernelStartARM

ARM Linux内核启动过程.

Updated Feb 24, 2011 by swordhui...@gmail.com

注: 本文转自ChinaUnix 作者为XPL.

本文针对arm linux, 从kernel的第一条指令开始分析,一直分析到进入 start_kernel()函数. 我们当前以linux-2.6.19内核版本作为范例来分析,本文中所有的代码,前面都会加上行号以便于和源码进行对照, 例: 在文件init/main.c中: 00478: asmlinkage void init start_kernel(void) 前面的"00478:" 表示478行,冒号后面的内容就是源码了.

在分析代码的过程中,我们使用缩进来表示各个代码的调用层次.

由于启动部分有一些代码是平台特定的,虽然大部分的平台所实现的功能都比较类似,但是为了更好的对code进行说明,对于平台相关的代码,我们选择 at91(ARM926EJS)平台进行分析.

另外,本文是以uncompressed kernel开始讲解的.对于内核解压缩部分的code,在 arch/arm/boot/compressed中,本文不做讨论.

一. 启动条件

通常从系统上电到执行到linux kenel这部分的任务是由boot loader来完成. 关于boot loader的内容,本文就不做过多介绍. 这里只讨论进入到linux kernel的时候的一些限制条件,这一般是boot loader在最后跳转到kernel之前要完成的:

  • 1. CPU必须处于SVC(supervisor)模式,并且IRQ和FIQ中断都是禁止的;
  • 2. MMU(内存管理单元)必须是关闭的, 此时虚拟地址对物理地址;
  • 3. 数据cache(Data cache)必须是关闭的
  • 4. 指令cache(Instruction cache)可以是打开的,也可以是关闭的,这个没有强制要求;
  • 5. CPU 通用寄存器0 (r0)必须是 0;
  • 6. CPU 通用寄存器1 (r1)必须是 ARM Linux machine type (关于machine type, 我们后面会有讲解)
  • 7. CPU 通用寄存器2 (r2) 必须是 kernel parameter list 的物理地址(parameter list 是由boot loader传递给kernel,用来描述设备信息属性的列表,详细内容可参考"Booting ARM Linux"文档).

二. starting kernel

首先,我们先对几个重要的宏进行说明(我们针对有MMU的情况):

位置默认值说明
KERNEL_RAM_ADDRarch/arm/kernel/head.S +260xc0008000kernel在RAM中的的虚拟地址
PAGE_OFFSETinclude/asm-arm/memeory.h +500xc0000000内核空间的起始虚拟地址
TEXT_OFFSETarch/arm/Makefile +1370x00008000内核相对于存储空间的偏移
TEXTADDRarch/arm/kernel/head.S +490xc0008000kernel的起始虚拟地址
PHYS_OFFSETinclude/asm-arm/arch-xxx/memory.h平台相关RAM的起始物理地址

内核的入口是stext,这是在arch/arm/kernel/vmlinux.lds.S中定义的:

00011: ENTRY(stext)

对于vmlinux.lds.S,这是ld script文件,此文件的格式和汇编及C程序都不同,本文不对ld script作过多的介绍,只对内核中用到的内容进行讲解,关于ld的详细内容可以参考ld.info 这里的ENTRY(stext) 表示程序的入口是在符号stext. 而符号stext是在arch/arm/kernel/head.S中定义的: 下面我们将arm linux boot的主要代码列出来进行一个概括的介绍,然后,我们会逐个的进行详细的讲解.

在arch/arm/kernel/head.S中 72 - 94 行,是arm linux boot的主代码: 00072: ENTRY(stext)
00073: msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
00074: @ and irqs disabled
00075: mrc p15, 0, r9, c0, c0 @ get processor id
00076: bl __lookup_processor_type @ r5=procinfo r9=cpuid
00077: movs r10, r5 @ invalid processor (r5=0)?
00078: beq __error_p @ yes, error p
00079: bl __lookup_machine_type @ r5=machinfo
00080: movs r8, r5 @ invalid machine (r5=0)?
00081: beq __error_a @ yes, error a
00082: bl __create_page_tables
00083:
00084: /*
00085: * The following calls CPU specific code in a position independent
00086: * manner. See arch/arm/mm/proc-*.S for details. r10 = base of
00087: * xxx_proc_info structure selected by __lookup_machine_type
00088: * above. On return, the CPU will be ready for the MMU to be
00089: * turned on, and r0 will hold the CPU control register value.
00090: */
00091: ldr r13, __switch_data @ address to jump to after
00092: @ mmu has been enabled
00093: adr lr, __enable_mmu @ return (PIC) address
00094: add pc, r10, #PROCINFO_INITFUNC

其中,73行是确保kernel运行在SVC模式下,并且IRQ和FIRQ中断已经关闭,这样做是很谨慎的.

arm linux boot的主线可以概括为以下几个步骤:

  • 1. 确定 processor type (75 - 78行)
  • 2. 确定 machine

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top