On Mon, Jul 24, 2017 at 7:48 PM, Paolo Bonzini <pbonzini@xxxxxxxxxx> wrote: > On 17/07/2017 15:28, Ladi Prosek wrote: >> It has been experimentally confirmed that supporting these two MSRs is one >> of the necessary conditions for nested Hyper-V to use the TSC page. Modern >> Windows guests are noticeably slower when they fall back to reading >> timestamps from the HV_X64_MSR_TIME_REF_COUNT MSR instead of using the TSC >> page. >> >> The newly supported MSRs are advertised with the AccessFrequencyRegs >> partition privilege flag and CPUID.40000003H:EDX[8] "Support for >> determining timer frequencies is available" (both outside of the scope of >> this KVM patch). >> >> Hypervisor Top Level Functional Specification version 5.0b does not >> explicitly mark these MSRs as partition wide. This is, however, implied by >> the way Windows uses them (one read on Hyper-V startup regardless of the >> number of VCPUs) as well as our implementation. >> >> Signed-off-by: Ladi Prosek <lprosek@xxxxxxxxxx> > > No opposition to adding these registers, but QEMU must only present them > if the TSC frequency is stable across migration and known, that is > > /* TSC clock must be stable and known for this feature. */ > && ((env->features[FEAT_8000_0007_EDX] & CPUID_APM_INVTSC) > || env->user_tsc_khz != 0) > && env->tsc_khz != 0 > > (A similar condition is already used for cpu->vmware_cpuid_freq). Will do! Hyper-V won't initialize L2's TSC pages without CPUID_APM_INVTSC anyway. > Paolo > >> --- >> arch/x86/kvm/hyperv.c | 8 ++++++++ >> arch/x86/kvm/lapic.c | 2 -- >> arch/x86/kvm/lapic.h | 3 +++ >> arch/x86/kvm/x86.c | 1 + >> 4 files changed, 12 insertions(+), 2 deletions(-) >> >> diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c >> index ebae57a..c93ed3a 100644 >> --- a/arch/x86/kvm/hyperv.c >> +++ b/arch/x86/kvm/hyperv.c >> @@ -707,6 +707,8 @@ static bool kvm_hv_msr_partition_wide(u32 msr) >> case HV_X64_MSR_HYPERCALL: >> 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: >> case HV_X64_MSR_CRASH_CTL: >> case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4: >> case HV_X64_MSR_RESET: >> @@ -1065,6 +1067,12 @@ static int kvm_hv_get_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) >> case HV_X64_MSR_REFERENCE_TSC: >> data = hv->hv_tsc_page; >> break; >> + case HV_X64_MSR_TSC_FREQUENCY: >> + data = (u64)tsc_khz * 1000; >> + break; >> + case HV_X64_MSR_APIC_FREQUENCY: >> + data = APIC_BUS_FREQUENCY; >> + break; >> case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4: >> return kvm_hv_msr_get_crash_data(vcpu, >> msr - HV_X64_MSR_CRASH_P0, >> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c >> index 2819d4c..41110c4 100644 >> --- a/arch/x86/kvm/lapic.c >> +++ b/arch/x86/kvm/lapic.c >> @@ -54,8 +54,6 @@ >> #define PRIu64 "u" >> #define PRIo64 "o" >> >> -#define APIC_BUS_CYCLE_NS 1 >> - >> /* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */ >> #define apic_debug(fmt, arg...) >> >> diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h >> index 29caa2c..215721e1 100644 >> --- a/arch/x86/kvm/lapic.h >> +++ b/arch/x86/kvm/lapic.h >> @@ -12,6 +12,9 @@ >> #define KVM_APIC_SHORT_MASK 0xc0000 >> #define KVM_APIC_DEST_MASK 0x800 >> >> +#define APIC_BUS_CYCLE_NS 1 >> +#define APIC_BUS_FREQUENCY (1000000000ULL / APIC_BUS_CYCLE_NS) >> + >> struct kvm_timer { >> struct hrtimer timer; >> s64 period; /* unit: ns */ >> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c >> index 6c7266f..94a2eb5 100644 >> --- a/arch/x86/kvm/x86.c >> +++ b/arch/x86/kvm/x86.c >> @@ -990,6 +990,7 @@ static u32 emulated_msrs[] = { >> MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW, >> HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, >> HV_X64_MSR_TIME_REF_COUNT, HV_X64_MSR_REFERENCE_TSC, >> + HV_X64_MSR_TSC_FREQUENCY, HV_X64_MSR_APIC_FREQUENCY, >> HV_X64_MSR_CRASH_P0, HV_X64_MSR_CRASH_P1, HV_X64_MSR_CRASH_P2, >> HV_X64_MSR_CRASH_P3, HV_X64_MSR_CRASH_P4, HV_X64_MSR_CRASH_CTL, >> HV_X64_MSR_RESET, >