首页 >> 大全

uboot的虚拟地址映射学习

2023-12-16 大全 24 作者:考证青年

参考资料:

1: 关于ARM地址映射的理解.

2: uboot中的 MMU代码分析.

3: 协处理器CP15介绍—MCR/MRC指令(6).

4.朱老师的课程uboot的2.5.10-2.5.12节

虚拟地址映射

把虚拟地址映射到物理地址。

怎么映射

两者之间的进行转换的话会有一个转换关系,这个转换关系对应的是虚拟地址映射表。

uboot是在进行完BL2的重定位之后,开始虚拟地址映射,然后后面都使用的虚拟地址了。

重定位之后进入段

具体思路可以看注释,并且要结合用到的参考资料,知道一个个转换关系到底是怎样结合起来的。

还有,这里只是一级映射,用了段模式,算是最简单的一种映射方法。

after_copy:#if defined(CONFIG_ENABLE_MMU)
enable_mmu:/* enable domain access */ldr	r5, =0x0000ffffmcr	p15, 0, r5, c3, c0, 0		@load domain access register //mcr 把arm处理器的数据传输到协处理器里面 即把r5的值写到c3里面//c3是协处理器cp15的一个寄存器,控制了ARM处理器16个域的访问权限//ffff即16个1对应16个域的权限。/* Set the TTB register */    ldr	r0, _mmu_table_base		//获取mmu_table(转换表)的基地址ldr	r1, =CFG_PHY_UBOOT_BASE //根据注释算得是0x33e000000ldr	r2, =0xfff00000   		//取bit[31:20]位,也就是高12位bic	r0, r0, r2				//取把这个值的高12位清零orr	r1, r0, r1				//把物理地址和这个经过处理的转换表进行位或运算,组合成一个段地址+条目描述符mcr	p15, 0, r1, c2, c0, 0	//把这个得到的转换关系写到c2寄存器,也就是TTB 转换表里面/* Enable the MMU */		//设置完之后就启动mmu
mmu_on:mrc	p15, 0, r0, c1, c0, 0orr	r0, r0, #1mcr	p15, 0, r0, c1, c0, 0nopnopnopnop
#endif

下面这段代码是在里面,作用就是建立转换表

	/* form a first-level section entry *///ap是设置权限在 cp15 c2寄存器 bit[10-11]//d是domain域 cp15 c2寄存器 bit[5-8]不管是段模式还是页模式,系统都把4GB空间分为16个域,每个域有相同的权限检查//c bit 3  b bit 2   C/B位是控制位,与本条目(描述符)所在域的Cache和Buffer有关(是否允许本域开启Cache和Buffer)//最后的1<<1设置bit1为1,其实bit[0:1]是设置模式描述符,0b10是段模式的描述符标识.macro FL_SECTION_ENTRY base,ap,d,c,b              //.macro 声明一个宏   	 一个宏名,接受5个参数.word (\base << 20) | (\ap << 10) | \(\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1)
.endm												//.end macro 应该是完成的宏定义标志
.section .mmudata, "a"			//.section.mmudata 这里是链接脚本的mmudata段,后面的"a"不懂.align 14// the following alignment creates the mmu table at address 0x4000. 这句注释感觉不对,不止是不是没改还是我理解不对.globl mmu_table
mmu_table:.set __base,0						//base是<<20位,20-31是段基址的地方,也就设置段基址位0// Access for iRAM.rept 0x100                                  //.rept repeat 伪指令 循环0x100次 转成十进制 256次FL_SECTION_ENTRY __base,3,0,0,0				//每一次循环,段基地址都加1  一段1MB 共256MB.set __base,__base+1.endr										//.endr end repeat 构成一个for循环// Not Allowed							.rept 0x200 - 0x100					 //又循环256次	   但是每次循环里面都置零.word 0x00000000						.endr.set __base,0x200                  //设置段基址位0x200 ap权限还是3 也就是11 cb控制为控制cache和buffer开吧// should be accessed.rept 0x600 - 0x200						//循环1024次FL_SECTION_ENTRY __base,3,0,1,1.set __base,__base+1						//每次段基址+1 一段1M 1024段就1024M 1G.endr.rept 0x800 - 0x600         // 循环512次	   但是都是置0.word 0x00000000.endr.set __base,0x800							//设置段基址0x800// should be accessed.rept 0xb00 - 0x800						    // 0x300 256*3次 一次段+1 768MBFL_SECTION_ENTRY __base,3,0,0,0.set __base,__base+1.endr/*	.rept 0xc00 - 0xb00.word 0x00000000.endr */.set __base,0xB00							//设置段基址 B00.rept 0xc00 - 0xb00					    //0x100 256次  256MBFL_SECTION_ENTRY __base,3,0,0,0.set __base,__base+1.endr// 0xC000_0000映射到0x3000_0000             .set __base,0x300                          //设置段基址0x300//.set __base,0x200// 256MB for SDRAM with cacheable.rept 0xD00 - 0xC00							//从0xc00开始到0xd00一共256次,一次1MB,共256MBFL_SECTION_ENTRY __base,3,0,1,1.set __base,__base+1.endr// access is not allowed.@.rept 0xD00 - 0xC80						//从c80到d00又不给用@.word 0x00000000@.endr.set __base,0xD00									//d00到 10000 循环0x300次 768次 即768M// 1:1 mapping for debugging with non-cacheable.rept 0x1000 - 0xD00FL_SECTION_ENTRY __base,3,0,0,0.set __base,__base+1.endr	

抽取前面两端进行分析讲解,如图所示。

_虚拟地址映射表_映射虚拟磁盘什么意思

跟着代码一步步分析最终算出了的长度加起来刚刚好是4G的长度,也就是全映射了。

细心点会发现,到也是设置为不可用的。

结果就完成了转换表的建立。

回顾

DRAM有效范围:

DMC0: -

DMC1:

结论:虚拟地址映射只是把虚拟地址的开头的256MB映射到了DMC0的开头的256MB物理内存上去了。其他的虚拟地址空间根本没动,还是原样映射的。

思考:为什么配置时将链接地址设置为,因为这个地址将来会被映射到这个物理地址。

之前在主里面的设置为,经过映射后就到了的位置。

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了