i386/kvm: add support for Hyper-V reenlightenment MSRs
KVM recently gained support for Hyper-V Reenlightenment MSRs which are required to make KVM-on-Hyper-V enable TSC page clocksource to its guests when INVTSC is not passed to it (and it is not passed by default in Qemu as it effectively blocks migration). Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Message-Id: <20180411115036.31832-2-vkuznets@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									45b47130f4
								
							
						
					
					
						commit
						ba6a4fd95d
					
				| @ -416,7 +416,8 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { | ||||
|             NULL /* hv_vpindex_access */, NULL /* hv_msr_reset_access */, | ||||
|             NULL /* hv_msr_stats_access */, NULL /* hv_reftsc_access */, | ||||
|             NULL /* hv_msr_idle_access */, NULL /* hv_msr_frequency_access */, | ||||
|             NULL, NULL, NULL, NULL, | ||||
|             NULL /* hv_msr_debug_access */, NULL /* hv_msr_reenlightenment_access */, | ||||
|             NULL, NULL, | ||||
|             NULL, NULL, NULL, NULL, | ||||
|             NULL, NULL, NULL, NULL, | ||||
|             NULL, NULL, NULL, NULL, | ||||
| @ -4770,6 +4771,7 @@ static Property x86_cpu_properties[] = { | ||||
|     DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false), | ||||
|     DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false), | ||||
|     DEFINE_PROP_BOOL("hv-frequencies", X86CPU, hyperv_frequencies, false), | ||||
|     DEFINE_PROP_BOOL("hv-reenlightenment", X86CPU, hyperv_reenlightenment, false), | ||||
|     DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true), | ||||
|     DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false), | ||||
|     DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true), | ||||
|  | ||||
| @ -1174,6 +1174,9 @@ typedef struct CPUX86State { | ||||
|     uint64_t msr_hv_synic_sint[HV_SINT_COUNT]; | ||||
|     uint64_t msr_hv_stimer_config[HV_STIMER_COUNT]; | ||||
|     uint64_t msr_hv_stimer_count[HV_STIMER_COUNT]; | ||||
|     uint64_t msr_hv_reenlightenment_control; | ||||
|     uint64_t msr_hv_tsc_emulation_control; | ||||
|     uint64_t msr_hv_tsc_emulation_status; | ||||
| 
 | ||||
|     uint64_t msr_rtit_ctrl; | ||||
|     uint64_t msr_rtit_status; | ||||
| @ -1297,6 +1300,7 @@ struct X86CPU { | ||||
|     bool hyperv_synic; | ||||
|     bool hyperv_stimer; | ||||
|     bool hyperv_frequencies; | ||||
|     bool hyperv_reenlightenment; | ||||
|     bool check_cpuid; | ||||
|     bool enforce_cpuid; | ||||
|     bool expose_kvm; | ||||
|  | ||||
| @ -35,7 +35,7 @@ | ||||
| #define HV_RESET_AVAILABLE           (1u << 7) | ||||
| #define HV_REFERENCE_TSC_AVAILABLE   (1u << 9) | ||||
| #define HV_ACCESS_FREQUENCY_MSRS     (1u << 11) | ||||
| 
 | ||||
| #define HV_ACCESS_REENLIGHTENMENTS_CONTROL  (1u << 13) | ||||
| 
 | ||||
| /*
 | ||||
|  * HV_CPUID_FEATURES.EDX bits | ||||
| @ -129,6 +129,13 @@ | ||||
| #define HV_X64_MSR_CRASH_CTL                    0x40000105 | ||||
| #define HV_CRASH_CTL_NOTIFY                     (1ull << 63) | ||||
| 
 | ||||
| /*
 | ||||
|  * Reenlightenment notification MSRs | ||||
|  */ | ||||
| #define HV_X64_MSR_REENLIGHTENMENT_CONTROL      0x40000106 | ||||
| #define HV_X64_MSR_TSC_EMULATION_CONTROL        0x40000107 | ||||
| #define HV_X64_MSR_TSC_EMULATION_STATUS         0x40000108 | ||||
| 
 | ||||
| /*
 | ||||
|  * Hypercall status code | ||||
|  */ | ||||
|  | ||||
| @ -90,6 +90,7 @@ static bool has_msr_hv_runtime; | ||||
| static bool has_msr_hv_synic; | ||||
| static bool has_msr_hv_stimer; | ||||
| static bool has_msr_hv_frequencies; | ||||
| static bool has_msr_hv_reenlightenment; | ||||
| static bool has_msr_xss; | ||||
| static bool has_msr_spec_ctrl; | ||||
| static bool has_msr_smi_count; | ||||
| @ -583,7 +584,8 @@ static bool hyperv_enabled(X86CPU *cpu) | ||||
|             cpu->hyperv_vpindex || | ||||
|             cpu->hyperv_runtime || | ||||
|             cpu->hyperv_synic || | ||||
|             cpu->hyperv_stimer); | ||||
|             cpu->hyperv_stimer || | ||||
|             cpu->hyperv_reenlightenment); | ||||
| } | ||||
| 
 | ||||
