diff options
author | Michael Brown | 2017-07-28 22:19:45 +0200 |
---|---|---|
committer | Michael Brown | 2017-07-28 22:30:43 +0200 |
commit | 936657832f2262ad04bdf16b9229ce0b1d1c174f (patch) | |
tree | bc5ff1a50c989c604e462d4443822b163b2577a8 /src/arch | |
parent | [acpi] Fix spurious uninitialised-variable warning on some gcc versions (diff) | |
download | ipxe-936657832f2262ad04bdf16b9229ce0b1d1c174f.tar.gz ipxe-936657832f2262ad04bdf16b9229ce0b1d1c174f.tar.xz ipxe-936657832f2262ad04bdf16b9229ce0b1d1c174f.zip |
[hyperv] Do not steal ownership from the Gen 2 UEFI firmware
We must not steal ownership from the Gen 2 UEFI firmware, since doing
so will cause an immediate system crash (most likely in the form of a
reboot).
This problem was masked before commit a0f6e75 ("[hyperv] Do not fail
if guest OS ID MSR is already set"), since prior to that commit we
would always fail if we found any non-zero guest OS identity. We now
accept a non-zero previous guest OS identity in order to allow for
situations such as chainloading from iPXE to another iPXE, and as a
prerequisite for commit b91cc98 ("[hyperv] Cope with Windows Server
2016 enlightenments").
A proper fix would be to reverse engineer the UEFI protocols exposed
within the Hyper-V Gen 2 firmware and use these to bind to the VMBus
device representing the network connection, (with the native Hyper-V
driver moved to become a BIOS-only feature).
As an interim solution, fail to initialise the native Hyper-V driver
if we detect the guest OS identity known to be used by the Gen 2 UEFI
firmware. This will cause the standard all-drivers build (ipxe.efi)
to fall back to using the SNP driver.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/x86/drivers/hyperv/hyperv.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/src/arch/x86/drivers/hyperv/hyperv.c b/src/arch/x86/drivers/hyperv/hyperv.c index 4e687687..1903d1db 100644 --- a/src/arch/x86/drivers/hyperv/hyperv.c +++ b/src/arch/x86/drivers/hyperv/hyperv.c @@ -221,6 +221,29 @@ static int hv_check_features ( struct hv_hypervisor *hv ) { } /** + * Check that Gen 2 UEFI firmware is not running + * + * @v hv Hyper-V hypervisor + * @ret rc Return status code + * + * We must not steal ownership from the Gen 2 UEFI firmware, since + * doing so will cause an immediate crash. Avoid this by checking for + * the guest OS identity known to be used by the Gen 2 UEFI firmware. + */ +static int hv_check_uefi ( struct hv_hypervisor *hv ) { + uint64_t guest_os_id; + + /* Check for UEFI firmware's guest OS identity */ + guest_os_id = rdmsr ( HV_X64_MSR_GUEST_OS_ID ); + if ( guest_os_id == HV_GUEST_OS_ID_UEFI ) { + DBGC ( hv, "HV %p is owned by UEFI firmware\n", hv ); + return -ENOTSUP; + } + + return 0; +} + +/** * Map hypercall page * * @v hv Hyper-V hypervisor @@ -556,6 +579,10 @@ static int hv_probe ( struct root_device *rootdev ) { if ( ( rc = hv_check_features ( hv ) ) != 0 ) goto err_check_features; + /* Check that Gen 2 UEFI firmware is not running */ + if ( ( rc = hv_check_uefi ( hv ) ) != 0 ) + goto err_check_uefi; + /* Allocate pages */ if ( ( rc = hv_alloc_pages ( hv, &hv->hypercall, &hv->synic.message, &hv->synic.event, NULL ) ) != 0 ) @@ -587,6 +614,7 @@ static int hv_probe ( struct root_device *rootdev ) { hv_free_pages ( hv, hv->hypercall, hv->synic.message, hv->synic.event, NULL ); err_alloc_pages: + err_check_uefi: err_check_features: free ( hv ); err_alloc: |