KVM如何在Intel VMX中安排多个VM?

时间:2018-06-09 12:20:41

标签: linux x86 virtualization kvm

我正在通过Linux KVM学习英特尔VMX 我无法清楚地了解KVM(Linux)如何安排在同一主机上并行运行的多个VM 例如,主机中有1个物理CPU,并且有2个KVM VM,每个VM配置1个vCPU。 启动后,KVM / QEMU为每个vCPU配置VMCS,因此KVM中有2个VMCS。由于只有1个pCPU,因此KVM / Linux必须将每个vCPU 1安排为1 我的理解是vCPUa运行时,vCPUa的KVM VMPTRLD VMCS,并运行VM的代码。然后,将调度vCPUb,KVM将VCPTRST的VCPTRST到某个地方的VMCS,以及来自某处的vCPUb的VMPTRLD VMCS。 通过阅读KVM的代码,我找不到vMPTRLD / VMPTRST在vCPU调度中发生的位置,以及“某处”的内容。

2 个答案:

答案 0 :(得分:2)

vmptrld位于arch / x86 / kvm / vmx.c中的vmx_vcpu_load中 vmresume位于vmx_vcpu_run

答案 1 :(得分:1)

首先,KVM将为vCPU进出登记注册两个标注,如下所示 kvm_preempt_ops.sched_in = kvm_sched_in;
kvm_preempt_ops.sched_out = kvm_sched_out;

所以,每当调度发生时(没有深入研究),就会调用它们。以kvm_sched_in()为例,它会调用,

static void kvm_sched_in(struct preempt_notifier *pn, int cpu)
{
    struct kvm_vcpu *vcpu = preempt_notifier_to_vcpu(pn);

    if (vcpu->preempted)
        vcpu->preempted = false;

    kvm_arch_sched_in(vcpu, cpu);

    kvm_arch_vcpu_load(vcpu, cpu);
}

kvm_arch_vcpu_load()将与VMCS一起使用,如下所示。

void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
    /* Address WBINVD may be executed by guest */
    if (need_emulate_wbinvd(vcpu)) {
        if (kvm_x86_ops->has_wbinvd_exit())
            cpumask_set_cpu(cpu, vcpu->arch.wbinvd_dirty_mask);
        else if (vcpu->cpu != -1 && vcpu->cpu != cpu)
            smp_call_function_single(vcpu->cpu,
                    wbinvd_ipi, NULL, 1);
    }
    kvm_x86_ops->vcpu_load(vcpu, cpu); <<======

.vcpu_load = vmx_vcpu_load,

以来
/*
 * Switches to specified vcpu, until a matching vcpu_put(), but assumes
 * vcpu mutex is already taken.
 */
static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
    struct vcpu_vmx *vmx = to_vmx(vcpu);
    u64 phys_addr = __pa(per_cpu(vmxarea, cpu));

    if (!vmm_exclusive)
        kvm_cpu_vmxon(phys_addr);
    else if (vmx->loaded_vmcs->cpu != cpu)
        loaded_vmcs_clear(vmx->loaded_vmcs);

    if (per_cpu(current_vmcs, cpu) != vmx->loaded_vmcs->vmcs) {
        per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs;
        vmcs_load(vmx->loaded_vmcs->vmcs);
    }

就是这样。