QEMU 设备模拟
QEMU 在用户空间中独立进行设备模拟,虚拟设备被其他的 VM 通过 hypervisor 提供的接口进行调用。由于设备的模拟是独立于 hypervisor 的,因此我们可以模拟任何设备,且该模拟设备可以在其他 hypervisor 间进行共享。
本章我们讲述 QEMU 如何进行设备模拟。
QEMU 设备 IO 处理
当 VM 在访问某一虚拟设备对应的物理内存/端口时,控制权由 VM 转交到 Hypervisor,此时 QEMU 会根据触发 VM-exit 的事件类型进行不同的处理。
accel/kvm/kvm-all.c
int kvm_cpu_exec(CPUState *cpu)
{
//...
do {
//...
run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0);
// VCPU 退出运行,处理对应事件
trace_kvm_run_exit(cpu->cpu_index, run->exit_reason);
switch (run->exit_reason) {
case KVM_EXIT_IO:
DPRINTF("handle_io\n");
/* Called outside BQL */
kvm_handle_io(run->io.port, attrs,
(uint8_t *)run + run->io.data_offset,
run->io.direction,
run->io.size,
run->io.count);
ret = 0;
break;
case KVM_EXIT_MMIO:
DPRINTF("handle_mmio\n");
/* Called outside BQL */
address_space_rw(&address_space_memory,
run->mmio.phys_addr, attrs,
run->mmio.data,
run->mmio.len,
run->mmio.is_write);
ret = 0;
break;MMIO
对于 MMIO 而言会调用到 address_space_rw() 函数,该函数会先将全局地址空间 address_space_memory 展开成 FlatView 后再调用对应的函数进行读写操作。
softmmu/physmem.c
操作函数最后会根据 FlatView 找到目标内存对应的 MemoryRegion,对于函数表中定义了读写指针的 MR 而言最后会调用对应的函数指针完成内存访问工作,代码过多这里就不继续展开了:
softmmu/physmem.c
PMIO
对于 PMIO 而言会调用到 kvm_handle_io() 函数,该函数实际上也是对 address_space_rw() 的封装,只不过使用的是端口地址空间 address_space_io,最后也会调用到对应 MemoryRegion 的函数表中的读写函数。
QEMU PCI 设备
待施工。
REFERENCE
《QEMU/KVM 源码解析与应用》——李强 著
Last updated