ARM64内存虚拟化分析(8)coalesed MMIO处理

        从前面MMIO的处理可以看到,每次访问MMIO都会导致虚拟机退了到QEMU中。很多时候多个MMIO操作,这个时候可以先将前面的MMIO操作保存起来,等到最后一个MMIO的时候,再一起退出到QEMU中处理,这就是coalesced MMIO。目前只支持对写操作的coalesced MMIO。

1 coalesced MMIO相关的API

        首先介绍QEMU中部分Coalesced MMIO相关的API。

        函数memory_region_add_coalescing()将MR中偏移为offset大小为size的内存区域设置为coalesced mmio区域。

void memory_region_add_coalescing(MemoryRegion *mr,
                                  hwaddr offset,
                                  uint64_t size)

        函数memory_region_clear_coalescing()清除掉MR中的coalesced mmio区域。

void memory_region_clear_coalescing(MemoryRegion *mr)

        函数memory_region_set_flush_coalesced()将mr->flush_coalesced_mmio设置为true。

void memory_region_set_flush_coalesced(MemoryRegion *mr)

        函数memory_region_clear_flush_coalesced()首先会flush掉之前保存起来还未完成的MMIO操作,然后将mr->flush_coalesced_mmio设置为false。

void memory_region_clear_flush_coalesced(MemoryRegion *mr)

        函数memory_region_set_coalescing()首先将之前可能创建的coalesced MMIO去掉,然后再对整个MR区域设置为coalesced mmio区域。

void memory_region_set_coalescing(MemoryRegion *mr)

2 coalesced MMIO的实现

        在实现coalesced MMIO之前,虚拟机中对MMIO的每次访问,会立即陷入到EL2,最终通过QEMU中定义读写操作函数进行模拟。

        通常需要将MR的某段内存区域设置为coalesced MMIO后,后续对该段内存区域中的一个或多个连续写会被保存到ring中,不会对每个写都立即陷入到EL2,而是在下一次读或对其他区域写之前将保存在ring中的MMIO操作flush完成。

2.1 调用coalesced MMIO API设置coalesced MMIO

        以调用函数memory_region_add_calescing()将MR中一段内存区域设置为coalesced MMIO为例,讲述此过程。

  1. 分配CoalescedMemoryRange区域,并将其加和到mr->coalesced中;
  2. 依次遍历flatview中每个flatrange,若flatrange对应的MR与当前MR相符,进行下一步;
  3. 找到地址范围,若为增加coalesced MMIO时,通过系统调用KVM_REGISTER_COALESED_MMIO向KVM注册coalesced MMIO;
  4. 若为删除coalesced MMIO时,通过系统调用KVM_UNREGISTER_COALECED_MMIO向KVM注销coalesced MMIO;

2.2 往KVM注册/注销coalesced MMIO

        通过系统调用KVM_REGISTER_COALESCED_MMIO往KVM注册coalesced MMIO,过程如下:

(1)分配kvm_coalesced_mmio_dev;

(2)初始化该设备的操作回调,对于coalesced MMIO,仅定义write回调;

对于写回调coalesced_mmio_wirte(),当对coalesced MMIO写时,将数据缓存到ring中;

(3)将coalesced MMIO设备注册到系统中,类似于GIC/ITS;

(4)将设备添加到kvm->coalesced_zones中;

2.3 对coalesced MMIO的访问

        当对coalesced MMIO作写访问时,仍然会陷入到EL2 host上,调用coalesced_mmio_write()将数据缓存到ring中。

        当对coalesced MMIO作读访问时,仍然会陷入到EL2 host上(不作任何操作),返回到EL2 QEMU中,首先会flush掉之前缓存的coalesced MMIO操作,然后再执行QEMU中对应的读操作;

        对其他MMIO区域的读写访问时,首先陷入到EL2 host上,然后返回到EL2 QEMU中,先flush掉之前缓存coalesced MMIO操作,再执行QEMU中对应的读写操作。

        因此对于coalesced MMIO区域的真正写操作,是在对coalesced MMIO区域读操作或对其他MMIO域的读写访问时发生的,它会依次将ring中缓存的coalesced MMIO进行处理,过程如下:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值