Skip to content

Commit 9366578

Browse files
committed
[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>
1 parent 51a7973 commit 9366578

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

src/arch/x86/drivers/hyperv/hyperv.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,29 @@ static int hv_check_features ( struct hv_hypervisor *hv ) {
220220
return 0;
221221
}
222222

223+
/**
224+
* Check that Gen 2 UEFI firmware is not running
225+
*
226+
* @v hv Hyper-V hypervisor
227+
* @ret rc Return status code
228+
*
229+
* We must not steal ownership from the Gen 2 UEFI firmware, since
230+
* doing so will cause an immediate crash. Avoid this by checking for
231+
* the guest OS identity known to be used by the Gen 2 UEFI firmware.
232+
*/
233+
static int hv_check_uefi ( struct hv_hypervisor *hv ) {
234+
uint64_t guest_os_id;
235+
236+
/* Check for UEFI firmware's guest OS identity */
237+
guest_os_id = rdmsr ( HV_X64_MSR_GUEST_OS_ID );
238+
if ( guest_os_id == HV_GUEST_OS_ID_UEFI ) {
239+
DBGC ( hv, "HV %p is owned by UEFI firmware\n", hv );
240+
return -ENOTSUP;
241+
}
242+
243+
return 0;
244+
}
245+
223246
/**
224247
* Map hypercall page
225248
*
@@ -556,6 +579,10 @@ static int hv_probe ( struct root_device *rootdev ) {
556579
if ( ( rc = hv_check_features ( hv ) ) != 0 )
557580
goto err_check_features;
558581

582+
/* Check that Gen 2 UEFI firmware is not running */
583+
if ( ( rc = hv_check_uefi ( hv ) ) != 0 )
584+
goto err_check_uefi;
585+
559586
/* Allocate pages */
560587
if ( ( rc = hv_alloc_pages ( hv, &hv->hypercall, &hv->synic.message,
561588
&hv->synic.event, NULL ) ) != 0 )
@@ -587,6 +614,7 @@ static int hv_probe ( struct root_device *rootdev ) {
587614
hv_free_pages ( hv, hv->hypercall, hv->synic.message, hv->synic.event,
588615
NULL );
589616
err_alloc_pages:
617+
err_check_uefi:
590618
err_check_features:
591619
free ( hv );
592620
err_alloc:

src/include/ipxe/hyperv.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
3737
*/
3838
#define HV_GUEST_OS_ID_IPXE ( ( 1ULL << 63 ) | ( 0x18aeULL << 48 ) )
3939

40+
/** Guest OS identity for Gen 2 UEFI firmware
41+
*
42+
* This does not conform to the documented structure for guest OS
43+
* identities.
44+
*/
45+
#define HV_GUEST_OS_ID_UEFI ( 1ULL << 40 )
46+
4047
/** Enable hypercall page */
4148
#define HV_HYPERCALL_ENABLE 0x00000001UL
4249

0 commit comments

Comments
 (0)