From c88860250e116fb4f782caf26814d49b0f946476 Mon Sep 17 00:00:00 2001 From: Jian Jun Chen Date: Tue, 5 Jul 2022 15:51:32 +0800 Subject: [PATCH] hv: tlfs: add tlfs TSC freq MSR support for WaaG TLFS defined 2 vMSRs which can be used by Windows guest to get the TSC/APIC frequencies from hypervisor. This patch adds the support of HV_X64_MSR_TSC_FREQUENCY/HV_X64_MSR_APIC_FREQUENCY vMSRS whose availability is exposed by CPUID.0x40000003:EAX[bit11] and EDX[bit8]. v1->v2: - revise commit message to highlight that the changes are for WaaG Tracked-On: #7876 Signed-off-by: Jian Jun Chen Reviewed-by: Zhao Yakui Reviewed-by: Fei Li --- hypervisor/arch/x86/guest/hyperv.c | 18 ++++++++++++++++-- hypervisor/arch/x86/guest/vmsr.c | 4 ++++ hypervisor/include/arch/x86/asm/guest/hyperv.h | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/hypervisor/arch/x86/guest/hyperv.c b/hypervisor/arch/x86/guest/hyperv.c index d23647bb2..6cf171fef 100644 --- a/hypervisor/arch/x86/guest/hyperv.c +++ b/hypervisor/arch/x86/guest/hyperv.c @@ -24,6 +24,10 @@ #define CPUID3A_VP_INDEX_MSR (1U << 6U) /* Partition reference TSC MSR (HV_X64_MSR_REFERENCE_TSC) */ #define CPUID3A_REFERENCE_TSC_MSR (1U << 9U) +/* Partition local APIC and TSC frequency registers (HV_X64_MSR_TSC_FREQUENCY/HV_X64_MSR_APIC_FREQUENCY) */ +#define CPUID3A_ACCESS_FREQUENCY_MSRS (1U << 11U) +/* Frequency MSRs available */ +#define CPUID3D_FREQ_MSRS_AVAILABLE (1U << 8U) struct HV_REFERENCE_TSC_PAGE { uint32_t tsc_sequence; @@ -167,6 +171,8 @@ hyperv_wrmsr(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t wval) break; case HV_X64_MSR_VP_INDEX: case HV_X64_MSR_TIME_REF_COUNT: + case HV_X64_MSR_TSC_FREQUENCY: + case HV_X64_MSR_APIC_FREQUENCY: /* read only */ /* fallthrough */ default: @@ -202,6 +208,13 @@ hyperv_rdmsr(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *rval) case HV_X64_MSR_REFERENCE_TSC: *rval = vcpu->vm->arch_vm.hyperv.ref_tsc_page.val64; break; + case HV_X64_MSR_TSC_FREQUENCY: + *rval = get_tsc_khz() * 1000UL; + break; + case HV_X64_MSR_APIC_FREQUENCY: + /* both KVM and XEN hardcode the APIC freq as 1GHz ... */ + *rval = 1000000000UL; + break; default: pr_err("hv: %s: unexpected MSR[0x%x] read", __func__, msr); ret = -1; @@ -264,10 +277,11 @@ hyperv_init_vcpuid_entry(uint32_t leaf, uint32_t subleaf, uint32_t flags, break; case 0x40000003U: /* HV supported feature */ entry->eax = CPUID3A_HYPERCALL_MSR | CPUID3A_VP_INDEX_MSR | - CPUID3A_TIME_REF_COUNT_MSR | CPUID3A_REFERENCE_TSC_MSR; + CPUID3A_TIME_REF_COUNT_MSR | CPUID3A_REFERENCE_TSC_MSR | + CPUID3A_ACCESS_FREQUENCY_MSRS; entry->ebx = 0U; entry->ecx = 0U; - entry->edx = 0U; + entry->edx = CPUID3D_FREQ_MSRS_AVAILABLE; break; case 0x40000004U: /* HV Recommended hypercall usage */ entry->eax = 0U; diff --git a/hypervisor/arch/x86/guest/vmsr.c b/hypervisor/arch/x86/guest/vmsr.c index 9dc1c8eb8..6509d34b0 100644 --- a/hypervisor/arch/x86/guest/vmsr.c +++ b/hypervisor/arch/x86/guest/vmsr.c @@ -581,6 +581,8 @@ int32_t rdmsr_vmexit_handler(struct acrn_vcpu *vcpu) case HV_X64_MSR_VP_INDEX: case HV_X64_MSR_REFERENCE_TSC: case HV_X64_MSR_TIME_REF_COUNT: + case HV_X64_MSR_TSC_FREQUENCY: + case HV_X64_MSR_APIC_FREQUENCY: { err = hyperv_rdmsr(vcpu, msr, &v); break; @@ -943,6 +945,8 @@ int32_t wrmsr_vmexit_handler(struct acrn_vcpu *vcpu) case HV_X64_MSR_VP_INDEX: case HV_X64_MSR_REFERENCE_TSC: case HV_X64_MSR_TIME_REF_COUNT: + case HV_X64_MSR_TSC_FREQUENCY: + case HV_X64_MSR_APIC_FREQUENCY: { err = hyperv_wrmsr(vcpu, msr, v); break; diff --git a/hypervisor/include/arch/x86/asm/guest/hyperv.h b/hypervisor/include/arch/x86/asm/guest/hyperv.h index 0bc9b1255..a55c29cfd 100644 --- a/hypervisor/include/arch/x86/asm/guest/hyperv.h +++ b/hypervisor/include/arch/x86/asm/guest/hyperv.h @@ -16,6 +16,8 @@ #define HV_X64_MSR_TIME_REF_COUNT 0x40000020U #define HV_X64_MSR_REFERENCE_TSC 0x40000021U +#define HV_X64_MSR_TSC_FREQUENCY 0x40000022U +#define HV_X64_MSR_APIC_FREQUENCY 0x40000023U union hyperv_ref_tsc_page_msr { uint64_t val64;