您的位置 首页 IC

ARM Linux发动剖析headarmv.S内情

__create_page_tables:pgtblr4,r5@pagetableaddress/*Clearthe16Klevel1swapperpagetable*/movr0…

__create_page_tables:
pgtbl r4, r5 @ page table address

/* Clear the 16K level 1 swapper page table */
mov r0, r4
mov r3, #0
add r2, r0, #0x4000
1: str r3, [r0], #4
str r3, [r0], #4
str r3, [r0], #4
str r3, [r0], #4
teq r0, r2
bne 1b

/*
* Create identity mapping for first MB of kernel to
* cater for the MMU enable.This identity mapping
* will be removed by paging_init()
*/
krnladrr2, r4, r5 @ start of kernel
add r3, r8, r2 @ flags + kernel base
str r3, [r4, r2, lsr #18] @ identity mapping

/*
* Now setup the pagetables for our kernel direct
* mapped region.We round TEXTADDR down to the
* nearest megabyte boundary.
*/
add r0, r4, #(TEXTADDR & 0xff000000) >> 18 @ start of kernel
bic r2, r3, #0x00f00000
str r2, [r0] @ PAGE_OFFSET + 0MB
add r0, r0, #(TEXTADDR & 0x00f00000) >> 18
str r3, [r0], #4 @ KERNEL + 0MB
add r3, r3, #1 << 20
str r3, [r0], #4 @ KERNEL + 1MB
add r3, r3, #1 << 20
str r3, [r0], #4 @ KERNEL + 2MB
add r3, r3, #1 << 20
str r3, [r0], #4 @ KERNEL + 3MB

/*
* Ensure that the first section of RAM is present.
* we assume that:
*1. the RAM is aligned to a 32MB boundary
*2. the kernel is executing in the same 32MB chunk
* as the start of RAM.
*/
bic r0, r0, #0x01f00000 >> 18 @ round down
and r2, r5, #0xfe000000 @ round down
add r3, r8, r2 @ flags + rambase
str r3, [r0]

bic r8, r8, #0x0c @ turn off cacheable
@ and bufferable bits
代码创立页表目录。首要清空从0xA0004000开端的16K页表项。然后,为了能够拜访从0xA0000000开端的内核的1M空间,将该地址对应的页表项赋值。接着映射从TEXTADDR开端的4M的虚拟地址空间,这需求4个页表项。最终,因为SDRAM开端的榜首MB的空间寄存有启动时的一些参数,所以也需求映射。在这里,该映射和前面的虚拟地址的映射在地址上是持平的。

在创立页表目录完成后,代码经过前面主程序的最终一句addpc, r10, #12跳转到实践的CPU的设置子程序__xscale_setup。
__xscale_setup:
mov r0, #F_BIT|I_BIT|SVC_MODE
msr cpsr_c, r0
mcr p15, 0, ip, c7, c7, 0@ invalidate I, D caches & BTB
mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
mov r0, #0x1f @ Domains 0, 1 = client
mcr p15, 0, r0, c3, c0, 0@ load domain access register
mov r0, #1 @ Allow user space to access
mcr p15, 0, r0, c15, c1, 0 @ … CP 0 only.
#if CACHE_WRITE_THROUGH
mov r0, #0x20
#else
Mov r0, #0x00
#endif
mcr p15, 0, r0, c1, c1, 0 @ set auxiliary control reg
mrc p15, 0, r0, c1, c0, 0 @ get control register
bic r0, r0, #0x0200 @ ……R………
bic r0, r0, #0x0082 @ ……..B…..A.
orr r0, r0, #0x0005 @ ………….C.M
orr r0, r0, #0x3900 @ ..VIZ..S……..
#ifdef CONFIG_XSCALE_CACHE_ERRATA
bic r0, r0, #0x0004 @ see cpu_xscale_proc_init
#endif
mov pc, lr
主要是操作协处理器,设置页表目录项基地址,对CACHE和BUFFER的操控位进行一些操作。详细咱们能够看看介绍ARM编程的书。

.type__switch_data, %object
__switch_data:.long__mmap_switched
.long SYMBOL_NAME(__bss_start)
.long SYMBOL_NAME(_end)
.long SYMBOL_NAME(processor_id)
.long SYMBOL_NAME(__machine_arch_type)
.long SYMBOL_NAME(cr_alignment)
.long SYMBOL_NAME(init_task_union)+8192

.type __ret, %function
__ret: ldr lr, __switch_data
mcr p15, 0, r0, c1, c0
mov r0, r0
mov r0, r0
mov r0, r0
mov pc, lr

.align 5
__mmap_switched:
adr r3, __switch_data + 4
ldmia r3, {r4, r5, r6, r7, r8, sp}@ r2 = compat
@ sp = stack pointer

mov fp, #0 @ Clear BSS (and zero fp)
1: cmp r4, r5
strcc fp, [r4],#4
bcc 1b

str r9, [r6] @ Save processor ID
str r1, [r7] @ Save machine type
#ifdef CONFIG_ALIGNMENT_TRAP
orr r0, r0, #2 @ ………..A.
#endif
bic r2, r0, #2 @ Clear A bit
stmia r8, {r0, r2} @ Save control register values
bSYMBOL_NAME(start_kernel)
最终这段代码的效果主要是在进入C函数前先做一些变量的初始化和保存作业。首要清空BSS区域,然后保存处理器ID和机器类型到各自变量地址,接着保存cr_alignment,最终跳转到init/main.c中的start_kernel函数运转。

以上介绍的是head-armv.S文件的主要内容和功用,它是linux运转的榜首个文件,具有非常重要的含义。很好的阅览该文件,关于咱们了解ARM处理器的作业方式有很大的协助。一起,在许多linux体系的移植作业中,往往需求对该文件透彻的了解。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/277158.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部