用模擬器解決Linux核心載入問題
快樂蝦
歡迎轉載,但請保留作者資訊
在使用合眾達DVS6467T開發板時遇到一個問題,在核心選項中加上initramfs的支援,結果在bootm時核心載入失敗:
## Booting image at 8e000000 ...
Image Name:Linux-2.6.10_mvl401-davinci_evm-
Image Type:ARM Linux Kernel Image (uncompressed)
Data Size:3479208 Bytes =3.3 MB
Load Address: 80008000
Entry Point:80008000
Verifying Checksum ... OK
OK
Starting kernel ...
UncompressingLinux..........................................................................................................................................................done, booting the kernel.
然後就沒有下文了。
這種情況其實在剛開始除錯核心時經常會遇到,通常也只能通過核心功能的新增和刪除來初步判斷問題的位置。但我們現在有模擬器這個神器,就不再需要這麼摸索了。
下面有請模擬器大神上場。
首先啟動uboot並將核心tftp到板上。Bootm後出現上文所提的現象。
在ccs下用模擬器連線裝置:很顯然pc跑飛了,但此時已經無法得到更多資訊了。
再來一次。
用uboot將核心tftp下載到裝置上,在bootm之前用ccs連線到裝置,此時ccs將在uboot的程式碼中中斷下來:
新增兩個斷點:
因為0x80008000這個地址是Linux核心的入口地址。
在ccs中繼續執行,uboot繼續工作,我們也可以通過串列埠和uboot
在串列埠中輸入bootm,此時模擬器將在核心入口處中斷下來:
通過單步執行,很容易發現程式跑飛的位置:
/*
* The following fragment of code is executedwith the MMU on, and uses
* absolute addresses; this is not positionindependent.
*
*r0= cp#15 control register
*r1= machine ID
*r9= processor ID
*/
.type__mmap_switched, %function
__mmap_switched:
adrr3,__switch_data + 4
ldmiar3!,{r4, r5, r6, r7}
cmpr4,r5@ Copy data segment if needed
1:cmpner5,r6
ldrnefp,[r4], #4
strnefp,[r5], #4
bne1b
movfp,#0@ Clear BSS (and zero fp)
1:cmpr6,r7
strccfp,[r6],#4
bcc1b
在這裡清除BSS段時程式飛了。通過檢查各暫存器的值感覺並沒有什麼異常,但當核心執行到這裡時,可以發現mmu已經啟用了,那麼問題估計和這個有關了。
看看之前執行的MMU相關的一段程式碼:
/*
* Setup the initial page tables.We only setup the barest
* amount which are required to get the kernelrunning, which
* generally means mapping in the kernel code.
*
* r8=machinfo
* r9=cpuid
* r10 = procinfo
*
* Returns:
*r0,r3, r5, r6, r7 corrupted
*r4 =physical page table address
*/
.type__create_page_tables, %function
__create_page_tables:
ldrr5,[r8, #MACHINFO_PHYSRAM]@ physram
pgtblr4,r5@ page table address
………..
/*
* Nowsetup the pagetables for our kernel direct
*mapped region.We round TEXTADDR down tothe
*nearest megabyte boundary.It is assumedthat
* thekernel fits within 4 contigous 1MB sections.
*/
addr0,r4,#(TEXTADDR & 0xff000000)>> 18@ start of kernel
strr3,[r0, #(TEXTADDR & 0x00f00000) >> 18]!
addr3,r3, #1 << 20
strr3,[r0, #4]!@ KERNEL + 1MB
addr3,r3, #1 << 20
strr3,[r0, #4]!@ KERNEL + 2MB
addr3,r3, #1 << 20
strr3,[r0, #4]@ KERNEL + 3MB
……
很顯然這裡只配置了核心程式碼開始的3M空間,而我們的核心在加上initramfs之後,bss段的一部分資料是處於3M之外的,這也是正是核心跑飛的原因!!
知道原因就好辦了,修改下這段程式碼:
/*
* Nowsetup the pagetables for our kernel direct
*mapped region.
*/
addr0,r4,#(TEXTADDR & 0xff000000)>> 18
strr3,[r0, #(TEXTADDR & 0x00f00000) >> 18]!
ldrr6,=(TEXTADDR + 0x01000000 - 1)
addr0,r0, #4
addr6,r4, r6, lsr #18
1:cmpr0,r6
addr3,r3, #1 << 20
strlsr3,[r0], #4
bls1b
再編譯執行,搞定!!