diff options
author | Michael Brown | 2015-02-19 15:47:07 +0100 |
---|---|---|
committer | Michael Brown | 2015-02-20 12:00:52 +0100 |
commit | b6889eaa1ea5685a06b13a03337c0e0d7e3bd251 (patch) | |
tree | 1ca6ba0f1640a82b834621f2d850287ab0ab66c4 | |
parent | [libc] Rewrite strtoul() (diff) | |
download | ipxe-b6889eaa1ea5685a06b13a03337c0e0d7e3bd251.tar.gz ipxe-b6889eaa1ea5685a06b13a03337c0e0d7e3bd251.tar.xz ipxe-b6889eaa1ea5685a06b13a03337c0e0d7e3bd251.zip |
[hyperv] Check for required features
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) <ondrejj@salstar.sk>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/arch/x86/drivers/hyperv/hyperv.c | 26 | ||||
-rw-r--r-- | src/arch/x86/drivers/hyperv/hyperv.h | 15 |
2 files changed, 41 insertions, 0 deletions
diff --git a/src/arch/x86/drivers/hyperv/hyperv.c b/src/arch/x86/drivers/hyperv/hyperv.c index d911dcba..ff5e4987 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 94bdb8a8..d1733d6c 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 |