之前在 文章 中描述了 7个ioctl,现在着重分析 其中5个,这5个与虚拟机CPU相关
KVM_CREATE_VM
KVM_CREATE_VCPU
KVM_ARM_VCPU_INIT
KVM_SET_ONE_REG
KVM_RUN
vm entry
vm exit
KVM_RUN
- VM entry 的流程
kvm_vcpu_ioctl
kvm_arch_vcpu_ioctl_run
-1.kvm_call_hyp_ret(__kvm_vcpu_run_nvhe, vcpu); //kvm_call_hyp_ret即__kvm_call_hyp
0. __kvm_call_hyp 中的 hvc #0
1. arch/arm/kvm/hyp/hyp-entry.S 中的 __kvm_hyp_vector_ic_inv 中的 W(add) sp, sp, #1 /* HVC 2 */
2. b decode_vectors
3. vect_br 0, hyp_fiq 和 vect_br 1, hyp_irq 和 vect_br 2, hyp_hvc
4. hyp_hvc
5. blx lr @ Call the HYP function
6. __kvm_vcpu_run_nvhe
7. __guest_enter
8. eret // 进入 guest
- VM exit 的流程
1. 虚拟机执行敏感指令
2. __kvm_hyp_vector_ic_inv 中的 W(add) sp, sp, #1 /* HVC 2 */
3. b decode_vectors
4. vect_br 0, hyp_fiq 和 vect_br 1, hyp_irq 和 vect_br 2, hyp_hvc
5. hyp_hvc
6. bne guest_trap @ Not HVC instr.
7. mov r1, #ARM_EXCEPTION_HVC 和 b __guest_exit
8. abort_guest_exit_end: bx lr
9. arch/arm/kvm/hyp/switch.c 中的 __populate_fault_info 中的 u32 hsr = read_sysreg(HSR); // ???
10. if (exit_code == ARM_EXCEPTION_HVC && !__populate_fault_info(vcpu)) goto again;
切换
- host PL2 与 host PL1 的切换
关注
1. host PL1 mode 陷入 host PL2mode
主动调用 指令(hvc)
virt/kvm/arm/vgic/vgic-init.c:477: kvm_call_hyp(__vgic_v3_init_lrs);
virt/kvm/arm/vgic/vgic-v3.c:661: kvm_call_hyp(__vgic_v3_write_vmcr, cpu_if->vgic_vmcr);
virt/kvm/arm/vgic/vgic-v3.c:663: kvm_call_hyp(__vgic_v3_restore_aprs, vcpu);
virt/kvm/arm/vgic/vgic-v3.c:685: kvm_call_hyp(__vgic_v3_save_aprs, vcpu);
virt/kvm/arm/mmu.c:58: kvm_call_hyp(__kvm_tlb_flush_vmid, kvm);
virt/kvm/arm/mmu.c:63: kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa);
virt/kvm/arm/arm.c:348: kvm_call_hyp(__kvm_tlb_flush_local_vmid, vcpu);
virt/kvm/arm/arm.c:507: kvm_call_hyp(__kvm_flush_vm_context);
virt/kvm/arm/arch_timer.c:464: kvm_call_hyp(__kvm_timer_set_cntvoff, low, high);
arch/arm/include/asm/kvm_host.h kvm_call_hyp(__init_stage2_translation);
virt/kvm/arm/vgic/vgic-v3.c:584: u32 ich_vtr_el2 = kvm_call_hyp_ret(__vgic_v3_get_ich_vtr_el2);
virt/kvm/arm/vgic/vgic-v3.c:676: cpu_if->vgic_vmcr = kvm_call_hyp_ret(__vgic_v3_read_vmcr);
virt/kvm/arm/arm.c:747: ret = kvm_call_hyp_ret(__kvm_vcpu_run_nvhe, vcpu);
中断(来自外设,模拟外设) // 哪些中断会进入host PL2 mode,可配置决定
2. host PL2 mode 退出到 host PL1 mode
指令 : eret
- host os 与 guest os 的切换
1. host PL2 mode 陷入 guest
__kvm_vcpu_run_nvhe -> __guest_enter -> eret(该指令执行后进入 guest)
2. guest 退出到 host PL2 mode
3.1 敏感指令(包括ipi指令) // 哪些指令会退出,可配置决定
3.2 中断(来自外设,模拟外设) // 哪些中断会进入host PL2 mode,可配置决定