From: Bandan Das <bsd@redhat.com>
To: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: Jim Mattson <jmattson@google.com>,
kvm@vger.kernel.org, pbonzini@redhat.com, dmatlack@google.com,
pfeiner@google.com
Subject: Re: [PATCH v2] KVM: nVMX: Track active shadow VMCSs
Date: Wed, 27 Jul 2016 17:53:05 -0400 [thread overview]
Message-ID: <jpg60rq21fi.fsf@linux.bootlegged.copy> (raw)
In-Reply-To: 20160727204533.GA29177@potion
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));
next prev parent reply other threads:[~2016-07-27 21:53 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 [this message]
2016-07-28 13:30 ` Jim Mattson
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=jpg60rq21fi.fsf@linux.bootlegged.copy \
--to=bsd@redhat.com \
--cc=dmatlack@google.com \
--cc=jmattson@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox