1 ram 比较简单的内存空间,读写对应直接修改 hva, 初始memory_region_init_ram, memory_region_init_resizeable_ram, memory_region_init_ram_from_file, memory_region_init_ram_ptr 函数用于初始化
2 mmio 这些空间对应于设备的地址空间映射到内存地址空间的空间(也就是mmio), 读写这些地址空间都会触发对应模拟设备的回调操作 memory_region_init_io 初始化
3 ROM 只读空间, 读直接访问hva, 写则拒绝,使用memory_region_init_rom() 初始化
4 rom device 这类空间读直接访问hva, 写则回调设备注册的函数(设备可能进行出错处理)
5 IOMMU 用于iommu建模型,也就是支持iommu的设备模拟 memory_region_init_iommu()
6 container 逻辑单元, 逻辑单元内的地址可以通过overlay覆盖, memory_region_init() 初始化容器
7 别名: 比较难理解, 比如我的pci是一个MemoryRegion是一个Region, 对应一片连续的hva, 但是我要把它映射到ram的地址空间, 就需要别名机制,把pci的一段地址分裂出一个别名,把这个别名放入Ram MemoryRegion的子region中,这样这段地址在, 也就是同一个MemoryRegion有相同
的设备属性(MMIO, RAM , ROM , ROM DEVICES), 但是可能在不连续的AddressSpace, 就是这样.
addresspace上是在ram所在的区域,但是实际的hva却指向pci的region, memory_region_init_alias() 初始化
8 保留区域: 主要用于调试,使用 memory_region_init_io() 初始化
1 别名MemoryRegion没有子Region
2 建议使用一个纯容器作为父MemoryRegion, 一个整个空间的MemoryRegion作为背景MemoryRegion, 其他MemoryRegion 覆盖到这个MemoryRegion上面, 当读写MemoryRegion对应的AddressSpace的时候, 只回调相应MemoryRegion的地址
Where the memory region is backed by host memory (RAM, ROM and
ROM device memory region types), this host memory needs to be
copied to the destination on migration. These APIs which allocate
the host memory for you will also register the memory so it is
migrated:
- memory_region_init_ram()
- memory_region_init_rom()
- memory_region_init_rom_device()
For most devices and boards this is the correct thing. If you
have a special case where you need to manage the migration of
the backing memory yourself, you can call the functions:
- memory_region_init_ram_nomigrate()
- memory_region_init_rom_nomigrate()
- memory_region_init_rom_device_nomigrate()
which only initialize the MemoryRegion and leave handling
migration to the caller.
The functions:
- memory_region_init_resizeable_ram()
- memory_region_init_ram_from_file()
- memory_region_init_ram_from_fd()
- memory_region_init_ram_ptr()
- memory_region_init_ram_device_ptr()
are for special cases only, and so they do not automatically
register the backing memory for migration; the caller must
manage migration if necessary.
也就是说对于两种类型的MemoryRegion, 一种对应hva, 这种系统会直接帮忙迁移(也就是自动保存,复制)
另外一种不对应hva, 需要设备实现者自己去在相应的回调中实现保存复制
memory_region_add_subregion_overlap() 函数允许一个MemoryRegion覆盖容器中的其他区域, 覆盖是根据优先级来设置的,高优先级覆盖低优先级地址
如果高优先级的MemoryRegion是别名或者容器, 地址是不连续的,则会留下一些空洞,低优先级的MemoryRegion会在这些空洞的地方漏出来
A是一个纯容器,里面有B和C两个子MemoryRegion, C的优先级是1 , 相对A偏移为0, 大小为6000
B是一个纯容器,里面有两个MemoryRegion.分别是D和E, D相对B偏移为0,大小为1000, E相对B偏移为2000,大小为1000,如下图