内核最终目的:运行根文件系统的应用程序
内核做的事情:
处理uboot传入的参数
代码语言:javascript
复制archarmkernel
/*启动内核:bi_arch_number机器ID。参数存放的地址 bd->bi_boot_params*/
theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
判断是否支持单板(根据启动内核时传入的机器ID)
代码语言:javascript
复制/**/
ENTRY(stext)
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
@ and irqs disabled
mrc p15, 0, r9, c0, c0 @ get processor id
/*支持的处理器类型*/
bl __lookup_processor_type @ r5=procinfo r9=cpuid
movs r10, r5 @ invalid processor (r5=0)?
beq __error_p @ yes, error 'p'
bl __lookup_machine_type @ r5=machinfo
movs r8, r5 @ invalid machine (r5=0)?
beq __error_a @ yes, error 'a'
bl __create_page_tables
__lookup_machine_type:
adr r3, 3b @ r3=3b的地址,物理地址
/* 链接脚本
__arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;
*/
ldmia r3, {r4, r5, r6}@ r4=“.”(.代表3b的虚拟地址) r5=__arch_info_begin r6=__arch_info_end
sub r3, r3, r4 @ get offset between virt&phys 虚拟地址物理地址的偏差
add r5, r5, r3 @ convert virt addresses to
add r6, r6, r3 @ physical address space
1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type
teq r3, r1 @ matches loader number? 机器ID
beq 2f @ found
add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
cmp r5, r6
blo 1b
mov r5, #0 @ unknown machine
2: mov pc, lr
/*linux-2.6.22.6linux-2.6.22.6includeasm-armmacharch.h*/
/*定义两个结构体,把段强制设置成.arch.info.init*/
#define MACHINE_START(_type,_name)
static const struct machine_desc __mach_desc_##_type
__used
__attribute__((__section__(".arch.info.init"))) = {
.nr = MACH_TYPE_##_type,
.name = _name,
/*linux-2.6.22.6linux-2.6.22.6archarmmach-s3c2440Mach-smdk2440.c*/
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks <ben@fluff.org> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
创建页表
代码语言:javascript
复制 bl __create_page_tables
使能MMU
代码语言:javascript
复制 adr r4, __secondary_data
ldmia r4, {r5, r7, r13} @ address to jump to after
sub r4, r4, r5 @ mmu has been enabled
ldr r4, [r7, r4] @ get secondary_data.pgdir
adr lr, __enable_mmu @ return address
add pc, r10, #PROCINFO_INITFUNC @ initialise processor
@ (return control reg)
跳转到start kernel(内核的第一个C函数,处理启动参数)
代码语言:javascript
复制b start_kernel
main.c(init)
代码语言:javascript
复制/*启动流程
start_kernel
setup_arch 解析UBOOT传入的启动参数
setup_command_line 解析UBOOT传入的启动参数
parse_early_param
do_early_para
从_setup_start到_setup_end,调用early函数
unknown_bootoption
obsolete_checksetup
从_setup_start到_setup_end,调用early函数
rest_init
kernel_init
prepare_namespace
mount_root 挂载根文件系统
init_post 执行应用程序
*/
char * command_line;
extern struct kernel_param __start___param[], __stop___param[];
smp_setup_processor_id();
/*
* Need to run as early as possible, to initialize the
* lockdep hash:
*/
unwind_init();
lockdep_init();
local_irq_disable();
early_boot_irqs_off();
early_init_irq_lock_class();
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
lock_kernel();
tick_init();
boot_cpu_init();
page_address_init();
printk(KERN_NOTICE);
printk(linux_banner);
setup_arch(&command_line);
setup_command_line(command_line);
unwind_setup();
setup_per_cpu_areas();
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
/*
* Set up the scheduler prior starting any interrupts (such as the
* timer interrupt). Full topology setup happens at smp_init()
* time - but meanwhile we still have a functioning scheduler.
*/
sched_init();
/*
* Disable preemption - early bootup scheduling is extremely
* fragile until we cpu_idle() for the first time.
*/
preempt_disable();
build_all_zonelists();
page_alloc_init();
printk(KERN_NOTICE "Kernel command line: %sn", boot_command_line);
parse_early_param();
parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
&unknown_bootoption);
if (!irqs_disabled()) {
printk(KERN_WARNING "start_kernel(): bug: interrupts were "
"enabled *very* early, fixing itn");
local_irq_disable();
}
sort_main_extable();
trap_init();
rcu_init();
init_IRQ();
pidhash_init();
init_timers();
hrtimers_init();
softirq_init();
timekeeping_init();
time_init();
profile_init();
if (!irqs_disabled())
printk("start_kernel(): bug: interrupts were enabled earlyn");
early_boot_irqs_on();
local_irq_enable();