cemu
载入中...
搜索中...
未找到
mmu.h 文件参考
#include "dram.h"

浏览源代码.

函数

size_t mmu_get_offset (u64 base_memory_addr, u64 guest_physics_addr)
 MMU获取来宾物理地址相对 DRAM_BASE 的偏移量
 
u64 mmu_GPA_to_HVA (u64 base_memory_addr, u64 guest_physics_addr)
 MMU将来宾物理地址转化为主机虚拟地址
 
u64 mmu_HVA_to_GPA (u64 base_memory_addr, u64 host_virtual_addr)
 MMU将主机虚拟地址转化为来宾物理地址
 

详细描述

作者
your name (you@d.nosp@m.omai.nosp@m.n.com)
版本
0.1
日期
2024-01-09

MMU 设计

  • 关于MMU具体如何进行地址映射, 目前主要有两种主流的方式:

直接映射

  • 最简单的方法就是:物理地址 = 虚拟地址 + 偏移量。 这种最朴素的方式就是段式虚拟内存管理机制, 简称分段机制。 从直觉上来理解, 就是把物理内存划分成若干个段, 不同的进程就放到不同的段中运行, 进程不需要关心自己具体在哪一个段里面, 操作系统只要让不同的进程使用不同的偏移量, 进程之间就不会相互干扰了.
  • 分段机制在硬件上的实现可以非常简单, 只需要在MMU中实现一个段基址寄存器就可以了。 操作系统在运行不同进程的时候, 就在段基址寄存器中设置不同的值, MMU会把进程使用的虚拟地址加上段基址, 来生成真正用于访问内存的物理地址
  • 在的大部分操作系统都不再使用分段机制, 就连i386手册中也提到可以想办法"绕过"它来提高性能: 将段基地址设成0, 长度设成4GB, 这样看来就像没有段的概念一样, 这就是i386手册中提到的"扁平模式"

分页机制

  • i386是x86史上首次引进分页机制的处理器, 它把物理内存划分成以4KB为单位的页面, 同时也采用了二级页表的结构. 为了方便叙述, i386给第一级页表取了个新名字叫"页目录".
  • 每一张页目录和页表都有1024个表项, 每个表项的大小都是4字节, 除了包含页表(或者物理页)的基地址, 还包含一些标志位信息. 因此, 一张页目录或页表的大小是4KB, 要放在寄存器中是不可能的, 因此它们要放在内存中. 为了找到页目录, i386提供了一个CR3(control register 3)寄存器, 专门用于存放页目录的基地址

riscv64需要实现三级页表

  • riscv32的Sv32机制只能对32位的虚拟地址进行地址转换, 但riscv64的虚拟地址最长是64位, 因此需要有另外的机制来支持更长的虚拟地址的地址转换. 需要实现Sv39三级页表的分页机制即可, 而且PA只会使用4KB小页面, 不会使用2MB的大页面, 因此你无需实现Sv39的大页面功能. 具体细节请RTFM.

函数说明

◆ mmu_get_offset()

size_t mmu_get_offset ( u64 base_memory_addr,
u64 guest_physics_addr )

MMU获取来宾物理地址相对 DRAM_BASE 的偏移量

参数
base_memory_addr内存基址 dram.mem_addr
guest_physics_addr来宾物理地址:比 DRAM_BASE 大
返回
size_t 偏移量

◆ mmu_GPA_to_HVA()

u64 mmu_GPA_to_HVA ( u64 base_memory_addr,
u64 guest_physics_addr )

MMU将来宾物理地址转化为主机虚拟地址

参数
base_memory_addr内存基址 dram.mem_addr
guest_physics_addr来宾物理地址:比 DRAM_BASE 大
返回
u64 主机虚拟地址

◆ mmu_HVA_to_GPA()

u64 mmu_HVA_to_GPA ( u64 base_memory_addr,
u64 host_virtual_addr )

MMU将主机虚拟地址转化为来宾物理地址

参数
base_memory_addr内存基址
host_virtual_addr主机虚拟地址
返回
u64 来宾物理地址