target-i386/kvm: Hyper-V SynIC timers MSR's support
Hyper-V SynIC timers are host timers that are configurable by guest through corresponding MSR's (HV_X64_MSR_STIMER*). Guest setup and use fired by host events(SynIC interrupt and appropriate timer expiration message) as guest clock events. The state of Hyper-V SynIC timers are stored in corresponding MSR's. This patch seria implements such MSR's support and migration. Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com> CC: Paolo Bonzini <pbonzini@redhat.com> CC: Richard Henderson <rth@twiddle.net> CC: Eduardo Habkost <ehabkost@redhat.com> CC: "Andreas Färber" <afaerber@suse.de> CC: Marcelo Tosatti <mtosatti@redhat.com> CC: Denis V. Lunev <den@openvz.org> CC: Roman Kagan <rkagan@virtuozzo.com> CC: kvm@vger.kernel.org Message-Id: <1448464885-8300-3-git-send-email-asmetanin@virtuozzo.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									b67dbb7070
								
							
						
					
					
						commit
						ff99aa64b1
					
				| @ -95,6 +95,7 @@ typedef struct X86CPU { | ||||
|     bool hyperv_vpindex; | ||||
|     bool hyperv_runtime; | ||||
|     bool hyperv_synic; | ||||
|     bool hyperv_stimer; | ||||
|     bool check_cpuid; | ||||
|     bool enforce_cpuid; | ||||
|     bool expose_kvm; | ||||
|  | ||||
| @ -3147,6 +3147,7 @@ static Property x86_cpu_properties[] = { | ||||
|     DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false), | ||||
|     DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false), | ||||
|     DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false), | ||||
|     DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, 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), | ||||
|  | ||||
| @ -925,6 +925,8 @@ typedef struct CPUX86State { | ||||
|     uint64_t msr_hv_synic_evt_page; | ||||
|     uint64_t msr_hv_synic_msg_page; | ||||
|     uint64_t msr_hv_synic_sint[HV_SYNIC_SINT_COUNT]; | ||||
|     uint64_t msr_hv_stimer_config[HV_SYNIC_STIMER_COUNT]; | ||||
|     uint64_t msr_hv_stimer_count[HV_SYNIC_STIMER_COUNT]; | ||||
| 
 | ||||
|     /* exception/interrupt handling */ | ||||
|     int error_code; | ||||
|  | ||||
| @ -90,6 +90,7 @@ static bool has_msr_hv_reset; | ||||
| static bool has_msr_hv_vpindex; | ||||
| static bool has_msr_hv_runtime; | ||||
| static bool has_msr_hv_synic; | ||||
| static bool has_msr_hv_stimer; | ||||
| static bool has_msr_mtrr; | ||||
| static bool has_msr_xss; | ||||
| 
 | ||||
| @ -526,7 +527,8 @@ static bool hyperv_enabled(X86CPU *cpu) | ||||
|             cpu->hyperv_reset || | ||||
|             cpu->hyperv_vpindex || | ||||
|             cpu->hyperv_runtime || | ||||
|             cpu->hyperv_synic); | ||||
|             cpu->hyperv_synic || | ||||
|             cpu->hyperv_stimer); | ||||
| } | ||||
| 
 | ||||
| static Error *invtsc_mig_blocker; | ||||
| @ -630,6 +632,13 @@ int kvm_arch_init_vcpu(CPUState *cs) | ||||
|                 env->msr_hv_synic_sint[sint] = HV_SYNIC_SINT_MASKED; | ||||
|             } | ||||
|         } | ||||
|         if (cpu->hyperv_stimer) { | ||||
|             if (!has_msr_hv_stimer) { | ||||
|                 fprintf(stderr, "Hyper-V timers aren't supported by kernel\n"); | ||||
|                 return -ENOSYS; | ||||
|             } | ||||
|             c->eax |= HV_X64_MSR_SYNTIMER_AVAILABLE; | ||||
|         } | ||||
|         c = &cpuid_data.entries[cpuid_i++]; | ||||
|         c->function = HYPERV_CPUID_ENLIGHTMENT_INFO; | ||||
|         if (cpu->hyperv_relaxed_timing) { | ||||
| @ -980,6 +989,10 @@ static int kvm_get_supported_msrs(KVMState *s) | ||||
|                     has_msr_hv_synic = true; | ||||
|                     continue; | ||||
|                 } | ||||
|                 if (kvm_msr_list->indices[i] == HV_X64_MSR_STIMER0_CONFIG) { | ||||
|                     has_msr_hv_stimer = true; | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -1558,6 +1571,19 @@ static int kvm_put_msrs(X86CPU *cpu, int level) | ||||
|                                   env->msr_hv_synic_sint[j]); | ||||
|             } | ||||
|         } | ||||
|         if (has_msr_hv_stimer) { | ||||
|             int j; | ||||
| 
 | ||||
|             for (j = 0; j < ARRAY_SIZE(env->msr_hv_stimer_config); j++) { | ||||
|                 kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_STIMER0_CONFIG + j*2, | ||||
|                                 env->msr_hv_stimer_config[j]); | ||||
|             } | ||||
| 
 | ||||
