您的位置:首页 > 其它

Windows CE 6.0 启动过程分析(2)

2010-11-22 17:58 381 查看
3、KernelStart函数主要作用:
◆完成OEMAddressTable表中的物理地址到虚拟地址和虚拟地址到物理地址之间的映射;
◆对存储器页表和内核参数区存储空间(RAM或DRAM)进行清零处理。
◆读出CPU的ID号,内核需要根据该ID决定ARM的MMU处理,因为ARMV6和ARMV6之前的ARM处理器的MMU处理过程有所区别;
◆设置并开启MMU和Cache,因为在Startup函数关闭MMU和Cache;
◆设置ARM处理器工作模式的SP指针,ARM处理器共用7种不同的工作模式(USER、FIQ、IRQ、Supervisor、Abort、 Undefined、System),除用户模式(USER)和系统模式(System)之外,其他5种工作模式都有具有特定的SP指针寄存器(ARM处理器称其为影子寄存器);
◆读取内核启动所需要的KDataStruct结构体;
◆调用ARMInit函数重新定位Windows CE内核参数pTOC和初始化OEMInitGlobals全局变量;
◆利用mov pc, r12指令跳转到kernel.dll的入口位置,即NKStartup函数中。
$(_PRIVATEROOT)WINCEOS/COREOS/NK/LDR/ARM/armstart.s
LEAF_ENTRY KernelStart
mov r11, r0 ;(r11) = &OEMAddressTable (save pointer)
mov r1, r11 ;(r1) = &OEMAddressTable (2nd argument to VaFromPa)
bl VaFromPa
mov r6, r0 ;(r6) = VA of OEMAddressTable
; convert base of PTs to Physical address
ldr r4, =PTs ;(r4) = virtual address of FirstPT
mov r0, r4 ;(r0) = virtual address of FirstPT
mov r1, r11 ;(r1) = &OEMAddressTable (2nd argument to PaFromVa)
bl VaFromPa
mov r10, r0 ;(r10) = ptr to FirstPT (physical)
; Zero out page tables & kernel data page
mov r0, #0 ;(r0-r3) = 0''''s to store
mov r1, #0
mov r2, #0
mov r3, #0
mov r4, r10 ; (r4) = first address to clear
add r5, r10, #KDEnd-PTs ; (r5) = last address + 1
18 stmia r4!, {r0-r3}
stmia r4!, {r0-r3}
cmp r4, r5
blo %B18
; read the architecture information
bl GetCpuId
mov r5, r0 LSR #16 ; r5 >>= 16
and r5, r5, #0x0000000f ; r5 &= 0x0000000f == architecture id
add r4, r10, #HighPT-PTs ; (r4) = ptr to high page table
cmp r5, #ARMv6 ; v6 or later?
; ARMV6_MMU
orrge r0, r10, #PTL2_KRW + PTL2_SMALL_PAGE + ARMV6_MMU_PTL2_SMALL_XN
; (r0) = PTE for 4K, kr/w u-/- page, uncached unbuffered,
nonexecutable
; PRE ARMV6_MMU;
orrlt r0, r10, #PTL2_KRW + (PTL2_KRW << 2) + (PTL2_KRW << 4) + (PTL2_KRW << 6)
;Need to replicate AP bits into all 4 fields
orrlt r0, r0, #PTL2_SMALL_PAGE + PREARMV6_MMU_PTL2_SMALL_XN
;(r0) = PTE for 4K, kr/w u-/- page, uncached unbuffered,
nonexecutable
str r0,[r4, #0xD0*4] ;store the entry into 4 slots to map 16K of primary page table
add r0,r0, #0x1000 ;step on the physical address
str r0,[r4, #0xD1*4]
add r0,r0, #0x1000 ;step on the physical address
str r0,[r4, #0xD2*4]
add r0,r0, #0x1000 ;step on the physical address
str r0,[r4, #0xD3*4]
add r8,r10, #ExceptionVectors-PTs ;(r8) = ptr to vector page
orr r0,r8, #PTL2_SMALL_PAGE ;construct the PTE (C=B=0)
cmp r5,#ARMv6 ;v6 or later?
; ARMV6_MMU
orrge r0, r0, #PTL2_KRW
; PRE ARMV6_MMU
orrlt r0, r0, #PTL2_KRW + (PTL2_KRW << 2) + (PTL2_KRW << 4) + (PTL2_KRW << 6)
; Need to replicate AP bits into all 4 fields for pre-V6 MMU
str r0,[r4, #0xF0*4] ;store entry for exception stacks and vectors
;other 3 entries now unused
add r9,r10,#KPage-PTs ;(r9) = ptr to kdata page
orr r0,r9,#PTL2_SMALL_PAGE ;(r0)=PTE for 4K (C=B=0)
; ARMV6_MMU (condition codes still set)
orrge r0, r0, #PTL2_KRW_URO ; No subpage access control, so we must set this all to kr/w+ur/o
; PRE ARMV6_MMU
orrlt r0, r0, #(PTL2_KRW << 0) + (PTL2_KRW << 2) + (PTL2_KRW_URO << 4)
;(r0) = set perms kr/w kr/w kr/w+ur/o r/o
str r0, [r4, #0xFC*4] ;store entry for kernel data page
orr r0,r4, #PTL1_2Y_TABLE ;(r0) = 1st level PTE for high memory section
add r1, r10, #0x4000
str r0, [r1, #-4] ; store PTE in last slot of 1st level table
add r10, r10, #0x2000 ; (r10) = ptr to 1st PTE for "unmapped space"
mov r0, #PTL1_SECTION
orr r0, r0, #PTL1_KRW ;(r0)=PTE for 0: 1MB (C=B=0, kernel r/w)
20 mov r1, r11 ;(r1) = ptr to OEMAddressTable array (physical)
25 ldr r2,[r1],#4 ;(r2) = virtual address to map Bank at
ldr r3,[r1],#4 ;(r3) = physical address to map from
ldr r4,[r1],#4 ;(r4) = num MB to map
cmp r4,#0 ;End of table?
beq %F29
ldr r12, =0x1FF00000
and r2, r2, r12 ;VA needs 512MB, 1MB aligned.
ldr r12, =0xFFF00000
and r3, r3, r12 ;PA needs 4GB, 1MB aligned.
add r2, r10, r2, LSR #18
add r0, r0, r3 ;(r0) = PTE for next physical page
28 str r0, [r2],#4
add r0, r0, #0x00100000 ;(r0) = PTE for next physical page
sub r4, r4, #1 ;Decrement number of MB left
cmp r4, #0
bne %B28 ;Map next MB
bic r0, r0,#0xF0000000 ;Clear Section Base Address Field
bic r0, r0, #0x0FF00000 ;Clear Section Base Address Field
b %B25 ;Get next element
29
sub r10, r10, #0x2000 ;(r10) = restore address of 1st level page table
ldr r12, =0xFFF00000 ;(r12) = mask for section bits
and r1, pc, r12 ;physical address of where we are
;NOTE: we assume that the KernelStart function never spam
across 1M boundary.
orr r0, r1, #PTL1_SECTION
orr r0, r0, #PTL1_KRW ;(r0) = PTE for 1M for current physical address, C=B=0, kernel r/w
add r7, r10, r1, LSR #18 ;(r7) = 1st level PT entry for the identity map
ldr r8, [r7] ;(r8) = saved content of the 1st-level PT
str r0, [r7] ;create the identity map
mov r1, #1
mtc15 r1, c3 ;Setup access to domain 0 and clear other
mtc15 r10, c2 ;setup translation base (physical of 1st level PT)
mov r0, #0
mcr p15, 0, r0, c8, c7, 0 ;Flush the I&D TLBs
mfc15 r1, c1
orr r1, r1, #0x007F ;changed to read-mod-write for ARM920 Enable: MMU, Align, DCache, WriteBuffer
cmp r5, #ARMv6 ;r5 still set
; ARMV6_MMU
orrge r1, r1, #0x3000 ;vector adjust, ICache
orrge r1, r1, #1<<23 ;V6-format page tables
orrge r1, r1, #ARMV6_U_BIT ;V6-set U bit, let A bit control unalignment support
; PRE ARMV6_MMU
orrlt r1, r1, #0x3200 ;vector adjust, ICache, ROM protection
ldr r0, VirtualStart
cmp r0, #0 ;make sure no stall on "mov pc,r0" below
mtc15 r1, c1 ;enable the MMU & Caches
mov pc, r0 ;& jump to new virtual address
nop
VStart ldr r2, =FirstPT ;(r2) = VA of 1st level PT
sub r7, r7, r10 ;(r7) = offset into 1st-level PT
str r8, [r2, r7] ;restore the temporary identity map
mcr p15, 0, r0, c8, c7, 0 ;Flush the I&D TLBs
; setup stack for each modes: current mode = supervisor mode
ldr sp, =KStack
add r4, sp, #KData-KStack ;(r4) = ptr to KDataStruct
; setup ABORT stack
mov r1, #ABORT_MODE:OR:0xC0
msr cpsr_c, r1 ;switch to Abort Mode w/IRQs disabled
add sp, r4, #AbortStack-KData
; setup IRQ stack
mov r2, #IRQ_MODE:OR:0xC0
msr cpsr_c, r2 ;switch to IRQ Mode w/IRQs disabled
add sp, r4, #IntStack-KData
; setup FIQ stack
mov r3, #FIQ_MODE:OR:0xC0
msr cpsr_c, r3 ;switch to FIQ Mode w/IRQs disabled
add sp, r4, #FIQStack-KData
; setup UNDEF stack
mov r3, #UNDEF_MODE:OR:0xC0
msr cpsr_c, r3 ;switch to Undefined Mode w/IRQs disabled
mov sp, r4 ;(sp_undef) = &KData
; switch back to Supervisor mode
mov r0, #SVC_MODE:OR:0xC0
msr cpsr_c, r0 ;switch to Supervisor Mode w/IRQs disabled
ldr sp, =KStack
; continue initialization in C
add r0, sp, #KData-KStack ;(r0) = ptr to KDataStruct
str r6, [r0, #pAddrMap] ;store VA of OEMAddressTable in KData
bl ARMInit ;call C function to perform the rest of initializations
; upon return, (r0) = entry point of kernel.dll
mov r12, r0
ldr r0, =KData
mov pc, r12 ;jump to entry of kernel.dll
VirtualStart DCD VStart
ENTRY_END KernelStart
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: