From b6889eaa1ea5685a06b13a03337c0e0d7e3bd251 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Feb 2015 14:47:07 +0000 Subject: [PATCH] [hyperv] Check for required features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Other hypervisors (e.g. KVM) may provide an unusable subset of the Hyper-V features, and our attempts to use these non-existent features cause the guest to reboot. Fix by explicitly checking for the Hyper-V features that we use. Reported-by: Ján ONDREJ (SAL) Signed-off-by: Michael Brown --- src/arch/x86/drivers/hyperv/hyperv.c | 26 ++++++++++++++++++++++++++ src/arch/x86/drivers/hyperv/hyperv.h | 15 +++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/arch/x86/drivers/hyperv/hyperv.c b/src/arch/x86/drivers/hyperv/hyperv.c index d911dcba8..ff5e4987b 100644 --- a/src/arch/x86/drivers/hyperv/hyperv.c +++ b/src/arch/x86/drivers/hyperv/hyperv.c @@ -150,6 +150,8 @@ static int hv_check_hv ( struct hv_hypervisor *hv ) { uint32_t discard_ebx; uint32_t discard_ecx; uint32_t discard_edx; + uint32_t available; + uint32_t permissions; /* Check for presence of a hypervisor (not necessarily Hyper-V) */ x86_features ( &features ); @@ -167,6 +169,30 @@ static int hv_check_hv ( struct hv_hypervisor *hv ) { return -ENODEV; } + /* Check that required features and privileges are available */ + cpuid ( HV_CPUID_FEATURES, &available, &permissions, &discard_ecx, + &discard_edx ); + if ( ! ( available & HV_FEATURES_AVAIL_HYPERCALL_MSR ) ) { + DBGC ( hv, "HV %p has no hypercall MSRs (features %08x:%08x)\n", + hv, available, permissions ); + return -ENODEV; + } + if ( ! ( available & HV_FEATURES_AVAIL_SYNIC_MSR ) ) { + DBGC ( hv, "HV %p has no SynIC MSRs (features %08x:%08x)\n", + hv, available, permissions ); + return -ENODEV; + } + if ( ! ( permissions & HV_FEATURES_PERM_POST_MESSAGES ) ) { + DBGC ( hv, "HV %p cannot post messages (features %08x:%08x)\n", + hv, available, permissions ); + return -EACCES; + } + if ( ! ( permissions & HV_FEATURES_PERM_SIGNAL_EVENTS ) ) { + DBGC ( hv, "HV %p cannot signal events (features %08x:%08x)", + hv, available, permissions ); + return -EACCES; + } + return 0; } diff --git a/src/arch/x86/drivers/hyperv/hyperv.h b/src/arch/x86/drivers/hyperv/hyperv.h index 94bdb8a86..d1733d6cd 100644 --- a/src/arch/x86/drivers/hyperv/hyperv.h +++ b/src/arch/x86/drivers/hyperv/hyperv.h @@ -18,6 +18,21 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** Get hypervisor identification */ #define HV_CPUID_HYPERVISOR_ID 0x40000002UL +/** Get hypervisor features */ +#define HV_CPUID_FEATURES 0x40000003UL + +/** SynIC MSRs are available */ +#define HV_FEATURES_AVAIL_SYNIC_MSR 0x00000004UL + +/** Hypercall MSRs are available */ +#define HV_FEATURES_AVAIL_HYPERCALL_MSR 0x00000020UL + +/** Guest may post messages */ +#define HV_FEATURES_PERM_POST_MESSAGES 0x00000010UL + +/** Guest may signal events */ +#define HV_FEATURES_PERM_SIGNAL_EVENTS 0x00000020UL + /** Guest OS identity MSR */ #define HV_X64_MSR_GUEST_OS_ID 0x40000000UL