最近porting linux kernel ,系统起不来,没有打印 搞了一两天,发现对kernel 启动调试已经很生疏了, 有点收获记录下来:
启动流程
首先是执行自解压,解压后重新跳转到0x40008000执行
arch\arm\kernel\head.s :
__HEAD
ENTRY(stext)
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
@ and irqs disabled
mrc p15, 0, r9, c0, c0 @ get processor id
bl __lookup_processor_type @ r5=procinfo r9=cpuid -->这里确定cpu type来决定 后面ROCINFO_INITFUNC 调用哪个初始化函数,4412为armv7
movs r10, r5 @ invalid processor (r5=0)?
THUMB( it eq ) @ force fixup-able long branch encoding
beq __error_p @ yes, error 'p'
#ifndef CONFIG_XIP_KERNEL
adr r3, 2f
ldmia r3, {r4, r8}
sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET)
add r8, r8, r4 @ PHYS_OFFSET
#else
ldr r8, =PLAT_PHYS_OFFSET
#endif
/*
* r1 = machine no, r2 = atags or dtb,
* r8 = phys_offset, r9 = cpuid, r10 = procinfo
*/
bl __vet_atags
#ifdef CONFIG_SMP_ON_UP
bl __fixup_smp
#endif
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
bl __fixup_pv_table
#endif
bl __create_page_tables
/*
* The following calls CPU specific code in a position independent
* manner. See arch/arm/mm/proc-*.S for details. r10 = base of
* xxx_proc_info structure selected by __lookup_processor_type
* above. On return, the CPU will be ready for the MMU to be
* turned on, and r0 will hold the CPU control register value.
*/
ldr r13, =__mmap_switched @ address to jump to after
@ mmu has been enabled
adr lr, BSYM(1f) @ return (PIC) address
mov r8, r4 @ set TTBR1 to swapper_pg_dir
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
THUMB( mov pc, r12 )
1: b __enable_mmu
ENDPROC(stext)
__enable_mmu 之后 pc会设置为 r13中保存的 __mmap_switched 地址执行,实现在 head-common.s
/*
* The following fragment of code is executed with the MMU on in MMU mode,
* and uses absolute addresses; this is not position independent.
*
* r0 = cp#15 control register
* r1 = machine ID
* r2 = atags/dtb pointer
* r9 = processor ID
*/
__INIT
__mmap_switched:
adr r3, __mmap_switched_data
ldmia r3!, {r4, r5, r6, r7}
cmp r4, r5 @ Copy data segment if needed
1: cmpne r5, r6
ldrne fp, [r4], #4
strne fp, [r5], #4
bne 1b
mov fp, #0 @ Clear BSS (and zero fp)
1: cmp r6, r7
strcc fp, [r6],#4
bcc 1b
ARM( ldmia r3, {r4, r5, r6, r7, sp})
THUMB( ldmia r3, {r4, r5, r6, r7} )
THUMB( ldr sp, [r3, #16] )
str r9, [r4] @ Save processor ID
str r1, [r5] @ Save machine type
str r2, [r6] @ Save atags pointer
bic r4, r0, #CR_A @ Clear 'A' bit
stmia r7, {r0, r4} @ Save control register values
b start_kernel
从此跳转到C代码
调试方法
如果在控制台初始化之前就死掉,需要JTAG或者 在汇编中添加代码定位
汇编中添加 b .
c代码中添加
__asm__(
"b .");
可以方便JTAG定位
同时可以load vmlinux : Data.LOAD.ELF &KERNEL_ROOT\vmlinux 0x40008000-0xc0008000;/nocode; ;
查看symbol来定位代码死在了哪里。
或者打开 CONFIG_DEBUG_LL 和 eraly_printk,不过这个功能需要借助debug-macro.s中的底层实现,如果实现有问题,也会引起死机。。我就是以为打开了这个死机,导致查了很久。。
如果start_kernel 执行过了,串口没有打印,系统还是死机。这时候问题可能比较多,cpu 相关设置 , pmic相关设置。
可以在arch\arm\mach-xxx.c 中吧 i2c resigister或者其他设备都去掉,排除设备驱动影响
用JTAG跟踪如果死在 inter cpu interrupt 或者其他 interrupt 可以查查trustzone hotlplug这些