All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jim Mattson <jmattson@google.com>
To: Bandan Das <bsd@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>,
	kvm@vger.kernel.org, "Paolo Bonzini" <pbonzini@redhat.com>,
	"David Matlack" <dmatlack@google.com>,
	"Peter Feiner" <pfeiner@google.com>
Subject: Re: [PATCH v2] KVM: nVMX: Track active shadow VMCSs
Date: Thu, 28 Jul 2016 06:30:04 -0700	[thread overview]
Message-ID: <CALMp9eQjY9Qg+vJ+8a6=ruA5PV99ykgh7pzNaWoHu65Gbw_-8Q@mail.gmail.com> (raw)
In-Reply-To: <jpg60rq21fi.fsf@linux.bootlegged.copy>

I'm going to be on vacation next week, but I'll address these concerns
when I return. If time permits, I'll send out a patch this week that
just addresses the issue of doing a VMPTRLD before putting the VMCS on
the loaded VMCSs list.

On Wed, Jul 27, 2016 at 2:53 PM, Bandan Das <bsd@redhat.com> wrote:
> Radim Krčmář <rkrcmar@redhat.com> writes:
>
>> 2016-07-22 11:25-0700, Jim Mattson:
>>> If a shadow VMCS is referenced by the VMCS link pointer in the
>>> current VMCS, then VM-entry makes the shadow VMCS active on the
>>> current processor. No VMCS should ever be active on more than one
>>> processor. If a VMCS is to be migrated from one processor to
>>> another, software should execute a VMCLEAR for the VMCS on the
>>> first processor before the VMCS is made active on the second
>>> processor.
>>>
>>> We already keep track of ordinary VMCSs that are made active by
>>> VMPTRLD. Extend that tracking to handle shadow VMCSs that are
>>> made active by VM-entry to their parents.
>>>
>>> Signed-off-by: Jim Mattson <jmattson@google.com>
>>> ---
>>> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
>>> @@ -2113,6 +2113,15 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
>>>                      new.control) != old.control);
>>>  }
>>>
>>> +static void record_loaded_vmcs(struct loaded_vmcs *loaded_vmcs, int cpu)
>>> +{
>>> +    if (loaded_vmcs->vmcs) {
>>> +            list_add(&loaded_vmcs->loaded_vmcss_on_cpu_link,
>>> +                     &per_cpu(loaded_vmcss_on_cpu, cpu));
>>> +            loaded_vmcs->cpu = cpu;
>>> +    }
>>> +}
>>> +
>>>  /*
>>>   * Switches to specified vcpu, until a matching vcpu_put(), but assumes
>>>   * vcpu mutex is already taken.
>>> @@ -2124,15 +2133,13 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>>>
>>>      if (!vmm_exclusive)
>>>              kvm_cpu_vmxon(phys_addr);
>>> -    else if (vmx->loaded_vmcs->cpu != cpu)
>>> +    else if (vmx->loaded_vmcs->cpu != cpu) {
>>>              loaded_vmcs_clear(vmx->loaded_vmcs);
>>> +            if (vmx->nested.current_shadow_vmcs.vmcs)
>>> +                    loaded_vmcs_clear(&vmx->nested.current_shadow_vmcs);
>>
>> loaded_vmcs_clear() uses expensive IPI, so would want to do both in one
>> call in future patches as they are always active on the same CPU.
>
> Maybe just move the check for an active shadow vmcs to loaded_vmcs_clear
> and clear it there unconditionally.
>
>> Another possible complication is marking current_shadow_vmcs as active
>> on a cpu only after a successful vmlaunch.
>> (We don't seem to ever vmptrld shadow vmcs explicitly.)
>>
>>> +        }
>>
>> Incorrect whitespace for indentation.
>>
>>>
>>>      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);
>>> -    }
>>> -
>>> -    if (vmx->loaded_vmcs->cpu != cpu) {
>>
>> This condition is nice for performance because a non-current vmcs is
>> usually already active on the same CPU, so we skip all the code below.
>>
>> (This is the only thing that has to be fixed as it regresses non-nested,
>>  the rest are mostly ideas for simplifications.)
>
> I think he wanted to make sure to call vmcs_load after the call
> to crash_disable_local_vmclear() but that should be possible without
> removing the check.
>
> Bandan
>
>>>              struct desc_ptr *gdt = this_cpu_ptr(&host_gdt);
>>>              unsigned long sysenter_esp;
>>>
>>> @@ -2147,11 +2154,15 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>>>               */
>>>              smp_rmb();
>>>
>>> -            list_add(&vmx->loaded_vmcs->loaded_vmcss_on_cpu_link,
>>> -                     &per_cpu(loaded_vmcss_on_cpu, cpu));
>>> +            record_loaded_vmcs(vmx->loaded_vmcs, cpu);
>>
>> Adding and an element to a list multiple times seems invalid, which the
>> condition was also guarding.
>>
>>> +            record_loaded_vmcs(&vmx->nested.current_shadow_vmcs, cpu);
>>
>> current_shadow_vmcs is always active on the same cpu as loaded_vmcs ...
>> I think we could skip the list and just clear current_shadow_vmcs when
>> clearing its loaded_vmcs.
>>
>>>              crash_enable_local_vmclear(cpu);
>>>              local_irq_enable();
>>>
>>> +            per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs;
>>> +            vmcs_load(vmx->loaded_vmcs->vmcs);
>>> +
>>>              /*
>>>               * Linux uses per-cpu TSS and GDT, so set these when switching
>>>               * processors.
>>> @@ -2161,8 +2172,6 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>>>
>>>              rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
>>>              vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
>>> -
>>> -            vmx->loaded_vmcs->cpu = cpu;
>>>      }
>>>
>>>      /* Setup TSC multiplier */
>>> @@ -6812,6 +6821,34 @@ static int nested_vmx_check_vmptr(struct kvm_vcpu *vcpu, int exit_reason,
>>>      return 0;
>>>  }
>>>
>>> +static int setup_shadow_vmcs(struct vcpu_vmx *vmx)
>>> +{
>>> +    struct vmcs *shadow_vmcs;
>>> +    int cpu;
>>> +
>>> +    shadow_vmcs = alloc_vmcs();
>>> +    if (!shadow_vmcs)
>>> +            return -ENOMEM;
>>> +
>>> +    /* mark vmcs as shadow */
>>> +    shadow_vmcs->revision_id |= (1u << 31);
>>> +    /* init shadow vmcs */
>>> +    vmx->nested.current_shadow_vmcs.vmcs = shadow_vmcs;
>>> +    loaded_vmcs_init(&vmx->nested.current_shadow_vmcs);
>>> +
>>> +    cpu = get_cpu();
>>> +    local_irq_disable();
>>> +    crash_disable_local_vmclear(cpu);
>>> +
>>> +    record_loaded_vmcs(&vmx->nested.current_shadow_vmcs, cpu);
>>
>> This could be avoided if we assumed that shadow vmcs is always active on
>> the same vcpu.  The assumption looks rock-solid, because shadow vmcs is
>> activated on vmlaunch and its linking vmcs must be active (and current)
>> on the same CPU.
>>
>>> +
>>> +    crash_enable_local_vmclear(cpu);
>>> +    local_irq_enable();
>>> +    put_cpu();
>>> +
>>> +    return 0;
>>> +}
>>> +
>>>  /*
>>>   * Emulate the VMXON instruction.
>>>   * Currently, we just remember that VMX is active, and do not save or even
>>> @@ -6867,14 +6903,9 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
>>>      }
>>>
>>>      if (enable_shadow_vmcs) {
>>> -            shadow_vmcs = alloc_vmcs();
>>> -            if (!shadow_vmcs)
>>> -                    return -ENOMEM;
>>> -            /* mark vmcs as shadow */
>>> -            shadow_vmcs->revision_id |= (1u << 31);
>>> -            /* init shadow vmcs */
>>> -            vmcs_clear(shadow_vmcs);
>>> -            vmx->nested.current_shadow_vmcs = shadow_vmcs;
>>> +            int ret = setup_shadow_vmcs(vmx);
>>> +            if (ret < 0)
>>> +                    return ret;
>>>      }
>>>
>>>      INIT_LIST_HEAD(&(vmx->nested.vmcs02_pool));

  reply	other threads:[~2016-07-28 13:30 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-15 17:39 [PATCH] kvm: nVMX: Track active shadow VMCSs Jim Mattson
2016-07-16  0:50 ` Bandan Das
2016-07-16 14:50   ` Paolo Bonzini
2016-07-16 19:48     ` Bandan Das
2016-07-19 16:22       ` Jim Mattson
2016-07-22 18:25         ` [PATCH v2] KVM: " Jim Mattson
2016-07-27 20:45           ` Radim Krčmář
2016-07-27 21:53             ` Bandan Das
2016-07-28 13:30               ` Jim Mattson [this message]
2016-07-28 14:01                 ` Radim Krčmář
2016-10-28 15:29         ` [PATCH v2] kvm: nVMX: VMCLEAR an active shadow VMCS after last use Jim Mattson
2016-11-02 17:23           ` Paolo Bonzini
2016-11-02 17:56             ` Jim Mattson
2016-11-02 18:04               ` Paolo Bonzini
2016-07-18 21:30   ` [PATCH] kvm: nVMX: Track active shadow VMCSs Jim Mattson
2016-07-18 23:36     ` Bandan Das
2016-07-19  8:41       ` Paolo Bonzini
2016-07-19 16:13         ` Jim Mattson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CALMp9eQjY9Qg+vJ+8a6=ruA5PV99ykgh7pzNaWoHu65Gbw_-8Q@mail.gmail.com' \
    --to=jmattson@google.com \
    --cc=bsd@redhat.com \
    --cc=dmatlack@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=pfeiner@google.com \
    --cc=rkrcmar@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.