| static int kvm_arch_set_tsc_khz(CPUState *cs) | ||||
| @ -669,6 +671,16 @@ static int hyperv_handle_properties(CPUState *cs) | ||||
|         } | ||||
|         env->features[FEAT_HYPERV_EDX] |= HV_GUEST_CRASH_MSR_AVAILABLE; | ||||
|     } | ||||
|     if (cpu->hyperv_reenlightenment) { | ||||
|         if (!has_msr_hv_reenlightenment) { | ||||
|             fprintf(stderr, | ||||
|                     "Hyper-V Reenlightenment MSRs " | ||||
|                     "(requested by 'hv-reenlightenment' cpu flag) " | ||||
|                     "are not supported by kernel\n"); | ||||
|             return -ENOSYS; | ||||
|         } | ||||
|         env->features[FEAT_HYPERV_EAX] |= HV_ACCESS_REENLIGHTENMENTS_CONTROL; | ||||
|     } | ||||
|     env->features[FEAT_HYPERV_EDX] |= HV_CPU_DYNAMIC_PARTITIONING_AVAILABLE; | ||||
|     if (cpu->hyperv_reset) { | ||||
|         if (!has_msr_hv_reset) { | ||||
| @ -1215,6 +1227,9 @@ static int kvm_get_supported_msrs(KVMState *s) | ||||
|                 case HV_X64_MSR_TSC_FREQUENCY: | ||||
|                     has_msr_hv_frequencies = true; | ||||
|                     break; | ||||
|                 case HV_X64_MSR_REENLIGHTENMENT_CONTROL: | ||||
|                     has_msr_hv_reenlightenment = true; | ||||
|                     break; | ||||
|                 case MSR_IA32_SPEC_CTRL: | ||||
|                     has_msr_spec_ctrl = true; | ||||
|                     break; | ||||
| @ -1778,6 +1793,14 @@ static int kvm_put_msrs(X86CPU *cpu, int level) | ||||
|                 kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC, | ||||
|                                   env->msr_hv_tsc); | ||||
|             } | ||||
|             if (cpu->hyperv_reenlightenment) { | ||||
|                 kvm_msr_entry_add(cpu, HV_X64_MSR_REENLIGHTENMENT_CONTROL, | ||||
|                                   env->msr_hv_reenlightenment_control); | ||||
|                 kvm_msr_entry_add(cpu, HV_X64_MSR_TSC_EMULATION_CONTROL, | ||||
|                                   env->msr_hv_tsc_emulation_control); | ||||
|                 kvm_msr_entry_add(cpu, HV_X64_MSR_TSC_EMULATION_STATUS, | ||||
|                                   env->msr_hv_tsc_emulation_status); | ||||
|             } | ||||
|         } | ||||
|         if (cpu->hyperv_vapic) { | ||||
|             kvm_msr_entry_add(cpu, HV_X64_MSR_APIC_ASSIST_PAGE, | ||||
| @ -2140,6 +2163,11 @@ static int kvm_get_msrs(X86CPU *cpu) | ||||
|     if (cpu->hyperv_time) { | ||||
|         kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC, 0); | ||||
|     } | ||||
|     if (cpu->hyperv_reenlightenment) { | ||||
|         kvm_msr_entry_add(cpu, HV_X64_MSR_REENLIGHTENMENT_CONTROL, 0); | ||||
|         kvm_msr_entry_add(cpu, HV_X64_MSR_TSC_EMULATION_CONTROL, 0); | ||||
|         kvm_msr_entry_add(cpu, HV_X64_MSR_TSC_EMULATION_STATUS, 0); | ||||
|     } | ||||
|     if (has_msr_hv_crash) { | ||||
|         int j; | ||||
| 
 | ||||
| @ -2397,6 +2425,15 @@ static int kvm_get_msrs(X86CPU *cpu) | ||||
|             env->msr_hv_stimer_count[(index - HV_X64_MSR_STIMER0_COUNT)/2] = | ||||
|                                 msrs[i].data; | ||||
|             break; | ||||
|         case HV_X64_MSR_REENLIGHTENMENT_CONTROL: | ||||
|             env->msr_hv_reenlightenment_control = msrs[i].data; | ||||
|             break; | ||||
|         case HV_X64_MSR_TSC_EMULATION_CONTROL: | ||||
|             env->msr_hv_tsc_emulation_control = msrs[i].data; | ||||
|             break; | ||||
|         case HV_X64_MSR_TSC_EMULATION_STATUS: | ||||
|             env->msr_hv_tsc_emulation_status = msrs[i].data; | ||||
|             break; | ||||
|         case MSR_MTRRdefType: | ||||
|             env->mtrr_deftype = msrs[i].data; | ||||
|             break; | ||||
|  | ||||
| @ -713,6 +713,29 @@ static const VMStateDescription vmstate_msr_hyperv_stimer = { | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| static bool hyperv_reenlightenment_enable_needed(void *opaque) | ||||
| { | ||||
|     X86CPU *cpu = opaque; | ||||
|     CPUX86State *env = &cpu->env; | ||||
| 
 | ||||
|     return env->msr_hv_reenlightenment_control != 0 || | ||||
|         env->msr_hv_tsc_emulation_control != 0 || | ||||
|         env->msr_hv_tsc_emulation_status != 0; | ||||
| } | ||||
| 
 | ||||
| static const VMStateDescription vmstate_msr_hyperv_reenlightenment = { | ||||
|     .name = "cpu/msr_hyperv_reenlightenment", | ||||
|     .version_id = 1, | ||||
|     .minimum_version_id = 1, | ||||
|     .needed = hyperv_reenlightenment_enable_needed, | ||||
|     .fields = (VMStateField[]) { | ||||
|         VMSTATE_UINT64(env.msr_hv_reenlightenment_control, X86CPU), | ||||
|         VMSTATE_UINT64(env.msr_hv_tsc_emulation_control, X86CPU), | ||||
|         VMSTATE_UINT64(env.msr_hv_tsc_emulation_status, X86CPU), | ||||
|         VMSTATE_END_OF_LIST() | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| static bool avx512_needed(void *opaque) | ||||
| { | ||||
|     X86CPU *cpu = opaque; | ||||
| @ -1005,6 +1028,7 @@ VMStateDescription vmstate_x86_cpu = { | ||||
|         &vmstate_msr_hyperv_runtime, | ||||
|         &vmstate_msr_hyperv_synic, | ||||
|         &vmstate_msr_hyperv_stimer, | ||||
|         &vmstate_msr_hyperv_reenlightenment, | ||||
|         &vmstate_avx512, | ||||
|         &vmstate_xss, | ||||
|         &vmstate_tsc_khz, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Vitaly Kuznetsov
						Vitaly Kuznetsov