现在的位置: 首页 > 综合 > 正文

linux内核启动过程分析(二)

2013年10月07日 ⁄ 综合 ⁄ 共 2691字 ⁄ 字号 评论关闭

linux/arch/arm/kernel/head.Slinux内核映像解压后执行的第一个文件。

//PAGE_OFFSET = 0xc0000000; TEXT_OFFSET = 0x00008000;

//PHYS_OFFSET = 0x30000000;

#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET)

#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET)

/*

链接脚本文件arch/arm/kernel/vmlinux.lds指定了编译时程序段存放的位置。

SECTIONS

{

#ifdef CONFIG_XIP_KERNEL

. = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);

#else

. = PAGE_OFFSET + TEXT_OFFSET;

#endif

.text.head : {

_stext = .;

_sinittext = .;

*(.text.head)

}

.init : {

……………………

}

*/

.section ".text.head", "ax"

ENTRY(stext)

msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE  //禁止FIQIRQ,设定SVC模式

mrc p15, 0, r9, c0, c0 获取 processor id

/*判断CPU类型,查找运行的CPU ID值与Linux编译支持的ID值是否支持 */

bl __lookup_processor_type @ r5=procinfo r9=cpuid

movs r10, r5 @ invalid processor (r5=0)?

///*判断如果r10的值为0,跳转到出错处理,*/

beq __error_p @ yes, error 'p'

//查询machine ID并检查合法性

bl __lookup_machine_type @ r5=machinfo

movs r8, r5 @ invalid machine (r5=0)?

beq __error_a @ yes, error 'a'

bl __vet_atags  //检查bootloader传入的参数列表atags合法性

bl __create_page_tables  //创建初始页表

ldr r13, __switch_data   //将列表__switch_data存到r13中后面会跳到该列表出

adr lr, __enable_mmu //将程序段__enable_mmu的地址存到lr中。

//此命令将导致程序段__arm920_setup的执行,后面会将到。

//r10中存放的基地址是从__lookup_processor_type中得到的,如上面movs r10, r5

   add pc, r10, #PROCINFO_INITFUNC 

ENDPROC(stext)

 

接下来将对上面遇到的几个程序段展开分析。

__lookup_processor_type

/**********************************************************************/

在讲解该程序段之前先来看一些相关知识。

内核做支持的每一种CPU类型都由结构体proc_info_list 来描述。

该结构体在文件arch/arm/include/asm/procinfo.h中定义:

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;

};

对于arm920来说,其对应结构体在文件 linux/arch/arm/mm/proc-arm920.S

初始化。

.section ".proc.info.init", #alloc, #execinstr

.type __arm920_proc_info,#object

__arm920_proc_info:

.long 0x41009200

.long 0xff00fff0

.long   PMD_TYPE_SECT | \

PMD_SECT_BUFFERABLE | \

PMD_SECT_CACHEABLE | \

PMD_BIT4 | \

PMD_SECT_AP_WRITE | \

PMD_SECT_AP_READ

.long   PMD_TYPE_SECT | \

PMD_BIT4 | \

PMD_SECT_AP_WRITE | \

PMD_SECT_AP_READ

b __arm920_setup

………………………………

.section ".proc.info.init"表明了该结构在编译后存放的位置。

在链接文件arch/arm/kernel/vmlinux.lds中:

SECTIONS

{

#ifdef CONFIG_XIP_KERNEL

. = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);

#else

. = PAGE_OFFSET + TEXT_OFFSET;

#endif

.text.head : {

_stext = .;

_sinittext = .;

*(.text.head)

}

.init : { /* Init code and data */

INIT_TEXT

_einittext = .;

__proc_info_begin = .;

*(.proc.info.init)

__proc_info_end = .;

__arch_info_begin = .;

*(.arch.info.init)

抱歉!评论已关闭.