内核的人口是stext,这个是在arch/arm/kernel/vmlinux.lds.s定义
而符号stext是在arch/arm/kernel/head.S中定义的
其主线大致为:
1、确定processor type
通过cp15协处理器的c0寄存器来获取processor id的指令,跳转到__lookup_processor_type
__lookup_processor_type和数主要是根据从cpu获取的processor id和系统中的proc_info进行匹配,将匹配到得proc_info_list的基地址到r5,在processor type存储在r5中,最后判断r5十分为0,如果是0,说明是无效的type,跳转到error_p出错2、确定machine type
__proc_info_begin和__proc_info_end是在arch/arm/kernel/vmlinux.lds.S中:
__proc_info_begin = .;
*(.proc.info.init)
__proc_info_end = .;
这个地址存放着所有文件中的".proc.info.init"段得内容
kernel 使用struct proc_info_list来描述processor type.
在 include/asm-arm/procinfo.h 中:
struct proc_info_list {
unsigned int cpu_val;
unsigned int cpu_mask;
unsigned long __cpu_mm_mmu_flags;
unsigned long __cpu_io_mmu_flags;
unsigned long __cpu_flush;
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;
};
3、创建页表 __create_page_tables
4、调用平台特有的__cpu_flush函数
DEFINE(PROCINFO_INITFUNC, offsetof(struct
proc_info_list, __cpu_flush));
此时,一些特定寄存器的值如下所示:
r4 = pgtbl
(page table 的物理基地址)
r8 = machine info
(struct machine_desc的基地址)
r9 = cpu id
(通过cp15协处理器获得的cpu id)
r10 = procinfo
(struct proc_info_list的基地址)
在我们需要在开启mmu之前,做一些必须的工作:清除ICache, 清除 DCache, 清除 Writebuffer, 清除TLB等.这些一般是通过cp15协处理器来实现的,并且是平台相关的. 这就是 __cpu_flush 需要做的工作.
5、开启mmu
__enable_mmu
在进入 __enable_mmu 的时候, r0中已经存放了控制寄存器c1的一些配置(在上一步中进行的设置), 但是并没有真正的打开mmu,在 __enable_mmu 中,我们将打开mmu.此时,一些特定寄存器的值如下所示:
r0 = c1 parameters
(用来配置控制寄存器的参数)
r4 = pgtbl
(page table 的物理基地址)
r8 = machine info
(struct machine_desc的基地址)
r9 = cpu id
(通过cp15协处理器获得的cpu id)
r10 = procinfo
(struct proc_info_list的基地)
6、切换数据 __mmap_switched
最终通过调用__mmap_switched跳转到start_kernel
__mmap_switched:
adr r3, __switch_data + 4
ldm.w (r6, r7, r8), [r3]+
ldw sp, [r3]
mov fp, #0 @ Clear BSS (and zero fp)
203:
csub.a r6, r7
bea 204f
stw.w fp, [r6]+,#4
b 203b
204:
andn r1, r0, #CR_A @ Clear 'A' bit
stm (r0, r1), [r8]+ @ Save control register values
b start_kernel