|
@@ -220,6 +220,29 @@ static int hv_check_features ( struct hv_hypervisor *hv ) {
|
220
|
220
|
return 0;
|
221
|
221
|
}
|
222
|
222
|
|
|
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
|
+
|
223
|
246
|
/**
|
224
|
247
|
* Map hypercall page
|
225
|
248
|
*
|
|
@@ -556,6 +579,10 @@ static int hv_probe ( struct root_device *rootdev ) {
|
556
|
579
|
if ( ( rc = hv_check_features ( hv ) ) != 0 )
|
557
|
580
|
goto err_check_features;
|
558
|
581
|
|
|
582
|
+ /* Check that Gen 2 UEFI firmware is not running */
|
|
583
|
+ if ( ( rc = hv_check_uefi ( hv ) ) != 0 )
|
|
584
|
+ goto err_check_uefi;
|
|
585
|
+
|
559
|
586
|
/* Allocate pages */
|
560
|
587
|
if ( ( rc = hv_alloc_pages ( hv, &hv->hypercall, &hv->synic.message,
|
561
|
588
|
&hv->synic.event, NULL ) ) != 0 )
|
|
@@ -587,6 +614,7 @@ static int hv_probe ( struct root_device *rootdev ) {
|
587
|
614
|
hv_free_pages ( hv, hv->hypercall, hv->synic.message, hv->synic.event,
|
588
|
615
|
NULL );
|
589
|
616
|
err_alloc_pages:
|
|
617
|
+ err_check_uefi:
|
590
|
618
|
err_check_features:
|
591
|
619
|
free ( hv );
|
592
|
620
|
err_alloc:
|