|
既然跳到真正的kernel開始跑,表示進入重頭戲,在進入kernel之前arm的平台有一些預設的狀況,也就是說arm kernel image會預設目前的cpu和系統的狀況是在某個狀態,這樣對一個剛要跑起來的OS比較決定目前要怎麼boot起來。
( e0 b; u8 f5 N
( M% ]( ?5 z e可以看一下comment,有清楚的描述。這也幫助我們了解為什麼decompresser的程式跑完之後,還要把cache關掉。- 59 /* l0 Q4 |1 Z- y. @8 [1 W3 A
- 60 * Kernel startup entry point.
7 k9 f X+ }( y/ _6 { - 61 * ---------------------------
9 a6 w4 r8 ?' E$ ~9 r7 f J( } - 62 *
+ y( _( c; Q% u7 b4 q1 `& \ - 63 * This is normally called from the decompressor code. The requirements* T$ q, `1 g1 i5 ?( Z
- 64 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
, q: r$ m7 s5 X" ] - 65 * r1 = machine nr, r2 = atags pointer.
複製代碼 基於以上的假設,當program counter指到kernel的程式的時候,就會從line 80開始跑。" o4 P& [+ p" C# g! s1 E
line 80, msr指令會把, operand的值搬到cpsr_c裡面。這是用來確保arm cpu目前是跑在svc mode, irq&fiq都disable。(設成0x1就會disable,definition在./include/asm-arm/ptrace.h)
9 d- P5 K, g' {line 82, 讀取CPU ID到r9
$ f$ S1 ^$ [7 \+ i1 v0 q# b, rline 83, 跳到 __lookup_processor_type 執行(bl會記住返回位址)。- 77 .section ".text.head", "ax"
\! h1 i- O+ F - 78 .type stext, %function
- T, h! I; a9 N6 O5 ?" R - 79 ENTRY(stext)# Y# e7 g$ C$ A& y
- 80 msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode) t- k, b8 |9 |& ]
- 81 @ and irqs disabled7 R: b( ~. c; G8 q$ {
- 82 mrc p15, 0, r9, c0, c0 @ get processor id- K2 x4 u$ l( A5 b
- 83 bl __lookup_processor_type @ r5=procinfo r9=cpuid
複製代碼 接著會跳到head-common.S這個檔,
7 V- m. i6 ?/ R! i. H8 Iline 158, (3f表示forware往前找叫做『3』label)將label 3的address放到r3。; B+ n& h$ R; U0 U0 D6 C- v
line 159, 將r3指到的位址的資料,依序放到r7, r6, r5.(ldmda的da是要每次都位址減一次)
. {( k; Y" Y7 ~. G7 l Y' K2 H$ Lline l60, 161, 利用真實得到位址r3減去取得資料的位址得到一個offset值,這樣可計算出r5, r6真正應該要指到的地方。# l2 g+ P% q4 {% [; ~3 ?
line 163~169,這邊的程式應該不陌生,就是在各個CPU info裡面找尋對應的structure。找到的話就跳到line 171,返回head.S( A4 z$ W& N! K
line 170, 找不到的話,r5的processor id就放0x0.表示unknown id。, R9 m. \0 J1 c* b' A/ T% V+ D v
4 s3 N2 W8 a- s3 H
__proc_info_xxx可以在 vmlinux.lds.S 找到,是用來包住CPU info的所有data.資料則是被定義在./arch/arm/mm/proc-xxx.S,例如arm926就有 proc-arm926.S,裡面有相對應的data宣告,compiling time的時候,這些資料會被編譯到這個區段當中。- 156 .type __lookup_processor_type, %function
; D% p& @4 ~, r- E! \% e' ]( N - 157 __lookup_processor_type:! H8 t& O5 V* L, I0 j6 ?; n6 R
- 158 adr r3, 3f" N/ s6 ?' Z6 v! \7 v1 z
- 159 ldmda r3, {r5 - r7}
1 S/ N5 w. a4 a6 c, v# Y - 160 sub r3, r3, r7 @ get offset between virt&phys
; L, N7 U. D- E0 e9 @6 ~1 ` - 161 add r5, r5, r3 @ convert virt addresses to6 |, ?0 k1 Y7 i- d! h
- 162 add r6, r6, r3 @ physical address space* Q" E" V% R% ~8 ~ y7 V
- 163 1: ldmia r5, {r3, r4} @ value, mask8 r2 j9 K* X, N# r$ Y
- 164 and r4, r4, r9 @ mask wanted bits
9 q* d0 u& q Z( z+ q0 D - 165 teq r3, r4
0 w4 m/ l& R+ D( R - 166 beq 2f
) S& o G0 `: q- W6 h$ Z, h, r& y - 167 add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)! j" ^' D: g! d4 b4 u5 {
- 168 cmp r5, r6
. v( [' T/ i1 r - 169 blo 1b9 M% K, x/ v2 |% f* ^* V9 Y& X# A
- 170 mov r5, #0 @ unknown processor; I5 t4 U4 P& }; Q% W/ X- |
- 171 2: mov pc, lr9 Y, u/ G# [7 |1 Y
: Z5 E% A9 H- p8 W3 v0 Y) Z( B- 187 .long __proc_info_begin
, M: Y; b, N( O - 188 .long __proc_info_end6 `' W7 u" W- p# @
- 189 3: .long .
2 |6 H: r" _% s; Z4 n, }+ Q - 190 .long __arch_info_begin
( T% g; S+ w! u5 P) _+ C$ _, O - 191 .long __arch_info_end
複製代碼 跳了很多檔案,建議指令和object code如何link的概念要有,就會很清楚了。 |
|