|             for (j = 0; j < ARRAY_SIZE(env->msr_hv_stimer_count); j++) { | ||||
|                 kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_STIMER0_COUNT + j*2, | ||||
|                                 env->msr_hv_stimer_count[j]); | ||||
|             } | ||||
|         } | ||||
|         if (has_msr_mtrr) { | ||||
|             kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype); | ||||
|             kvm_msr_entry_set(&msrs[n++], | ||||
| @ -1937,6 +1963,14 @@ static int kvm_get_msrs(X86CPU *cpu) | ||||
|             msrs[n++].index = msr; | ||||
|         } | ||||
|     } | ||||
|     if (has_msr_hv_stimer) { | ||||
|         uint32_t msr; | ||||
| 
 | ||||
|         for (msr = HV_X64_MSR_STIMER0_CONFIG; msr <= HV_X64_MSR_STIMER3_COUNT; | ||||
|              msr++) { | ||||
|             msrs[n++].index = msr; | ||||
|         } | ||||
|     } | ||||
|     if (has_msr_mtrr) { | ||||
|         msrs[n++].index = MSR_MTRRdefType; | ||||
|         msrs[n++].index = MSR_MTRRfix64K_00000; | ||||
| @ -2108,6 +2142,20 @@ static int kvm_get_msrs(X86CPU *cpu) | ||||
|         case HV_X64_MSR_SINT0 ... HV_X64_MSR_SINT15: | ||||
|             env->msr_hv_synic_sint[index - HV_X64_MSR_SINT0] = msrs[i].data; | ||||
|             break; | ||||
|         case HV_X64_MSR_STIMER0_CONFIG: | ||||
|         case HV_X64_MSR_STIMER1_CONFIG: | ||||
|         case HV_X64_MSR_STIMER2_CONFIG: | ||||
|         case HV_X64_MSR_STIMER3_CONFIG: | ||||
|             env->msr_hv_stimer_config[(index - HV_X64_MSR_STIMER0_CONFIG)/2] = | ||||
|                                 msrs[i].data; | ||||
|             break; | ||||
|         case HV_X64_MSR_STIMER0_COUNT: | ||||
|         case HV_X64_MSR_STIMER1_COUNT: | ||||
|         case HV_X64_MSR_STIMER2_COUNT: | ||||
|         case HV_X64_MSR_STIMER3_COUNT: | ||||
|             env->msr_hv_stimer_count[(index - HV_X64_MSR_STIMER0_COUNT)/2] = | ||||
|                                 msrs[i].data; | ||||
|             break; | ||||
|         case MSR_MTRRdefType: | ||||
|             env->mtrr_deftype = msrs[i].data; | ||||
|             break; | ||||
|  | ||||
| @ -746,6 +746,34 @@ static const VMStateDescription vmstate_msr_hyperv_synic = { | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| static bool hyperv_stimer_enable_needed(void *opaque) | ||||
| { | ||||
|     X86CPU *cpu = opaque; | ||||
|     CPUX86State *env = &cpu->env; | ||||
|     int i; | ||||
| 
 | ||||
|     for (i = 0; i < ARRAY_SIZE(env->msr_hv_stimer_config); i++) { | ||||
|         if (env->msr_hv_stimer_config[i] || env->msr_hv_stimer_count[i]) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| static const VMStateDescription vmstate_msr_hyperv_stimer = { | ||||
|     .name = "cpu/msr_hyperv_stimer", | ||||
|     .version_id = 1, | ||||
|     .minimum_version_id = 1, | ||||
|     .needed = hyperv_stimer_enable_needed, | ||||
|     .fields = (VMStateField[]) { | ||||
|         VMSTATE_UINT64_ARRAY(env.msr_hv_stimer_config, | ||||
|                              X86CPU, HV_SYNIC_STIMER_COUNT), | ||||
|         VMSTATE_UINT64_ARRAY(env.msr_hv_stimer_count, | ||||
|                              X86CPU, HV_SYNIC_STIMER_COUNT), | ||||
|         VMSTATE_END_OF_LIST() | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| static bool avx512_needed(void *opaque) | ||||
| { | ||||
|     X86CPU *cpu = opaque; | ||||
| @ -930,6 +958,7 @@ VMStateDescription vmstate_x86_cpu = { | ||||
|         &vmstate_msr_hyperv_crash, | ||||
|         &vmstate_msr_hyperv_runtime, | ||||
|         &vmstate_msr_hyperv_synic, | ||||
|         &vmstate_msr_hyperv_stimer, | ||||
|         &vmstate_avx512, | ||||
|         &vmstate_xss, | ||||
|         NULL | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Andrey Smetanin
						Andrey Smetanin