target-i386/kvm: Hyper-V SynIC MSR's support
This patch does Hyper-V Synthetic interrupt controller(Hyper-V SynIC) MSR's support and migration. Hyper-V SynIC is enabled by cpu's 'hv-synic' option. This patch does not allow cpu creation if 'hv-synic' option specified but kernel doesn't support Hyper-V SynIC. Changes v3: * removed 'msr_hv_synic_version' migration because it's value always the same * moved SynIC msr's initialization into kvm_arch_init_vcpu Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com> Reviewed-by: Roman Kagan <rkagan@virtuozzo.com> Signed-off-by: Denis V. Lunev <den@openvz.org> 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: Roman Kagan <rkagan@virtuozzo.com> CC: Denis V. Lunev <den@openvz.org> CC: kvm@vger.kernel.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
fff02bc00b
commit
866eea9a13
@ -94,6 +94,7 @@ typedef struct X86CPU {
|
||||
bool hyperv_reset;
|
||||
bool hyperv_vpindex;
|
||||
bool hyperv_runtime;
|
||||
bool hyperv_synic;
|
||||
bool check_cpuid;
|
||||
bool enforce_cpuid;
|
||||
bool expose_kvm;
|
||||
|
@ -3146,6 +3146,7 @@ static Property x86_cpu_properties[] = {
|
||||
DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
|
||||
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("check", X86CPU, check_cpuid, true),
|
||||
DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
|
||||
DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
|
||||
|
@ -920,6 +920,11 @@ typedef struct CPUX86State {
|
||||
uint64_t msr_hv_tsc;
|
||||
uint64_t msr_hv_crash_params[HV_X64_MSR_CRASH_PARAMS];
|
||||
uint64_t msr_hv_runtime;
|
||||
uint64_t msr_hv_synic_control;
|
||||
uint64_t msr_hv_synic_version;
|
||||
uint64_t msr_hv_synic_evt_page;
|
||||
uint64_t msr_hv_synic_msg_page;
|
||||
uint64_t msr_hv_synic_sint[HV_SYNIC_SINT_COUNT];
|
||||
|
||||
/* exception/interrupt handling */
|
||||
int error_code;
|
||||
|
@ -86,6 +86,7 @@ static bool has_msr_hv_crash;
|
||||
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_mtrr;
|
||||
static bool has_msr_xss;
|
||||
|
||||
@ -521,7 +522,8 @@ static bool hyperv_enabled(X86CPU *cpu)
|
||||
cpu->hyperv_crash ||
|
||||
cpu->hyperv_reset ||
|
||||
cpu->hyperv_vpindex ||
|
||||
cpu->hyperv_runtime);
|
||||
cpu->hyperv_runtime ||
|
||||
cpu->hyperv_synic);
|
||||
}
|
||||
|
||||
static Error *invtsc_mig_blocker;
|
||||
@ -610,6 +612,21 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
if (cpu->hyperv_runtime && has_msr_hv_runtime) {
|
||||
c->eax |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
|
||||
}
|
||||
if (cpu->hyperv_synic) {
|
||||
int sint;
|
||||
|
||||
if (!has_msr_hv_synic ||
|
||||
kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_SYNIC, 0)) {
|
||||
fprintf(stderr, "Hyper-V SynIC is not supported by kernel\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
c->eax |= HV_X64_MSR_SYNIC_AVAILABLE;
|
||||
env->msr_hv_synic_version = HV_SYNIC_VERSION_1;
|
||||
for (sint = 0; sint < ARRAY_SIZE(env->msr_hv_synic_sint); sint++) {
|
||||
env->msr_hv_synic_sint[sint] = HV_SYNIC_SINT_MASKED;
|
||||
}
|
||||
}
|
||||
c = &cpuid_data.entries[cpuid_i++];
|
||||
c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
|
||||
if (cpu->hyperv_relaxed_timing) {
|
||||
@ -956,6 +973,10 @@ static int kvm_get_supported_msrs(KVMState *s)
|
||||
has_msr_hv_runtime = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == HV_X64_MSR_SCONTROL) {
|
||||
has_msr_hv_synic = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1517,6 +1538,23 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_VP_RUNTIME,
|
||||
env->msr_hv_runtime);
|
||||
}
|
||||
if (cpu->hyperv_synic) {
|
||||
int j;
|
||||
|
||||
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SCONTROL,
|
||||
env->msr_hv_synic_control);
|
||||
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SVERSION,
|
||||
env->msr_hv_synic_version);
|
||||
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIEFP,
|
||||
env->msr_hv_synic_evt_page);
|
||||
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIMP,
|
||||
env->msr_hv_synic_msg_page);
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(env->msr_hv_synic_sint); j++) {
|
||||
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SINT0 + j,
|
||||
env->msr_hv_synic_sint[j]);
|
||||
}
|
||||
}
|
||||
if (has_msr_mtrr) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype);
|
||||
kvm_msr_entry_set(&msrs[n++],
|
||||
@ -1885,6 +1923,17 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
if (has_msr_hv_runtime) {
|
||||
msrs[n++].index = HV_X64_MSR_VP_RUNTIME;
|
||||
}
|
||||
if (cpu->hyperv_synic) {
|
||||
uint32_t msr;
|
||||
|
||||
msrs[n++].index = HV_X64_MSR_SCONTROL;
|
||||
msrs[n++].index = HV_X64_MSR_SVERSION;
|
||||
msrs[n++].index = HV_X64_MSR_SIEFP;
|
||||
msrs[n++].index = HV_X64_MSR_SIMP;
|
||||
for (msr = HV_X64_MSR_SINT0; msr <= HV_X64_MSR_SINT15; msr++) {
|
||||
msrs[n++].index = msr;
|
||||
}
|
||||
}
|
||||
if (has_msr_mtrr) {
|
||||
msrs[n++].index = MSR_MTRRdefType;
|
||||
msrs[n++].index = MSR_MTRRfix64K_00000;
|
||||
@ -2041,6 +2090,21 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
case HV_X64_MSR_VP_RUNTIME:
|
||||
env->msr_hv_runtime = msrs[i].data;
|
||||
break;
|
||||
case HV_X64_MSR_SCONTROL:
|
||||
env->msr_hv_synic_control = msrs[i].data;
|
||||
break;
|
||||
case HV_X64_MSR_SVERSION:
|
||||
env->msr_hv_synic_version = msrs[i].data;
|
||||
break;
|
||||
case HV_X64_MSR_SIEFP:
|
||||
env->msr_hv_synic_evt_page = msrs[i].data;
|
||||
break;
|
||||
case HV_X64_MSR_SIMP:
|
||||
env->msr_hv_synic_msg_page = msrs[i].data;
|
||||
break;
|
||||
case HV_X64_MSR_SINT0 ... HV_X64_MSR_SINT15:
|
||||
env->msr_hv_synic_sint[index - HV_X64_MSR_SINT0] = msrs[i].data;
|
||||
break;
|
||||
case MSR_MTRRdefType:
|
||||
env->mtrr_deftype = msrs[i].data;
|
||||
break;
|
||||
|
@ -710,6 +710,42 @@ static const VMStateDescription vmstate_msr_hyperv_runtime = {
|
||||
}
|
||||
};
|
||||
|
||||
static bool hyperv_synic_enable_needed(void *opaque)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
CPUX86State *env = &cpu->env;
|
||||
int i;
|
||||
|
||||
if (env->msr_hv_synic_control != 0 ||
|
||||
env->msr_hv_synic_evt_page != 0 ||
|
||||
env->msr_hv_synic_msg_page != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(env->msr_hv_synic_sint); i++) {
|
||||
if (env->msr_hv_synic_sint[i] != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_msr_hyperv_synic = {
|
||||
.name = "cpu/msr_hyperv_synic",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = hyperv_synic_enable_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT64(env.msr_hv_synic_control, X86CPU),
|
||||
VMSTATE_UINT64(env.msr_hv_synic_evt_page, X86CPU),
|
||||
VMSTATE_UINT64(env.msr_hv_synic_msg_page, X86CPU),
|
||||
VMSTATE_UINT64_ARRAY(env.msr_hv_synic_sint, X86CPU,
|
||||
HV_SYNIC_SINT_COUNT),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static bool avx512_needed(void *opaque)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
@ -893,6 +929,7 @@ VMStateDescription vmstate_x86_cpu = {
|
||||
&vmstate_msr_hyperv_time,
|
||||
&vmstate_msr_hyperv_crash,
|
||||
&vmstate_msr_hyperv_runtime,
|
||||
&vmstate_msr_hyperv_synic,
|
||||
&vmstate_avx512,
|
||||
&vmstate_xss,
|
||||
NULL
|
||||
|
Loading…
Reference in New Issue
Block a user