新闻  |   论坛  |   博客  |   在线研讨会
armlinux演艺---第六回
tongxin | 2009-04-13 17:35:13    阅读:722   发布文章

查询到了处理器类型和系统的内存映像后就要进入初始化过程中比较关键的一步了,开始设置mmu,但首先要设置一个临时的内核页表,映射4m的内存,这在初始化过程中是足够了:
%A
%A //r5=0800 0000 ram起始地址 r6=0020 0000 io地址,r7=f020 0000 虚io
%A teq r7, #0 @ invalid architecture?
%A moveq r0, #‘a‘ @ yes, error ‘a‘
%A beq __error
%A bl __create_page_tables
%A
%A 其中__create_page_tables为:
%A __create_page_tables:
%A pgtbl r4
%A //r4=0800 4000 临时页表的起始地址
%A //r5=0800 0000, ram的起始地址
%A //r6=0020 0000, i/o寄存器空间的起始地址
%A //r7=0000 3c08
%A //r8=0000 0c1e
%A
%A //the page table in 0800 4000 is just temp base page, when init_task‘s sweaper_page_dir ready,
%A // the temp page will be useless
%A // the high 12 bit of virtual address is base table index, so we need 4kx4 = 16k temp base page,
%A
%A mov r0, r4
%A mov r3, #0
%A add r2, r0, #0x4000 @ 16k of page table
%A 1: str r3, [r0], #4 @ Clear page table
%A str r3, [r0], #4
%A str r3, [r0], #4
%A str r3, [r0], #4
%A teq r0, r2
%A bne 1b
%A /*
%A * Create identity mapping for first MB of kernel.
%A * This is marked cacheable and bufferable.
%A *
%A * The identity mapping will be removed by
%A */
%A
%A // 由于linux编译的地址是0xC0008000,load的地址是0x08008000,我们需要将虚地址0xC0008000映射到0800800一段
%A //同时,由于部分代码也要直接访问0x08008000,所以0x08008000对应的表项也要填充
%A // 页表中的表象为section,AP=11表示任何模式下可访问,domain为0。
%A add r3, r8, r5 @ mmuflags + start of RAM
%A //r3=0800 0c1e
%A add r0, r4, r5, lsr #18
%A //r0=0800 4200
%A str r3, [r0] @ identity mapping
%A //*0800 4200 = 0800 0c1e 0x200表象 对应的是0800 0000 的1m
%A /*
%A * Now setup the pagetables for our kernel direct
%A * mapped region. We round TEXTADDR down to the
%A * nearest megabyte boundary.
%A */
%A //下面是映射4M
%A
%A add r0, r4, #(TEXTADDR & 0xfff00000) >> 18 @ start of kernel
%A //r0 = r4+ 0x3000 = 0800 4000 + 3000 = 0800 7000
%A str r3, [r0], #4 @ PAGE_OFFSET + 0MB
%A //*0800 7004 = 0800 0c1e
%A add r3, r3, #1 << 20
%A //r3=0810 0c1e
%A str r3, [r0], #4 @ PAGE_OFFSET + 1MB
%A //*0800 7008 = 0810 0c1e
%A add r3, r3, #1 << 20
%A str r3, [r0], #4
%A //*0800 700c = 0820 0c1e @ PAGE_OFFSET + 2MB
%A add r3, r3, #1 << 20
%A str r3, [r0], #4 @ PAGE_OFFSET + 3MB
%A //*0800 7010 = 0830 0c1e
%A
%A bic r8, r8, #0x0c @ turn off cacheable
%A //r8=0000 0c12 @ and bufferable bits
%A mov pc, lr //子程序返回。
%A 下一回就要开始打开mmu的操作了
%A
%A 长篇连载--arm linux演艺---第七回
%A --------------------------------------------------------------------------------
%A
%A 上回书讲到已经设置好了内核的页表,然后要跳转到__arm920_setup,
%A 这个函数在arch/arm/mm/proc-arm929.s
%A
%A __arm920_setup:
%A mov r0, #0
%A mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4
%A mcr p15, 0, r0, c7, c10, 4@ drain write buffer on v4
%A mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4
%A mcr p15, 0, r4, c2, c0 @ load page table pointer
%A mov r0, #0x1f @ Domains 0, 1 = client
%A mcr p15, 0, r0, c3, c0 @ load domain access register
%A mrc p15, 0, r0, c1, c0 @ get control register v4
%A /*
%A * Clear out ‘unwanted‘ bits (then put them in if we need them)
%A */
%A @ VI ZFRS BLDP WCAM
%A bic r0, r0, #0x0e00
%A bic r0, r0, #0x0002
%A bic r0, r0, #0x000c
%A bic r0, r0, #0x1000 @ ...0 000. .... 000.
%A /*
%A * Turn on what we want
%A */
%A orr r0, r0, #0x0031
%A orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1
%A
%A #ifdef CONFIG_CPU_ARM920_D_CACHE_ON
%A orr r0, r0, #0x0004 @ .... .... .... .1..
%A #endif
%A #ifdef CONFIG_CPU_ARM920_I_CACHE_ON
%A orr r0, r0, #0x1000 @ ...1 .... .... ....
%A #endif
%A mov pc, lr
%A
%A 这一段首先关闭i,d cache,清除write buffer ,然后设置页目录地址,设置
%A domain的保护,在上节中,注意到页目录项的domain都是0,domain寄存器中
%A 的domain 0 对应的是0b11,表示访问模式为manager,不受限制。
%A
%A 接下来设置控制寄存器,打开d,i cache和mmu
%A 注意arm的d cache必须和mmu一起打开,而i cache可以单独打开
%A
%A 其实,cache和mmu的关系实在是紧密,每一个页表项都有标志标示是否是
%A cacheable的,可以说本来就是设计一起使用的
%A
%A 最后,自函数返回后,有一句
%A mcr p15, 0, r0, c1, c0
%A 使设置生效。
%A
%A%A
%A

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
最近文章
寂寞如雪
2009-05-19 19:01:18
夜色花
2009-05-19 18:56:22
没有爱可以重来
2009-05-19 18:54:59
推荐文章
最近访客