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) | (\b << 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) | (\b << 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) | (\b << 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
 
时间: 2024-10-19 05:53:43

S5PV210 uboot中的 MMU代码分析的相关文章

MPC8313ERDB在Linux从NAND FLASH读取UBoot环境变量的代码分析

[email protected] 一.故事起因 因为文件系统的增大,已经大大的超出了8MB的NOR FLASH,而不得不把内核,文件系统和设备树文件保存到NAND FLASH上.但是因为使用的是RAMDISK,而无法保存一些个别的配置和参数,最简单的需要就是设置系统的IP了,,, 要使用统一的RAMDISK,而实现LINUX启动之后,设置成不能的参数功能,比较方便的就是从UBOOT把这些参数传递过去,这个得到了大家的认证,我们可以直接添加启动参数,然后在内核里面读出来,这种方法比较方法,唯一不

Openstack中RabbitMQ RPC代码分析

在Openstack中,RPC调用是通过RabbitMQ进行的. 任何一个RPC调用,都有Client/Server两部分,分别在rpcapi.py和manager.py中实现. 这里以nova-scheduler调用nova-compute为例子. nova/compute/rpcapi.py中有ComputeAPI nova/compute/manager.py中有ComputeManager 两个类有名字相同的方法,nova-scheduler调用ComputeAPI中的方法,通过底层的R

uboot中setenv和saveenv分析

转:https://blog.csdn.net/weixin_34355715/article/details/85751477 Env在u-boot中通常有两种存在方式,在永久性存储介质中(flash.NVRAM等),在SDRAM中.可配置不适用env的永久存储方式,但不常用.U-boot在启动时会将存储在永久性存储介质中的env重新定位到RAM中,这样可以快速访问,同时可以通过saveenv将RAM保存到永久性存储介质中. 相关结构体 env_t定义于include/environment.

AnimationsDemo中的ZoomActivity代码分析

AnimationsDemo是android官网的一个动画使用示例. ZoomActivity是demo中的图像缩放动画,因为这种效果比较常见,所以研究了一下代码. 下面是效果图: 毫无疑问这是一个组合动画,translation和scale动画.实现这种动画的关键是如何确定动画的坐标和缩放比例 除了一些简单的数学计算外,该demo还利用了ImageView的fitCenter特性.稍后我们就可以看到. 在开始分析代码之前,先说一下程序的原理:     1,点击缩略图的时候同时将缩略图隐藏.  

对Java tutorial-examples中hello2核心代码分析

1.在hello2中有两个.java源文件分别是GreetingServlet.Java和ResponseServlet.jva文件主要对以下核心代码做主要分析. 1 String username = request.getParameter("username"); //获取表单数据 2 if (username != null && username.length() > 0) { 3 RequestDispatcher dispatcher = //定义一

openCV中cvSnakeImage()函数代码分析

/*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // // By downloading, copying, installing or using the software you agree to this licen

微擎框架中receive.php代码分析

原文地址:https://www.cnblogs.com/guiyishanren/p/11025125.html

ARM上电启动及Uboot代码分析

注意:由于文档是去年写的,内有多个图片,上传图片很麻烦(需要截图另存插入等等),我把文章的PDF版本上传到了CSDN下载资源中.为了给自己赚点积分,所以标价2分,没有积分的同学可以直接留言跟我要,记得留下邮箱. 以下是文章内容,由于我懒得编辑图片了,所以文章看来会很不爽,强烈推荐点击以上红色链接下载pdf版. 文件编号:DCC01 版本号:1.0 ARM上电启动及Uboot代码分析 部    门:                          作    者:                 

常用 Java 静态代码分析工具的分析与比较

转载自: http://www.oschina.net/question/129540_23043 简介: 本文首先介绍了静态代码分析的基本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBugs,PMD,Jtest),最后从功能.特性等方面对它们进行分析和比较,希望能够帮助 Java 软件开发人员了解静态代码分析工具,并选择合适的工具应用到软件开发中. 引言 在 Java 软件开发过程中,开发团队往往要花费大量的时间和精力发现并修改代