54#define HV_MESSAGE_MAX_WAIT_MS 1000
57#define HV_TIMER_HZ 10000000
60#define HV_TIMER_SHIFT 18
68#define EHV( status ) EPLATFORM ( EINFO_EPLATFORM, (status) )
85 for ( i = 0 ; ( ( page =
va_arg ( args,
void ** ) ) !=
NULL ); i++ ) {
98 for ( ; i >= 0 ; i-- ) {
99 page =
va_arg ( args,
void ** );
118 while ( ( page =
va_arg ( args,
void * ) ) !=
NULL )
177 "ID %#08x)\n", interface_id );
200 DBGC ( hv,
"HV %p has no hypercall MSRs (features %08x:%08x)\n",
201 hv, available, permissions );
205 DBGC ( hv,
"HV %p has no SynIC MSRs (features %08x:%08x)\n",
206 hv, available, permissions );
210 DBGC ( hv,
"HV %p cannot post messages (features %08x:%08x)\n",
211 hv, available, permissions );
215 DBGC ( hv,
"HV %p cannot signal events (features %08x:%08x)",
216 hv, available, permissions );
239 DBGC ( hv,
"HV %p is owned by UEFI firmware\n", hv );
270 if ( guest_os_id != 0 ) {
271 DBGC ( hv,
"HV %p guest OS ID MSR was %#08llx\n",
275 DBGC2 ( hv,
"HV %p guest OS ID MSR is %#08llx\n", hv, guest_os_id );
284 DBGC ( hv,
"HV %p detected \"%s\" version %d.%d build %d\n", hv,
312 DBGC2 ( hv,
"HV %p guest OS ID MSR is %#08llx\n", hv, guest_os_id );
334 DBGC2 ( hv,
"HV %p SIMP MSR is %#08llx\n", hv, simp );
341 DBGC2 ( hv,
"HV %p SIEFP MSR is %#08llx\n", hv, siefp );
347 DBGC2 ( hv,
"HV %p SCONTROL MSR is %#08llx\n", hv, scontrol );
363 DBGC2 ( hv,
"HV %p SIEFP MSR is %#08llx\n", hv, siefp );
369 DBGC2 ( hv,
"HV %p SIMP MSR is %#08llx\n", hv, simp );
384 DBGC2 ( hv,
"HV %p SCONTROL MSR is %#08llx\n", hv, scontrol );
409 sint = rdmsr ( msr );
413 DBGC2 ( hv,
"HV %p SINT%d MSR is %#08llx\n", hv, sintx, sint );
428 sint = rdmsr ( msr );
435 DBGC2 ( hv,
"HV %p SINT%d MSR is %#08llx\n", hv, sintx, sint );
450 unsigned int type,
const void *
data,
size_t len ) {
464 DBGC2 ( hv,
"HV %p connection %d posting message type %#08x:\n",
471 DBGC ( hv,
"HV %p could not post message to %#08x: %s\n",
489 unsigned int retries;
504 DBGC2 ( hv,
"HV %p SINT%d received message type "
505 "%#08x:\n", hv, sintx,
522 DBGC ( hv,
"HV %p SINT%d timed out waiting for message\n",
536 unsigned int flag ) {
542 memset ( event, 0,
sizeof ( *event ) );
549 DBGC ( hv,
"HV %p could not signal event to %#08x: %s\n",
572 hv =
zalloc (
sizeof ( *hv ) );
580 goto err_check_features;
589 goto err_alloc_pages;
593 goto err_alloc_message;
603 goto err_vmbus_probe;
651 .dev = { .name =
"Hyper-V" },
697 DBGC ( hv,
"HV %p quiesced\n", hv );
735 if ( (
rc =
vmbus_reset ( hv, &hv_root_device.dev ) ) != 0 ) {
736 DBGC ( hv,
"HV %p could not unquiesce: %s\n",
805 }
while ( elapsed < threshold );
#define NULL
NULL pointer (VOID *)
typeof(acpi_finder=acpi_find)
ACPI table finder.
uint32_t flag
Flag number.
struct arbelprm_rc_send_wqe rc
unsigned long long uint64_t
#define HV_X64_MSR_SIMP
SynIC message page MSR.
#define HV_X64_MSR_TIME_REF_COUNT
Time reference MSR.
#define HV_X64_MSR_EOM
SynIC end of message MSR.
#define HV_X64_MSR_SCONTROL
SynIC control MSR.
#define HV_CPUID_FEATURES
Get hypervisor features.
#define HV_CPUID_INTERFACE_ID
Get interface identification.
#define HV_FEATURES_AVAIL_HYPERCALL_MSR
Hypercall MSRs are available.
#define HV_FEATURES_PERM_POST_MESSAGES
Guest may post messages.
#define HV_FEATURES_AVAIL_TIME_REF_COUNT_MSR
Time reference counter MSR is available.
#define HV_X64_MSR_GUEST_OS_ID
Guest OS identity MSR.
#define HV_CPUID_VENDOR_ID
Get vendor identification.
#define HV_X64_MSR_SIEFP
SynIC event flags page MSR.
#define HV_FEATURES_AVAIL_SYNIC_MSR
SynIC MSRs are available.
#define HV_X64_MSR_SINT(x)
SynIC interrupt source MSRs.
#define HV_FEATURES_PERM_SIGNAL_EVENTS
Guest may signal events.
#define HV_CPUID_HYPERVISOR_ID
Get hypervisor identification.
#define HV_X64_MSR_HYPERCALL
Hypercall page MSR.
static unsigned int hypercall
#define assert(condition)
Assert a condition at run-time.
u32 version
Driver version.
void x86_features(struct x86_features *features)
Get x86 CPU features.
x86 CPU feature detection
static uint32_t uint32_t uint32_t * ebx
#define CPUID_FEATURES_INTEL_ECX_HYPERVISOR
Hypervisor is present.
static uint32_t uint32_t uint32_t uint32_t * ecx
static uint32_t uint32_t uint32_t uint32_t uint32_t * edx
#define __root_device
Declare a root device.
static void * rootdev_get_drvdata(struct root_device *rootdev)
Get root device driver-private data.
static void rootdev_set_drvdata(struct root_device *rootdev, void *priv)
Set root device driver-private data.
uint32_t features
Supported features.
uint32_t type
Operating system type.
uint8_t data[48]
Additional event data.
uint32_t start
Starting offset.
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
#define REQUIRE_OBJECT(object)
Require an object.
#define ETIMEDOUT
Connection timed out.
#define ENOMEM
Not enough space.
#define ENOTSUP
Operation not supported.
#define ENODEV
No such device.
#define EACCES
Permission denied.
#define REQUIRING_SYMBOL(symbol)
Specify the file's requiring symbol.
#define TIMER_PREFERRED
Preferred timer.
int hv_wait_for_message(struct hv_hypervisor *hv, unsigned int sintx)
Wait for received message.
static void hv_map_hypercall(struct hv_hypervisor *hv)
Map hypercall page.
#define EHV(status)
Convert a Hyper-V status code to an iPXE status code.
static int hv_alloc_message(struct hv_hypervisor *hv)
Allocate message buffer.
static void hv_remove(struct root_device *rootdev)
Remove root device.
static struct root_driver hv_root_driver
Hyper-V root device driver.
static void hv_free_message(struct hv_hypervisor *hv)
Free message buffer.
static void hv_udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
void hv_disable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Disable synthetic interrupt.
static int hv_probe(struct root_device *rootdev)
Probe root device.
#define HV_TIMER_SHIFT
Hyper-V timer scale factor (used to avoid 64-bit division)
static int hv_check_features(struct hv_hypervisor *hv)
Check required features.
static int hv_check_uefi(struct hv_hypervisor *hv)
Check that Gen 2 UEFI firmware is not running.
#define HV_TIMER_HZ
Hyper-V timer frequency (fixed 10Mhz)
static void hv_map_synic(struct hv_hypervisor *hv)
Map synthetic interrupt controller.
static unsigned long hv_currticks(void)
Get current system time in ticks.
static void hv_unmap_hypercall(struct hv_hypervisor *hv)
Unmap hypercall page.
static void hv_unmap_synic_no_scontrol(struct hv_hypervisor *hv)
Unmap synthetic interrupt controller, leaving SCONTROL untouched.
void hv_free_pages(struct hv_hypervisor *hv,...)
Free pages.
int hv_post_message(struct hv_hypervisor *hv, unsigned int id, unsigned int type, const void *data, size_t len)
Post message.
int hv_alloc_pages(struct hv_hypervisor *hv,...)
Allocate zeroed pages.
static void hv_quiesce(void)
Quiesce system.
static void hv_unmap_synic(struct hv_hypervisor *hv)
Unmap synthetic interrupt controller.
int hv_signal_event(struct hv_hypervisor *hv, unsigned int id, unsigned int flag)
Signal event.
void hv_enable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Enable synthetic interrupt.
static int hv_timer_probe(void)
Probe timer.
#define HV_MESSAGE_MAX_WAIT_MS
Maximum time to wait for a message response.
static void hv_unquiesce(void)
Unquiesce system.
static int hv_check_hv(void)
Check whether or not we are running in Hyper-V.
#define le32_to_cpu(value)
#define cpu_to_le32(value)
#define cpu_to_le16(value)
#define HV_SINT_VECTOR_MASK
Synthetic interrupt vector mask.
#define HV_GUEST_OS_ID_IPXE
Guest OS identity for iPXE.
#define HV_INTERFACE_ID
Hyper-V interface identification.
#define HV_SINT_MAX
Maximum synthetic interrupt number.
#define HV_SINT_AUTO_EOI
Perform implicit EOI upon synthetic interrupt delivery.
#define HV_SIEFP_ENABLE
Enable SynIC event flags.
#define HV_SINT_VECTOR(x)
Synthetic interrupt vector.
#define HV_SCONTROL_ENABLE
Enable SynIC.
#define HV_POST_MESSAGE
Post message.
#define HV_GUEST_OS_ID_UEFI
Guest OS identity for Gen 2 UEFI firmware.
#define HV_SIGNAL_EVENT
Signal event.
#define HV_SIMP_ENABLE
Enable SynIC messages.
#define HV_HYPERCALL_ENABLE
Enable hypercall page.
#define HV_SINT_MASKED
Mask synthetic interrupt.
#define PAGE_SIZE
Page size.
#define TICKS_PER_SEC
Number of ticks per second.
#define __timer(order)
Declare a timer.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void * zalloc(size_t size)
Allocate cleared memory.
void * malloc_phys(size_t size, size_t phys_align)
Allocate memory with specified physical alignment.
void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys()
Dynamic memory allocation.
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Model-specific registers.
#define __quiescer
Declare a quiescer.
static void(* free)(struct refcnt *refcnt))
#define va_start(ap, last)
__builtin_va_list va_list
#define offsetof(type, field)
Get offset of a field within a structure.
char * strerror(int errno)
Retrieve string representation of error number.
struct hv_synic synic
Synthetic interrupt controller (SynIC)
union hv_message_buffer * message
Message buffer.
void * hypercall
Hypercall page.
struct hv_event * event
Event flag page.
struct hv_message * message
Message page.
struct device dev
Device chain.
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
struct hv_message received
Received message.
struct hv_post_message posted
Posted message.
struct hv_signal_event signalled
Signalled event.
int vmbus_probe(struct hv_hypervisor *hv, struct device *parent)
Probe Hyper-V virtual machine bus.
void vmbus_remove(struct hv_hypervisor *hv, struct device *parent)
Remove Hyper-V virtual machine bus.
int vmbus_reset(struct hv_hypervisor *hv, struct device *parent)
Reset Hyper-V virtual machine bus.
Hyper-V virtual machine bus.