head32.S 启动第一阶段 在arch/powerpc/kernel/下 head32.S 关键函数 1、early_init()早期初始化,清BBS 识别CPU 2、mmu_off 关闭MMU 汇编代码 3、reloc_offset() 4、relocate_kernel()->copy_and_flush 16M 5、turn_on_mmu打开MMU turn_on_mmu: mfmsr r0 ori r0,r0,MSR_DR|MSR_IR mtspr SPRN_SRR1,r0 lis r0,start_here@h ori r0,r0,start_here@l //调用start_here函数 mtspr SPRN_SRR0,r0 SYNC RFI //跳转到start_here 。。 /* * This is where the main kernel code starts. */ start_here: /* ptr to current */ lis r2,init_task@h ori r2,r2,init_task@l /* Set up for using our exception vectors */ /* ptr to phys current thread */ tophys(r4,r2) addi r4,r4,THREAD /* init task's THREAD */ CLR_TOP32(r4) mtspr SPRN_SPRG_THREAD,r4 li r3,0 mtspr SPRN_SPRG_RTAS,r3 /* 0 => not in RTAS */ /* stack */ lis r1,init_thread_union@ha addi r1,r1,init_thread_union@l li r0,0 stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1) /* * Do early platform-specific initialization, * and set up the MMU. */ mr r3,r31 mr r4,r30 bl machine_init //->probe_machine()-> bl __save_cpu_setup bl MMU_init //初始化mmu /* * Go back to running unmapped so we can load up new values * for SDR1 (hash table pointer) and the segment registers * and change to using our exception vectors. */ lis r4,2f@h ori r4,r4,2f@l tophys(r4,r4) li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR) FIX_SRR1(r3,r5) mtspr SPRN_SRR0,r4 mtspr SPRN_SRR1,r3 SYNC RFI /* Load up the kernel context */ 2: bl load_up_mmu #ifdef CONFIG_BDI_SWITCH /* Add helper information for the Abatron bdiGDB debugger. * We do this here because we know the mmu is disabled, and * will be enabled for real in just a few instructions. */ lis r5, abatron_pteptrs@h ori r5, r5, abatron_pteptrs@l stw r5, 0xf0(r0) /* This much match your Abatron config */ lis r6, swapper_pg_dir@h ori r6, r6, swapper_pg_dir@l tophys(r5, r5) stw r6, 0(r5) #endif /* CONFIG_BDI_SWITCH */ /* Now turn on the MMU for real! */ li r4,MSR_KERNEL FIX_SRR1(r4,r5) lis r3,start_kernel@h ori r3,r3,start_kernel@l mtspr SPRN_SRR0,r3 mtspr SPRN_SRR1,r4 SYNC RFI //调到start——kernel 第一阶段的硬件设置完成 ********************** void probe_machine(void) { extern struct machdep_calls __machine_desc_start; extern struct machdep_calls __machine_desc_end; /* * Iterate all ppc_md structures until we find the proper * one for the current machine type */ DBG("Probing machine type ...\n"); for (machine_id = &__machine_desc_start; machine_id < &__machine_desc_end; machine_id++) { DBG(" %s ...", machine_id->name); memcpy(&ppc_md, machine_id, sizeof(struct machdep_calls)); if (ppc_md.probe()) { DBG(" match !\n"); break; } DBG("\n"); } /* What can we do if we didn't find ? */ if (machine_id >= &__machine_desc_end) { DBG("No suitable machine found !\n"); for (;;); } printk(KERN_INFO "Using %s machine description\n", ppc_md.name); } /* __machine_desc_start, __machine_desc_end在vmlinux.lds.S文件中定义,系统编译完成后初始化这两个变量 */ ********************* __secondary_start start 到start_kernel 第二阶段 start_kernel 到kernel_thread函数创建init进程。 early init函数 bl early_init early_init函数主要功能是判断当前处理器系统使用的内核类型,并作出相应的初始操作。函数在/arch/powerpc/kernel/setup_32.c文件中定义 Linux Powerpc 从early_init 返回 之后调用mathine_init 定义同上。主要作用是1、分析OF Tree结构,获取当前内存使用情况,2、确定当前的处理器的PPC—md结构 |
|
来自: langhuayipian > 《powerpc》