diff options
author | Michael Brown | 2017-04-25 15:13:22 +0200 |
---|---|---|
committer | Michael Brown | 2017-04-28 17:20:47 +0200 |
commit | b91cc983da48b2791a672431551f7859e33126ec (patch) | |
tree | 466bc46ef18d86a619769a49acf4c149193237b1 /src/include/ipxe | |
parent | [hyperv] Remove redundant return status code from mapping functions (diff) | |
download | ipxe-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.h | 3 | ||||
-rw-r--r-- | src/include/ipxe/vmbus.h | 26 |
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 */ |