arm mmu源码分析
2015-07-30 08:33
239 查看
arm7以上带有mmu模块,这个模块可以进行单位大小的地址的重新映射,这是扩展地址空间,增加代码灵活性的一个模块。以下是一个源码
void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size)
{
}
开始阶段我们要建立一张地址的映射表,这个表供cpu在拿到代码的地址访问请求是进行地址的寻址,在这个表里拿到的地址才是真正的物理地址。而我们代码给cpu的请求地址现在已经变成虚拟地址,他必须经过mmu进行一次转换。这样我们就可以做到多个虚拟地址对应一个物理地址,一块共享内存也就可以硬件实现了。这张表应该是长这个样子的
00000c12 00100c12 00200c12 00300c12…..
这里可以看出这是个一级页表的映射,他的单位是1m地址映射。
0 ———-》0000
1m ———->1M
这里就是一个原地址的映射关系
如果是
00100c12 在这张表的0地址
就是 0——–》1M 零地址对应了0x100000的地址了,这时候我们访问0地址 其实会获得0x1OOOOO地址的N内容。
void mmu_setttbase(register rt_uint32_t i)
{
register rt_uint32_t value;
}
这里完成了整张表的初始化之后就要将这张表的首地址告诉给cpu了,也就是上面的协处理器的汇编代码了。这个想知道具体意义可以去查arm官方的文档。
有个问题需要注意:这张表的地址不能够映射到其他地方,一定是给协处理器的地址,不然连cpu都找不到这张表,你的地址也就无法查到了。
最后就是开启这个mmu了 ,通知cpu不要直接发送地址而要去mmu进行转换了,
void mmu_enable()
{
register rt_uint32_t i;
}
这里也是协处理器的汇编也就设置了一个bit。
后面进行cache相关。
void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size)
{
unsigned int i; unsigned int reg; unsigned int low,high,ram; low = (0xa1000000 - 0xa0000000)>>20; high = (0xfffffffff - 0xa1000000)>>20; ram = (0x20000000 -0x10000000)>>20; for(i=0;i<low;i++){ reg = 0x10000000 +(i<<20); reg += 0xc12; *(int *)(0xa1000000 +i*4) =reg; } for(i=0;i<ram;i++){ reg = 0x10000000 +(i<<20); reg += 0xc12; *(int *)(0xa1000000+(0x10000000>>20)*4 +i*4) =reg; } for(i=0;i<high;i++){ reg = 0xa0000000+(i<<20); reg += 0xc12; *(int *)(0xa1000000 + (0xa0000000>>20)*4 +i*4) =reg; } mmu_setttbase((UINT32)0xa1000000); mmu_enable();
}
开始阶段我们要建立一张地址的映射表,这个表供cpu在拿到代码的地址访问请求是进行地址的寻址,在这个表里拿到的地址才是真正的物理地址。而我们代码给cpu的请求地址现在已经变成虚拟地址,他必须经过mmu进行一次转换。这样我们就可以做到多个虚拟地址对应一个物理地址,一块共享内存也就可以硬件实现了。这张表应该是长这个样子的
00000c12 00100c12 00200c12 00300c12…..
这里可以看出这是个一级页表的映射,他的单位是1m地址映射。
0 ———-》0000
1m ———->1M
这里就是一个原地址的映射关系
如果是
00100c12 在这张表的0地址
就是 0——–》1M 零地址对应了0x100000的地址了,这时候我们访问0地址 其实会获得0x1OOOOO地址的N内容。
void mmu_setttbase(register rt_uint32_t i)
{
register rt_uint32_t value;
value = 0; asm ("mcr p15, 0, %0, c8, c7, 0"::"r"(value)); value = 0x55555555; asm ("mcr p15, 0, %0, c3, c0, 0"::"r"(value)); asm ("mcr p15, 0, %0, c2, c0, 0"::"r"(i));
}
这里完成了整张表的初始化之后就要将这张表的首地址告诉给cpu了,也就是上面的协处理器的汇编代码了。这个想知道具体意义可以去查arm官方的文档。
有个问题需要注意:这张表的地址不能够映射到其他地方,一定是给协处理器的地址,不然连cpu都找不到这张表,你的地址也就无法查到了。
最后就是开启这个mmu了 ,通知cpu不要直接发送地址而要去mmu进行转换了,
void mmu_enable()
{
register rt_uint32_t i;
/* read control register */ asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); i |= 0x1; /* write back to control register */ asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
}
这里也是协处理器的汇编也就设置了一个bit。
后面进行cache相关。
相关文章推荐
- #新闻拍一拍# IBM 招聘广告要求应聘者具备至少 12 年 K8S 使用经验
- vivi下重新调整分区
- ARM Linux系统启动
- Linux及ARM Linux程序开发笔记(零基础入门篇)
- 我的 ARM+Linux 学习路线
- 关于ARM启动的一篇文章
- ARM 的堆栈初始化详解
- ARM条件码与CPSR标志位的关系
- 加载/存储指令
- 关于ARM 汇编的一些疑问
- ARM汇编伪指令介绍
- linux的防火墙及arm与虚拟机共享
- 编译单个驱动的Makefile文件。
- ARM Linux系统调用的原理
- Android LKM Rootkit,查找sys_call_table
- LKM Tricks to Android Devices,查找sys_call_table
- Arm Linux系统调用流程详细解析
- ARM下的injectso
- 说说ARM汇编的LDR伪指
- Suterusu Rootkit: Inline Kernel Function Hooking on x86 and ARM