Как KVM планирует несколько виртуальных машин в Intel VMX? - PullRequest
0 голосов
/ 09 июня 2018

Я изучаю Intel VMX через Linux KVM.
И я не мог четко понять, как KVM (Linux) планирует одновременное выполнение нескольких виртуальных машин на одном хосте.
Например, в физическом процессоре 1хоста, и есть 2 виртуальные машины KVM, каждая из которых настроена на 1 vCPU.
Как только они запущены, KVM / QEMU настраивают VMCS для каждого vCPU, поэтому в KVM есть 2 VMCS.Поскольку существует только 1 pCPU, KVM / Linux должен планировать каждый vCPU 1 на 1.
Насколько я понимаю, когда vCPUa работает, KVM VMPTRLD VMCS vCPUa и запуск кодов виртуальной машины.Затем должен быть запланирован vCPUb, KVM куда-то VMPTRST VMCS vCPUa отправит VMPURL и куда-то VMPTRLD VMCS vCPUb.
Читая код KVM, я НЕ нашел, где произошло VMPTRLD / VMPTRST для планирования vCPU и что такое 'где-то».

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Во-первых, 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);
    }

Вот и все.

0 голосов
/ 09 июня 2018

vmptrld находится в vmx_vcpu_load в arch / x86 / kvm / vmx.c
vmresume находится в vmx_vcpu_run

...