summaryrefslogtreecommitdiffstats
path: root/src/include/ipxe
diff options
context:
space:
mode:
authorMichael Brown2017-04-25 15:13:22 +0200
committerMichael Brown2017-04-28 17:20:47 +0200
commitb91cc983da48b2791a672431551f7859e33126ec (patch)
tree466bc46ef18d86a619769a49acf4c149193237b1 /src/include/ipxe
parent[hyperv] Remove redundant return status code from mapping functions (diff)
downloadipxe-b91cc983da48b2791a672431551f7859e33126ec.tar.gz
ipxe-b91cc983da48b2791a672431551f7859e33126ec.tar.xz
ipxe-b91cc983da48b2791a672431551f7859e33126ec.zip
[hyperv] Cope with Windows Server 2016 enlightenments
An "enlightened" external bootloader (such as Windows Server 2016's winload.exe) may take ownership of the Hyper-V connection before all INT 13 operations have been completed. When this happens, all VMBus devices are implicitly closed and we are left with a non-functional network connection. Detect when our Hyper-V connection has been lost (by checking the SynIC message page MSR). Reclaim ownership of the Hyper-V connection and reestablish any VMBus devices, without disrupting any existing iPXE state (such as IPv4 settings attached to the network device). Windows Server 2016 will not cleanly take ownership of an active Hyper-V connection. Experimentation shows that we can quiesce by resetting only the SynIC message page MSR; this results in a successful SAN boot (on a Windows 2012 R2 physical host). Choose to quiesce by resetting (almost) all MSRs, in the hope that this will be more robust against corner cases such as a stray synthetic interrupt occurring during the handover. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/include/ipxe')
-rw-r--r--src/include/ipxe/hyperv.h3
-rw-r--r--src/include/ipxe/vmbus.h26
2 files changed, 29 insertions, 0 deletions
diff --git a/src/include/ipxe/hyperv.h b/src/include/ipxe/hyperv.h
index c61e2a08..9194a976 100644
--- a/src/include/ipxe/hyperv.h
+++ b/src/include/ipxe/hyperv.h
@@ -61,6 +61,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Synthetic interrupt vector mask */
#define HV_SINT_VECTOR_MASK HV_SINT_VECTOR ( 0xff )
+/** Maximum synthetic interrupt number */
+#define HV_SINT_MAX 15
+
/** Post message */
#define HV_POST_MESSAGE 0x005c
diff --git a/src/include/ipxe/vmbus.h b/src/include/ipxe/vmbus.h
index 26fc578c..68244185 100644
--- a/src/include/ipxe/vmbus.h
+++ b/src/include/ipxe/vmbus.h
@@ -479,6 +479,8 @@ struct vmbus_device {
/** Hyper-V hypervisor */
struct hv_hypervisor *hv;
+ /** Channel instance */
+ union uuid instance;
/** Channel ID */
unsigned int channel;
/** Monitor ID */
@@ -527,6 +529,12 @@ struct vmbus_driver {
* @ret rc Return status code
*/
int ( * probe ) ( struct vmbus_device *vmdev );
+ /** Reset device
+ *
+ * @v vmdev VMBus device
+ * @ret rc Return status code
+ */
+ int ( * reset ) ( struct vmbus_device *vmdev );
/** Remove device
*
* @v vmdev VMBus device
@@ -609,6 +617,23 @@ vmbus_unregister_pages ( struct vmbus_device *vmdev,
list_del ( &pages->list );
}
+extern unsigned int vmbus_obsolete_gpadl;
+
+/**
+ * Check if GPADL is obsolete
+ *
+ * @v gpadl GPADL ID
+ * @v is_obsolete GPADL ID is obsolete
+ *
+ * Check if GPADL is obsolete (i.e. was created before the most recent
+ * Hyper-V reset).
+ */
+static inline __attribute__ (( always_inline )) int
+vmbus_gpadl_is_obsolete ( unsigned int gpadl ) {
+
+ return ( gpadl <= vmbus_obsolete_gpadl );
+}
+
extern int vmbus_establish_gpadl ( struct vmbus_device *vmdev, userptr_t data,
size_t len );
extern int vmbus_gpadl_teardown ( struct vmbus_device *vmdev,
@@ -629,6 +654,7 @@ extern int vmbus_poll ( struct vmbus_device *vmdev );
extern void vmbus_dump_channel ( struct vmbus_device *vmdev );
extern int vmbus_probe ( struct hv_hypervisor *hv, struct device *parent );
+extern int vmbus_reset ( struct hv_hypervisor *hv, struct device *parent );
extern void vmbus_remove ( struct hv_hypervisor *hv, struct device *parent );
#endif /* _IPXE_VMBUS_H */