zoukankan      html  css  js  c++  java
  • S5PV210 uboot中的 MMU代码分析

    1:经过上一节的分析,如果采用SECTION虚拟地址映射的话;

    程序员只需要做的事情:

    (1) 建立转换表,Tanslation Table;

    (2) 将TTB(转换表基地址Tanslation Table Base)写入协处理器CP15的C2寄存器,这里要注意转换表

    基地址为16K对齐的(因为4096*32bit=16K)所以TTB的bit0-bit13为0。

    (3) 使能MMU,将CP15的C1寄存器0bit写1;

    (4) 设置域的访问权限;设置C3寄存器;

    CPU/MMU做的事情:

    (1) CPU核心看到和用到的只是虚拟地址VA,至于VA如果去对应物理地址PA,CPU核心不理会,MVA是除CPU核心

    外的其他部分看到的虚拟地址,VA与MVA的变化关系,如果VA<32M,需要使用进程标识号PID(通过读CP15的C13获得)

    来转换为MVA

     
    if (VA  < 32M) then
            MVA = VA | (PID << 25)
    else
            MVA = VA

    (2) MMU做的事情,将MVA的bit20-bit31与TTB的bit14-bit31组合,通过这个值来查找转换表中的物理地址所在位置,

    找到物理地址所在内存位置,即把所在位置的bit20-bit31与MVA的bit19-bit0,这个地址即为PA(物理地址)。

     2:uboot中代码分析

    s5pv210虚拟地址物理地址映射关系为:

    虚拟地址:---------------------------------------------物理地址----------------------------写入权限

    0x0000_0000--0x0FFF_FFFF       0x0000_0000--0x1000_0000          不可写入

    0x1000_0000--0x1FFF_FFFF             无效

    0x2000_0000--0x5FFF_FFFF        0x2000_0000--0x5FFF_FFFF          WT、WB

    0x6000_0000--0x7FFF_FFFF            无效

    0x8000_0000--0xaFFF_FFFF         0x8000_0000--0xAFFF_FFFF        不可写入

    0xb000_0000--0xbFFF_FFFF         0xb000_0000--0xbFFF_FFFF        不可写入

    0xc000_0000--0xcFFF_FFFF         0x2000_0000--0x2FFF_FFFF         WT、WB

    0xD00 - 0xC80                    无效

    0x1000 - 0xD00                0x1000 - 0xD00              不可写入

    #if defined(CONFIG_ENABLE_MMU)
    _mmu_table_base:
        .word mmu_table
    #endif
    
    
    #if defined(CONFIG_ENABLE_MMU)
    enable_mmu:
        /* enable domain access */
        ldr    r5, =0x0000ffff                //设置域权限:设置16个域权限位可读可写,在写入C3寄存器
        mcr    p15, 0, r5, c3, c0, 0        @load domain access register
    
        /* Set the TTB register */
        ldr    r0, _mmu_table_base            //把内存_mmu_table_base中的值写入到r0中,从最上面三行代码可以看出_mmu_table_base中的值为mmu_table
        ldr    r1, =CFG_PHY_UBOOT_BASE        //mmu_table定义在lowlevel_init函数中,mmu_table即为在SRAM中的向量表的地址,BL1中把整个uboot的代码
        ldr    r2, =0xfff00000                //复制到0x23e0_0000内存处,所以在内存中的向量表的地址为:0x23e0_0000+mmu_table的值
        bic    r0, r0, r2                    //清mmu_table的高12bit,在位或0x23e0_0000,即把内存中的向量表的地址计算出来赋值给r1了,
        orr    r1, r0, r1                    //然后把r1写入到寄存器c2中,则完成了TTB的设置。
        mcr    p15, 0, r1, c2, c0, 0
    
        /* Enable the MMU */
    mmu_on:
        mrc    p15, 0, r0, c1, c0, 0        //使能mmu,c3的M位置1,即使能mmu
        orr    r0, r0, #1
        mcr    p15, 0, r0, c1, c0, 0
        nop
        nop
        nop
        nop
    #endif
    
    /*这段代码的位于lowlevel_init中,作用就是建立TTB*/
        .globl lowlevel_init
    lowlevel_init:
        #ifdef CONFIG_MCP_SINGLE
        /*
         * MMU Table for SMDKC110
         * 0x0000_0000 -- 0xBFFF_FFFF => Not Allowed
         * 0xB000_0000 -- 0xB7FF_FFFF => A:0xB000_0000 -- 0xB7FF_FFFF
         * 0xC000_0000 -- 0xC7FF_FFFF => A:0x3000_0000 -- 0x37FF_FFFF
         * 0xC800_0000 -- 0xDFFF_FFFF => Not Allowed
         * 0xE000_0000 -- 0xFFFF_FFFF => A:0xE000_0000 -- 0XFFFF_FFFF
         */
    
            /* form a first-level section entry */
        .macro FL_SECTION_ENTRY base,ap,d,c,b
            .word (base << 20) | (ap << 10) | 
                  (d << 5) | (1<<4) | (c << 3) | ( << 2) | (1<<1)
        .endm
        .section .mmudata, "a"
            .align 14
            // the following alignment creates the mmu table at address 0x4000.
            .globl mmu_table
        mmu_table:
            .set __base,0                            //开始设置MMU table base。
            // Access for iRAM
            .rept 0x100                                //TTB中一共有4096个字节,我们假设这是一个数组 unsigned int TTB[1096]
            FL_SECTION_ENTRY __base,3,0,0,0            //rept 0x100 意思是循环256次,即 TTB[0] = FL_SECTION_ENTRY __base,3,0,0,0    
            .set __base,__base+1                    //TTB[1] = FL_SECTION_ENTRY __base+1,3,0,0,0 ----------最后TTB[0x100] =  FL_SECTION_ENTRY __base+99,3,0,0,0
            .endr                                    //对应映射关系为:虚拟地址:0x0-0x100M----------物理地址0x0-0x100
                                                    //这段内存的读写权限设置在(c << 3) | ( << 2) C位WT模式直写模式, B位WB模式,write back 先写入cache在写入内存
            // Not Allowed
            .rept 0x200 - 0x100                        //0x200M-0x100M 内容为0,最低两位为0,表示无效;
            .word 0x00000000
            .endr
    
            .set __base,0x200                        //TTB[0x200]-TTB[0x600 -1]对应的内容为:0x200-0x599
            // should be accessed                    //对应映射关系为:虚拟地址:0x200-0x600M----------物理地址0x200-0x600
            .rept 0x600 - 0x200                        //权限位WT、WB
            FL_SECTION_ENTRY __base,3,0,1,1
            .set __base,__base+1
            .endr
    
            .rept 0x800 - 0x600                        //同样0x600-0x800物理地址是无效的
            .word 0x00000000
            .endr
    
            .set __base,0x800                        //虚拟地址:0x800-0xB00M----------物理地址0x800-0xB00
            // should be accessed                    //不可写入
            .rept 0xb00 - 0x800
            FL_SECTION_ENTRY __base,3,0,0,0
            .set __base,__base+1
            .endr
    
        /*    .rept 0xc00 - 0xb00
            .word 0x00000000
            .endr */
    
            .set __base,0xB00                        //虚拟地址:0xB00-0xC00M----------物理地址0xB00-0xC00
            .rept 0xc00 - 0xb00                        //不可写入
            FL_SECTION_ENTRY __base,3,0,0,0
            .set __base,__base+1
            .endr
    
            // 0xC000_0000鏄犲皠鍒?x2000_0000
            //.set __base,0x300
            .set __base,0x200                        //虚拟地址:0xC00-0xD00M----------物理地址0x200-0x300
            // 256MB for SDRAM with cacheable        //WT、WB
            .rept 0xD00 - 0xC00
            FL_SECTION_ENTRY __base,3,0,1,1            //虚拟地址0xc000_0000----0xcFFF_FFFF对应的物理地址是0x2000_0000-----0x2FFF_FFFF
            .set __base,__base+1
            .endr
    
            // access is not allowed.
            @.rept 0xD00 - 0xC80
            @.word 0x00000000
            @.endr
    
            .set __base,0xD00
            // 1:1 mapping for debugging with non-cacheable
            .rept 0x1000 - 0xD00
            FL_SECTION_ENTRY __base,3,0,0,0
            .set __base,__base+1
            .endr

    C设置TTB代码:

    //16K对齐
    #define MMU_TABLE_ADDR       0x00100000
    #define TTB_VALUE_CONFIG(base, b, c, d, e)                    
    (((base) << 20) | ((b) << 10) | ((c) << 5) | ((d) << 3) | ((e) << 2) | (1 << 1))
    
    (ap << 10) | 
                  (d << 5) | (1<<4) | (c << 3) | ( << 2) | (1<<1)
    
    
    unsigned int *p_mmu_table = (unsigned int*)MMU_TABLE_ADDR;
    
    void ttb_set(void)
    {
        int i = 0x0;
        int base = 0x0;    
        for (i=0x0; i<0x100; i++) {
            *p_mmu_table = TTB_VALUE_CONFIG(base, 3, 0, 1, 1);    
            p_mmu_table++;
            base++;                                //base 0x0-0x100
        }
        for (; i<0x200; i++) {
            *p_mmu_table = 0;    
            p_mmu_table++;    
            base++;                                //base 0x100-0x200
        }    
        for (; i<0x600; i++) {
            *p_mmu_table = TTB_VALUE_CONFIG(base, 3, 0, 1, 1);
            p_mmu_table++;
            base++;                                //base 0x200-0x600
        }
        for (; i<0x800; i++) {
            *p_mmu_table = 0;
            p_mmu_table++;
            base++;                                //base 0x600-0x800
        }
        for (; i<0xB00; i++) {
            *p_mmu_table = TTB_VALUE_CONFIG(base, 3, 0, 0, 0);
            p_mmu_table++;
            base++;                                //base 0x800-0xB00
        }
        for (; i<0xc00; i++) {
            *p_mmu_table  = TTB_VALUE_CONFIG(base, 3, 0, 0, 0);
            p_mmu_table++;
            base++;
        }
        for (base=0x200; i<0xd00; i++) {
            *p_mmu_table = TTB_VALUE_CONFIG(base, 3, 0, 1, 1);
            p_mmu_table++;
            base++;
        }
        for (i=0xc80, p_mmu_table=p_mmu_table-0x80; i<D00; i++) {
            *p_mmu_table = 0;
            p_mmu_table++;
        }
        for (i=0xd00, base=0xD00; i<0x1000; i++) {
            *p_mmu_table = TTB_VALUE_CONFIG(base, 3, 0, 0, 0);
            p_mmu_table++;
        }
        
    }

    设置cp15寄存器中的值:

    #if defined(CONFIG_ENABLE_MMU)
    enable_mmu:
        /* enable domain access */
        ldr    r5, =0x0000ffff                //设置域权限:设置16个域权限位可读可写,在写入C3寄存器
        mcr    p15, 0, r5, c3, c0, 0        @load domain access register
    
        /* Set the TTB register */
        ldr    r0, MMU_TABLE_ADDR          //把内存_mmu_table_base中的值写入到r0中,从最上面三行代码可以看出_mmu_table_base中的值为mmu_table
        ldr    r1, =CFG_PHY_UBOOT_BASE        //mmu_table定义在lowlevel_init函数中,mmu_table即为在SRAM中的向量表的地址,BL1中把整个uboot的代码
        ldr    r2, =0xfff00000                //复制到0x23e0_0000内存处,所以在内存中的向量表的地址为:0x23e0_0000+mmu_table的值
        bic    r0, r0, r2                    //清mmu_table的高12bit,在位或0x23e0_0000,即把内存中的向量表的地址计算出来赋值给r1了,
        orr    r1, r0, r1                    //然后把r1写入到寄存器c2中,则完成了TTB的设置。
        mcr    p15, 0, r1, c2, c0, 0
    
        /* Enable the MMU */
    mmu_on:
        mrc    p15, 0, r0, c1, c0, 0        //使能mmu,c3的M位置1,即使能mmu
        orr    r0, r0, #1
        mcr    p15, 0, r0, c1, c0, 0
        nop
        nop
        nop
        nop
    #endif
     
  • 相关阅读:
    枚举求解,也叫暴力破解
    多线程之线程的中止
    beginners with the Multithreading programming
    EditBox control Update Problem (A CString type EditBox control in a loop cannot be updated immidiately)
    有关多线程的一些技术问题
    多线程编程基础知识
    VC的若干实用小技巧 (如何干净的删除一个类)
    进入MFC讲坛的前 (Window 程序详细分析)
    Multithreading using MFC in Plain English: Part I
    关于在VS2005环境下无法从源视图切换到设计视图的解决方案
  • 原文地址:https://www.cnblogs.com/biaohc/p/6292376.html
Copyright © 2011-2022 走看看