Avi Kivity wrote:
> On 05/06/2010 11:45 AM, Xu, Dongxiao wrote:
>> From: Dongxiao Xu<[email protected]>
>>
>> Originally VMCLEAR/VMPTRLD is called on vcpu migration. To
>> support hosted VMM coexistance, VMCLEAR is executed on vcpu
>> schedule out, and VMPTRLD is executed on vcpu schedule in.
>> This could also eliminate the IPI when doing VMCLEAR.
>>
>>
>>
>> +static int __read_mostly vmm_coexistence;
>> +module_param(vmm_coexistence, bool, S_IRUGO);
>>
>
> I think we can call it 'exclusive' defaulting to true.
I will change it in next version.
>
>> +
>> #define KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST
>> \
>> (X86_CR0_WP | X86_CR0_NE | X86_CR0_NW | X86_CR0_CD)
>> #define KVM_GUEST_CR0_MASK \
>> @@ -222,6 +225,7 @@ static u64 host_efer;
>>
>> static void ept_save_pdptrs(struct kvm_vcpu *vcpu);
>>
>> +static void vmx_flush_tlb(struct kvm_vcpu *vcpu);
>> /*
>> * Keep MSR_K6_STAR at the end, as setup_msrs() will try to
>> optimize it
>> * away by decrementing the array size.
>> @@ -784,25 +788,31 @@ static void vmx_vcpu_load(struct kvm_vcpu
>> *vcpu, int cpu) struct vcpu_vmx *vmx = to_vmx(vcpu);
>> u64 tsc_this, delta, new_offset;
>>
>> - if (vcpu->cpu != cpu) {
>> - vcpu_clear(vmx);
>> - kvm_migrate_timers(vcpu);
>> + if (vmm_coexistence) {
>> + vmcs_load(vmx->vmcs);
>> set_bit(KVM_REQ_TLB_FLUSH,&vcpu->requests);
>> - local_irq_disable();
>> - list_add(&vmx->local_vcpus_link,
>> - &per_cpu(vcpus_on_cpu, cpu));
>> - local_irq_enable();
>> - }
>> + } else {
>> + if (vcpu->cpu != cpu) {
>> + vcpu_clear(vmx);
>> + set_bit(KVM_REQ_TLB_FLUSH,&vcpu->requests);
>> + local_irq_disable();
>> + list_add(&vmx->local_vcpus_link,
>> + &per_cpu(vcpus_on_cpu, cpu));
>> + local_irq_enable();
>> + }
>>
>> - if (per_cpu(current_vmcs, cpu) != vmx->vmcs) {
>> - per_cpu(current_vmcs, cpu) = vmx->vmcs;
>> - vmcs_load(vmx->vmcs);
>> + if (per_cpu(current_vmcs, cpu) != vmx->vmcs) {
>> + per_cpu(current_vmcs, cpu) = vmx->vmcs;
>> + vmcs_load(vmx->vmcs);
>> + }
>> }
>>
>
> Please keep the exclusive use code as it is, and just add !exclusive
> cases. For example. the current_vmcs test will always fail since
> current_vmcs will be set to NULL on vmx_vcpu_put, so we can have just
> one vmcs_load().
Thanks for the suggestion.
>
>>
>> @@ -829,7 +839,14 @@ static void vmx_vcpu_load(struct kvm_vcpu
>> *vcpu, int cpu)
>>
>> static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
>> {
>> + struct vcpu_vmx *vmx = to_vmx(vcpu);
>> +
>> __vmx_load_host_state(to_vmx(vcpu));
>> + if (vmm_coexistence) {
>> + vmcs_clear(vmx->vmcs);
>> + rdtscll(vmx->vcpu.arch.host_tsc);
>> + vmx->launched = 0;
>>
>
> This code is also duplicated. Please refactor to avoid duplication.
Thanks.
>
>> + }
>> }
>>
>> static void vmx_fpu_activate(struct kvm_vcpu *vcpu)
>> @@ -1280,7 +1297,8 @@ static void kvm_cpu_vmxoff(void)
>>
>> static void hardware_disable(void *garbage)
>> {
>> - vmclear_local_vcpus();
>> + if (!vmm_coexistence)
>> + vmclear_local_vcpus();
>> kvm_cpu_vmxoff();
>> write_cr4(read_cr4()& ~X86_CR4_VMXE);
>> }
>> @@ -3927,7 +3945,8 @@ static void vmx_free_vmcs(struct kvm_vcpu
>> *vcpu) struct vcpu_vmx *vmx = to_vmx(vcpu);
>>
>> if (vmx->vmcs) {
>> - vcpu_clear(vmx);
>> + if (!vmm_coexistence)
>> + vcpu_clear(vmx);
>>
>
> What's wrong with doing this unconditionally?
The change should have beed put in PATCH 3/3.
This judgement is to avoid calling vcpu_clear() after kvm_cpu_vmxoff();
However it will not appear in next version since I will set vcpu->cpu=-1
in vmx_vcpu_put() !vmm_exclusive case, so that vcpu_clear() will not
executed actually.
>
>> free_vmcs(vmx->vmcs);
>> vmx->vmcs = NULL;
>> }
>> @@ -3969,13 +3988,20 @@ static struct kvm_vcpu
>> *vmx_create_vcpu(struct kvm *kvm, unsigned int id) if
>> (!vmx->vmcs) goto free_msrs;
>>
>> - vmcs_clear(vmx->vmcs);
>> -
>> - cpu = get_cpu();
>> - vmx_vcpu_load(&vmx->vcpu, cpu);
>> - err = vmx_vcpu_setup(vmx);
>> - vmx_vcpu_put(&vmx->vcpu);
>> - put_cpu();
>> + if (vmm_coexistence) {
>> + preempt_disable();
>> + vmcs_load(vmx->vmcs);
>> + err = vmx_vcpu_setup(vmx);
>> + vmcs_clear(vmx->vmcs);
>> + preempt_enable();
>>
>
> Why won't the normal sequence work?
Yes you are right.
>
>> + } else {
>> + vmcs_clear(vmx->vmcs);
>> + cpu = get_cpu();
>> + vmx_vcpu_load(&vmx->vcpu, cpu);
>> + err = vmx_vcpu_setup(vmx);
>> + vmx_vcpu_put(&vmx->vcpu);
>> + put_cpu();
>> + }
>> if (err)
>> goto free_vmcs;
>> if (vm_need_virtualize_apic_accesses(kvm))
>> @@ -4116,6 +4142,8 @@ static void vmx_cpuid_update(struct kvm_vcpu
>> *vcpu)
>>
>> vmx->rdtscp_enabled = false;
>> if (vmx_rdtscp_supported()) {
>> + if (vmm_coexistence)
>> + vmcs_load(vmx->vmcs);
>>
>
> Don't understand why this is needed. Shouldn't vmx_vcpu_load() load
> the vmptr?
This change also should be put in PATCH 3/3, to avoid operating VMCS when vmx
is off.
I will change it in next version.
Thanks,
Dongxiao
>
>> exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
>> if (exec_control& SECONDARY_EXEC_RDTSCP) {
>> best = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
>> @@ -4127,6 +4155,8 @@ static void vmx_cpuid_update(struct kvm_vcpu
>> *vcpu)
>> exec_control); }
>> }
>> + if (vmm_coexistence)
>> + vmcs_clear(vmx->vmcs);
>> }
>> }
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html