随笔-118  评论-133  文章-4  trackbacks-0
注:
    原文出自taoyuetao大侠的博客上:
http://www.eetop.cn/blog/html/45/11145_itemid_1746.html
    小弟参考之研究s3c2410相关代码,然后做了稍微的修改,作为一个学习笔记,方便以后的学习,也希望对后人有所帮助^_^

函数__create_page_tables介绍:

假设内核起始物理地址是0x30008000,虚拟地址是0xC0008000,下面的代码是建立内核起始处4MB空间的映射,
采用了一级映射方式,即段式(section)映射方式,每段映射范围为1MB空间。于是需要建立4个表项,实现:
虚拟地址0xC0000000~0xC0300000,映射到物理地址0x30000000~0x30300000


     .macro  pgtbl, reg, rambase
     adr \reg, stext
     sub \reg, \reg, #0x4000    
     .endm
    
     .macro  krnladr, rd, pgtable, rambase
     bic \rd, \pgtable, #0x000ff000
     .endm
    
/*

 * Setup the initial page tables.  We only setup the barest

 * amount which are required to get the kernel running, which

 * generally means mapping in the kernel code.

 *

 * r8  = machinfo

 * r9  = cpuid

 * r10 = procinfo

 *

 * Returns:

 *  r0, r3, r5, r6, r7 corrupted

 *  r4 = physical page table address

 */

    .type   __create_page_tables, %function

__create_page_tables:

    ldr r5, [r8, #MACHINFO_PHYSRAM] @ physram   r5=0x30000000

    pgtbl   r4, r5              @ page table address    r4=0x30004000

 

    /*

     * Clear the 16K level 1 swapper page table

     */

    mov r0, r4

    mov r3, #0

    add r6, r0, #0x4000

1:  str r3, [r0], #4

    str r3, [r0], #4

    str r3, [r0], #4

    str r3, [r0], #4

    teq r0, r6

    bne 1b

 

    ldr r7, [r10, #PROCINFO_MMUFLAGS]   @ mmuflags         //r7=0x00000c1e

    /*

*  r7用于设置第一级表描述符之用:

     *      AP          :11(读/写权限)

     *                :0000

     *      C           : 1(高速缓存)

     *      B           : 1 (缓冲)

     *      bit[1 0]    :10(标识此为节描述符)

    */

    /*

     * Create identity mapping for first MB of kernel to

     * cater for the MMU enable.  This identity mapping

     * will be removed by paging_init().  We use our current program

     * counter to determine corresponding section base address.

     *

* 为以后MMU的开启准备好内存头1M空间的转换表,

* 采用平板地址映射模式(表索引==节基址)

*/

    mov r6, pc, lsr #20         @ start of kernel section      //r6=0x00000300

    orr r3, r7, r6, lsl #20     @ flags + kernel base          //r3=0x30000c1e

    str r3, [r4, r6, lsl #2]    @ identity mapping  //[0x30004c00]=0x30000c1e

/*  结果:

*  虚拟地址        物理地址

*  0x300000000     0x30000000

    /*

     * Now setup the pagetables for our kernel direct

     * mapped region.  We round TEXTADDR down to the

     * nearest megabyte boundary.  It is assumed that

     * the kernel fits within 4 contigous 1MB sections.

     *

*为内核占用的头4M地址准备好转换表(在这采用的就不是平板地址映射模式了)

/

    add r0, r4,  #(TEXTADDR & 0xff000000) >> 18                 //ro=0x30007000

    str r3, [r0, #(TEXTADDR & 0x00f00000) >> 18]!       @ KERNEL + 0MB

    add r3, r3, #1 << 20                                        //r3=0x30100c1e

    str r3, [r0, #4]!                                   @ KERNEL + 1MB

    add r3, r3, #1 << 20                                        //r3=0x30200c1e

    str r3, [r0, #4]!                                   @ KERNEL + 2MB

    add r3, r3, #1 << 20                                        //0x30300c1e

    str r3, [r0, #4]                                    @ KERNEL + 3MB

    /*

     *  结果:

     *  虚拟地址        物理地址

              0xc0000000           0x30000000

              0xc0100000           0x30100000

              0xc0200000           0x30200000

              0xc0300000           0x30300000

       */

   

    /*

     * Then map first 1MB of ram in case it contains our boot params.

     *

*  映射sdram的头1M以防boot params需要(不是已经映射过了吗?)

*/

    add r0, r4, #VIRT_OFFSET >> 18                              //r0=0x30007000

    orr r6, r5, r7                                              //r6=0x30000c1e

    str r6, [r0]                                       //[0x30007000]=0x3000c1e

 

#ifdef CONFIG_XIP_KERNEL

    /*

     * Map some ram to cover our .data and .bss areas.

     * Mapping 3MB should be plenty.

     */

    sub r3, r4, r5

    mov r3, r3, lsr #20

    add r0, r0, r3, lsl #2

    add r6, r6, r3, lsl #20

    str r6, [r0], #4

    add r6, r6, #(1 << 20)

    str r6, [r0], #4

    add r6, r6, #(1 << 20)

    str r6, [r0]

#endif

 

#ifdef CONFIG_DEBUG_LL

    bic r7, r7, #0x0c           @ turn off cacheable

                        @ and bufferable bits

    /*

     * Map in IO space for serial debugging.

     * This allows debug messages to be output

     * via a serial console before paging_init.

     */

    ldr r3, [r8, #MACHINFO_PGOFFIO]

    add r0, r4, r3

    rsb r3, r3, #0x4000         @ PTRS_PER_PGD*sizeof(long)

    cmp r3, #0x0800         @ limit to 512MB

    movhi   r3, #0x0800

    add r6, r0, r3

    ldr r3, [r8, #MACHINFO_PHYSIO]

    orr r3, r3, r7

1:  str r3, [r0], #4

    add r3, r3, #1 << 20

    teq r0, r6

    bne 1b

#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)

    /*

     * If we're using the NetWinder, we need to map in

     * the 16550-type serial port for the debug messages

     */

    teq r1, #MACH_TYPE_NETWINDER

    teqne   r1, #MACH_TYPE_CATS

    bne 1f

    add r0, r4, #0xff000000 >> 18

    orr r3, r7, #0x7c000000

    str r3, [r0]

1:

#endif

#ifdef CONFIG_ARCH_RPC

    /*

     * Map in screen at 0x02000000 & SCREEN2_BASE

     * Similar reasons here - for debug.  This is

     * only for Acorn RiscPC architectures.

     */

    add r0, r4, #0x02000000 >> 18

    orr r3, r7, #0x02000000

    str r3, [r0]

    add r0, r4, #0xd8000000 >> 18

    str r3, [r0]

#endif

#endif

    mov pc, lr


posted on 2007-08-02 12:09 lfc 阅读(1770) 评论(0)  编辑 收藏 引用
只有注册用户登录后才能发表评论。