The lazy tsc deadline hasn't work in this version but just tranmit the physical addrss from gust to host sdie. - Add data structure in both guest and host side - If feature is enabled, set msr of lazy tscdeadline when guest cpu is initialized and clear it when cpu is offlined. - Add msr set/get emulation code in host side. Signed-off-by: Li Shujin <arkinjob@xxxxxxxxxxx> Signed-off-by: Wang Jianchao <jianchwa@xxxxxxxxxxx> --- arch/x86/include/asm/kvm_host.h | 6 ++++++ arch/x86/kernel/kvm.c | 13 +++++++++++++ arch/x86/kvm/x86.c | 13 +++++++++++++ 3 files changed, 32 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 28bd383..439e4a7 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -713,6 +713,10 @@ struct kvm_queued_exception { bool has_payload; }; +struct kvm_host_lazy_tscdeadline { + u64 msr_val; +}; + struct kvm_vcpu_arch { /* * rip and regs accesses must go through @@ -944,6 +948,8 @@ struct kvm_vcpu_arch { struct gfn_to_hva_cache data; } pv_eoi; + struct kvm_host_lazy_tscdeadline lazy_tscdeadline; + u64 msr_kvm_poll_control; /* set at EPT violation at this point */ diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 1cceac5..91eb333 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -67,6 +67,7 @@ early_param("no-steal-acc", parse_no_stealacc); static DEFINE_PER_CPU_DECRYPTED(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64); DEFINE_PER_CPU_DECRYPTED(struct kvm_steal_time, steal_time) __aligned(64) __visible; +DEFINE_PER_CPU_DECRYPTED(struct kvm_lazy_tscdeadline, kvm_lazy_tscdeadline) __aligned(64) __visible; static int has_steal_clock = 0; static int has_guest_poll = 0; @@ -379,6 +380,16 @@ static void kvm_guest_cpu_init(void) if (has_steal_clock) kvm_register_steal_time(); + + if (kvm_para_has_feature(KVM_FEATURE_LAZY_TSCDEADLINE)) { + struct kvm_lazy_tscdeadline *ptr = this_cpu_ptr(&kvm_lazy_tscdeadline); + unsigned long pa; + + BUILD_BUG_ON(__alignof__(kvm_lazy_tscdeadline) < 4); + memset(ptr, 0, sizeof(*ptr)); + pa = slow_virt_to_phys(ptr) | KVM_MSR_ENABLED; + wrmsrl(MSR_KVM_LAZY_TSCDEADLINE, pa); + } } static void kvm_pv_disable_apf(void) @@ -452,6 +463,8 @@ static void kvm_guest_cpu_offline(bool shutdown) if (kvm_para_has_feature(KVM_FEATURE_MIGRATION_CONTROL)) wrmsrl(MSR_KVM_MIGRATION_CONTROL, 0); kvm_pv_disable_apf(); + if (kvm_para_has_feature(KVM_FEATURE_LAZY_TSCDEADLINE)) + wrmsrl(MSR_KVM_LAZY_TSCDEADLINE, 0); if (!shutdown) apf_task_wake_all(); kvmclock_disable(); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index a6b9bea..dbbae8f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1551,6 +1551,7 @@ static const u32 emulated_msrs_all[] = { MSR_K7_HWCR, MSR_KVM_POLL_CONTROL, + MSR_KVM_LAZY_TSCDEADLINE, }; static u32 emulated_msrs[ARRAY_SIZE(emulated_msrs_all)]; @@ -3873,7 +3874,13 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) vcpu->arch.msr_kvm_poll_control = data; break; + case MSR_KVM_LAZY_TSCDEADLINE: + if (!guest_pv_has(vcpu, KVM_FEATURE_LAZY_TSCDEADLINE)) + return 1; + + vcpu->arch.lazy_tscdeadline.msr_val = data; + break; case MSR_IA32_MCG_CTL: case MSR_IA32_MCG_STATUS: case MSR_IA32_MC0_CTL ... MSR_IA32_MCx_CTL(KVM_MAX_MCE_BANKS) - 1: @@ -4229,6 +4236,12 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) msr_info->data = vcpu->arch.msr_kvm_poll_control; break; + case MSR_KVM_LAZY_TSCDEADLINE: + if (!guest_pv_has(vcpu, KVM_FEATURE_LAZY_TSCDEADLINE)) + return 1; + + msr_info->data = vcpu->arch.lazy_tscdeadline.msr_val; + break; case MSR_IA32_P5_MC_ADDR: case MSR_IA32_P5_MC_TYPE: case MSR_IA32_MCG_CAP: -- 2.7.4