|
既然跳到真正的kernel開始跑,表示進入重頭戲,在進入kernel之前arm的平台有一些預設的狀況,也就是說arm kernel image會預設目前的cpu和系統的狀況是在某個狀態,這樣對一個剛要跑起來的OS比較決定目前要怎麼boot起來。9 F% K9 F: J+ z- w
# R" q" k. Z' S+ c" [+ V$ {! e
可以看一下comment,有清楚的描述。這也幫助我們了解為什麼decompresser的程式跑完之後,還要把cache關掉。- 59 /*
# k3 z. e0 X' C2 @3 A6 q - 60 * Kernel startup entry point.
+ i& B5 _3 N2 o0 ~8 N7 ^/ ~ - 61 * ---------------------------
# m1 @) P& m, D' Q( Q - 62 *
- b" n7 j1 [9 z0 f; F4 I5 h - 63 * This is normally called from the decompressor code. The requirements
6 }2 P% M, R. Q c - 64 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
+ [" R6 o$ Z& Y- O6 p0 n/ f6 V - 65 * r1 = machine nr, r2 = atags pointer.
複製代碼 基於以上的假設,當program counter指到kernel的程式的時候,就會從line 80開始跑。
9 H. P0 P$ |* H4 S7 X4 F; wline 80, msr指令會把, operand的值搬到cpsr_c裡面。這是用來確保arm cpu目前是跑在svc mode, irq&fiq都disable。(設成0x1就會disable,definition在./include/asm-arm/ptrace.h)
( X& }- B. @) k9 yline 82, 讀取CPU ID到r9
" \, g) ?: b' vline 83, 跳到 __lookup_processor_type 執行(bl會記住返回位址)。- 77 .section ".text.head", "ax"
8 @( E: u9 g( D - 78 .type stext, %function/ c' y( I' z" V: B6 }
- 79 ENTRY(stext): L% t) s. a# n: \* G
- 80 msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
- y- ] d8 S, Q" C' `/ G) z0 y. e - 81 @ and irqs disabled! [& w! c! f3 P/ M# V2 b; ?
- 82 mrc p15, 0, r9, c0, c0 @ get processor id7 C& Z0 G/ K1 q' G
- 83 bl __lookup_processor_type @ r5=procinfo r9=cpuid
複製代碼 接著會跳到head-common.S這個檔,4 Y$ b- x# D8 y# K
line 158, (3f表示forware往前找叫做『3』label)將label 3的address放到r3。1 J7 \9 V% E$ p3 g
line 159, 將r3指到的位址的資料,依序放到r7, r6, r5.(ldmda的da是要每次都位址減一次)
z3 w8 ?* A2 v) K, d% |0 sline l60, 161, 利用真實得到位址r3減去取得資料的位址得到一個offset值,這樣可計算出r5, r6真正應該要指到的地方。4 `3 K: C7 b& U* {# O A8 p
line 163~169,這邊的程式應該不陌生,就是在各個CPU info裡面找尋對應的structure。找到的話就跳到line 171,返回head.S
! H1 g" x2 V2 S$ O" `4 R6 A3 dline 170, 找不到的話,r5的processor id就放0x0.表示unknown id。0 n! S/ B- d9 e Y3 \
9 h' n' v+ s+ w Z
__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
2 ~6 w8 H$ L/ f7 X5 @ - 157 __lookup_processor_type:
3 N! S, E: }1 B( T& N - 158 adr r3, 3f$ |4 u6 w) v* i2 C7 J
- 159 ldmda r3, {r5 - r7}
0 s" t1 f8 A+ [ _" ~ a( X - 160 sub r3, r3, r7 @ get offset between virt&phys
6 h7 L8 T. n; k" [, q1 w - 161 add r5, r5, r3 @ convert virt addresses to
# E z9 |: D6 e K" k6 G - 162 add r6, r6, r3 @ physical address space3 @8 x3 u: Y4 _, Y0 W
- 163 1: ldmia r5, {r3, r4} @ value, mask
/ o4 d7 Q" t- P- x2 y3 q# D1 \ - 164 and r4, r4, r9 @ mask wanted bits
# @9 s6 H. t+ h: H) m6 ` - 165 teq r3, r4, B# E4 ?+ L9 y& r7 [- q
- 166 beq 2f7 Z0 j! |) q$ u/ @5 H a
- 167 add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
1 L6 Z* Q: j. C. h* z - 168 cmp r5, r6. j5 V a6 L# p+ Q0 A. t7 l6 ?
- 169 blo 1b
V9 B" b& e. ?) Q0 C: \+ c - 170 mov r5, #0 @ unknown processor! R9 v1 D$ v$ F- l: B
- 171 2: mov pc, lr+ e( C B- j# \! V
. O: L, L7 C6 l1 a. L- 187 .long __proc_info_begin
6 w# I8 z' F/ j3 F5 V! u8 Q - 188 .long __proc_info_end7 \: o* k: l, S# B% Y1 P0 Q6 r% F
- 189 3: .long ./ D+ b/ ]: w1 {9 I( @: i
- 190 .long __arch_info_begin, o; b* O' T4 Q; i) g
- 191 .long __arch_info_end
複製代碼 跳了很多檔案,建議指令和object code如何link的概念要有,就會很清楚了。 |
|