- 虚拟机内存角度分析中列出了访存流程
想象中是这样子的流程 1. guest 内存相关 的初始化 (HTTBR 与 VTTBR 的设置) // 参考 "host 中的 HTTBR" 和 "host 中的 VTTBR" 2. guest os 开始运行 3. guest os 读 A 地址 4. 陷入 host PL2 异常 // host os 开始运行 4.1 异常退出 4.2 做相应的动作 4.3 注入中断 4.4 guest enter // guest os 开始 运行 5. guest os 陷入 guest PL1 异常 6. guest PL1 异常处理 6.1 保存现场 6.2 做相应的动作 6.2 恢复现场,恢复 pc 为访存时的pc 7. guest os 读 A 地址 // 和 3 是同一个动作 8. guest os 获取 A 地址的值 注意 : 4.2 和 6.2 是 我们关注的重点 ———————————————— 版权声明:本文为CSDN博主「__pop_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/u011011827/article/details/120864037
流程中 需要关注两点
1. 4.2 host PL2 中的异常处理 可参考 https://blog.csdn.net/u011011827/article/details/120986330 中的 kvm_handle_guest_abort 2. 6.2 : guest PL1 中的 异常处理 可参考 https://blog.csdn.net/u011011827/article/details/117430300 中的 "linux-5.11 对 data abort 异常的处理"host PL2 中的异常处理 kvm_handle_guest_abort
两种情况会进入 1. guest OS 申请内存 2. guest OS 访问由用户空间模拟的 I/O内存 会按照以下过程区分 1. 确认 导致 IPA 的 fault 2. 确认 内存区域是否已按用户空间注册为标准RAM kvm_handle_guest_abort 主要有三个程序流 io_mem_abort // 对应 guest OS 访问由用户空间模拟的 I/O内存 ,IPA非标准RAM handle_access_fault // 对应 guest OS 访问内存 的权限错误 ,IPA是标准RAM user_mem_abort // 对应 guest OS 申请内存 ,IPA是标准RAM
第一次 KVM_RUN guest enter guest exit handle_exit kvm_handle_guest_abort fault_ipa = kvm_vcpu_get_fault_ipa(vcpu); gfn = fault_ipa >> PAGE_SHIFT; // 0x100 memslot = gfn_to_memslot(vcpu->kvm, gfn); hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable); // 0xb6f35000 user_mem_abort guest enter guest exit handle_exit kvm_handle_guest_abort fault_ipa = kvm_vcpu_get_fault_ipa(vcpu); gfn = fault_ipa >> PAGE_SHIFT; // 0x8 memslot = gfn_to_memslot(vcpu->kvm, gfn); hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable); // 0xc0000000 io_mem_abort vcpu_data_guest_to_host kvm_mmio_write_buf kvm_io_bus_write run->mmio.is_write = is_write; // 1 run->mmio.phys_addr = fault_ipa; // 0x8000 vcpu->mmio_needed = 1; memcpy(run->mmio.data, data_buf, len); // H run->exit_reason = KVM_EXIT_MMIO; little-qemu 打印H 第二次 KVM_RUN guest enter guest exit handle_exit kvm_handle_guest_abort fault_ipa = kvm_vcpu_get_fault_ipa(vcpu); gfn = fault_ipa >> PAGE_SHIFT; memslot = gfn_to_memslot(vcpu->kvm, gfn); hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable); io_mem_abort vcpu_data_guest_to_host kvm_mmio_write_buf kvm_io_bus_write run->mmio.is_write = is_write; // 1 run->mmio.phys_addr = fault_ipa; // 0x8000 vcpu->mmio_needed = 1; memcpy(run->mmio.data, data_buf, len); // e run->exit_reason = KVM_EXIT_MMIO; little-qemu 打印e 第N次 KVM_RUN guest enter guest exit handle_exit kvm_handle_guest_abort fault_ipa = kvm_vcpu_get_fault_ipa(vcpu); gfn = fault_ipa >> PAGE_SHIFT; memslot = gfn_to_memslot(vcpu->kvm, gfn); hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable); io_mem_abort vcpu_data_guest_to_host kvm_mmio_write_buf kvm_io_bus_write run->mmio.is_write = is_write; // 1 run->mmio.phys_addr = fault_ipa; // 0x8000 vcpu->mmio_needed = 1; memcpy(run->mmio.data, data_buf, len); // 'n' run->exit_reason = KVM_EXIT_MMIO; little-qemu 打印'n' 第N+1次 KVM_RUN guest enter guest exit handle_exit kvm_handle_guest_abort fault_ipa = kvm_vcpu_get_fault_ipa(vcpu); gfn = fault_ipa >> PAGE_SHIFT; memslot = gfn_to_memslot(vcpu->kvm, gfn); hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable); io_mem_abort vcpu_data_guest_to_host kvm_mmio_write_buf kvm_io_bus_write run->mmio.is_write = is_write; // 1 run->mmio.phys_addr = fault_ipa; // 0x10000 vcpu->mmio_needed = 1; memcpy(run->mmio.data, data_buf, len); // 0 run->exit_reason = KVM_EXIT_MMIO; little-qemu 打印 "Guest Exit!"



