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;
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 );
static void hv_map_hypercall(struct hv_hypervisor *hv)
Map hypercall page.
#define HV_FEATURES_AVAIL_TIME_REF_COUNT_MSR
Time reference counter MSR is available.
struct arbelprm_rc_send_wqe rc
#define TICKS_PER_SEC
Number of ticks per second.
static void rootdev_set_drvdata(struct root_device *rootdev, void *priv)
Set root device driver-private data.
#define HV_X64_MSR_SIEFP
SynIC event flags page MSR.
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
static int hv_probe(struct root_device *rootdev)
Probe root device.
#define le32_to_cpu(value)
int hv_wait_for_message(struct hv_hypervisor *hv, unsigned int sintx)
Wait for received message.
static int hv_alloc_message(struct hv_hypervisor *hv)
Allocate message buffer.
int hv_post_message(struct hv_hypervisor *hv, unsigned int id, unsigned int type, const void *data, size_t len)
Post message.
#define HV_FEATURES_PERM_SIGNAL_EVENTS
Guest may signal events.
static void hv_unmap_synic(struct hv_hypervisor *hv)
Unmap synthetic interrupt controller.
uint32_t type
Operating system type.
#define HV_HYPERCALL_ENABLE
Enable hypercall page.
int hv_signal_event(struct hv_hypervisor *hv, unsigned int id, unsigned int flag)
Signal event.
int vmbus_reset(struct hv_hypervisor *hv, struct device *parent)
Reset Hyper-V virtual machine bus.
#define HV_X64_MSR_SIMP
SynIC message page MSR.
unsigned long long uint64_t
static void *__malloc malloc_phys(size_t size, size_t phys_align)
Allocate memory with specified physical alignment.
#define HV_TIMER_SHIFT
Hyper-V timer scale factor (used to avoid 64-bit division)
void x86_features(struct x86_features *features)
Get x86 CPU features.
struct hv_event * event
Event flag page.
void * hypercall
Hypercall page.
struct timer hv_timer __timer(TIMER_PREFERRED)
Hyper-V timer.
#define EACCES
Permission denied.
#define offsetof(type, field)
Get offset of a field within a structure.
#define PAGE_SIZE
Page size.
static unsigned int hypercall
static void hv_quiesce(void)
Quiesce system.
struct device dev
Device chain.
static int hv_timer_probe(void)
Probe timer.
#define HV_X64_MSR_SCONTROL
SynIC control MSR.
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
static unsigned long hv_currticks(void)
Get current system time in ticks.
#define HV_SINT_MAX
Maximum synthetic interrupt number.
#define ENOTSUP
Operation not supported.
static void hv_unmap_hypercall(struct hv_hypervisor *hv)
Unmap hypercall page.
Dynamic memory allocation.
uint32_t start
Starting offset.
Hyper-V virtual machine bus.
static void hv_free_message(struct hv_hypervisor *hv)
Free message buffer.
#define HV_TIMER_HZ
Hyper-V timer frequency (fixed 10Mhz)
void vmbus_remove(struct hv_hypervisor *hv, struct device *parent)
Remove Hyper-V virtual machine bus.
struct hv_message received
Received message.
#define ENOMEM
Not enough space.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define HV_FEATURES_AVAIL_HYPERCALL_MSR
Hypercall MSRs are available.
REQUIRING_SYMBOL(hv_root_device)
#define HV_POST_MESSAGE
Post message.
u32 version
Driver version.
static uint32_t uint32_t uint32_t * ebx
#define HV_X64_MSR_GUEST_OS_ID
Guest OS identity MSR.
#define HV_CPUID_VENDOR_ID
Get vendor identification.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void hv_unquiesce(void)
Unquiesce system.
int hv_alloc_pages(struct hv_hypervisor *hv,...)
Allocate zeroed pages.
struct hv_signal_event signalled
Signalled event.
#define CPUID_FEATURES_INTEL_ECX_HYPERVISOR
Hypervisor is present.
#define HV_FEATURES_AVAIL_SYNIC_MSR
SynIC MSRs are available.
#define TIMER_PREFERRED
Preferred timer.
void(* quiesce)(void)
Quiesce system.
#define cpu_to_le32(value)
#define HV_INTERFACE_ID
Hyper-V interface identification.
char * strerror(int errno)
Retrieve string representation of error number.
#define HV_SIGNAL_EVENT
Signal event.
static uint32_t uint32_t uint32_t uint32_t * ecx
static void(* free)(struct refcnt *refcnt))
x86 CPU feature detection
void * zalloc(size_t size)
Allocate cleared memory.
struct hv_message * message
Message page.
#define HV_X64_MSR_SINT(x)
SynIC interrupt source MSRs.
#define HV_CPUID_FEATURES
Get hypervisor features.
void hv_free_pages(struct hv_hypervisor *hv,...)
Free pages.
#define HV_FEATURES_PERM_POST_MESSAGES
Guest may post messages.
uint32_t features
Supported features.
#define HV_X64_MSR_TIME_REF_COUNT
Time reference MSR.
static uint32_t uint32_t uint32_t uint32_t uint32_t * edx
#define ENODEV
No such device.
struct quiescer hv_quiescer __quiescer
Hyper-V quiescer.
#define HV_X64_MSR_EOM
SynIC end of message MSR.
static struct root_driver hv_root_driver
Hyper-V root device driver.
static void hv_unmap_synic_no_scontrol(struct hv_hypervisor *hv)
Unmap synthetic interrupt controller, leaving SCONTROL untouched.
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
int(* probe)(struct root_device *rootdev)
Add root device.
#define HV_X64_MSR_HYPERCALL
Hypercall page MSR.
union hv_message_buffer * message
Message buffer.
#define EHV(status)
Convert a Hyper-V status code to an iPXE status code.
static void hv_udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
static void * rootdev_get_drvdata(struct root_device *rootdev)
Get root device driver-private data.
void hv_disable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Disable synthetic interrupt.
__builtin_va_list va_list
#define HV_GUEST_OS_ID_UEFI
Guest OS identity for Gen 2 UEFI firmware.
#define HV_SIEFP_ENABLE
Enable SynIC event flags.
static int hv_check_features(struct hv_hypervisor *hv)
Check required features.
#define cpu_to_le16(value)
uint8_t data[48]
Additional event data.
static int hv_check_uefi(struct hv_hypervisor *hv)
Check that Gen 2 UEFI firmware is not running.
#define HV_SINT_AUTO_EOI
Perform implicit EOI upon synthetic interrupt delivery.
#define HV_CPUID_HYPERVISOR_ID
Get hypervisor identification.
static void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys()
#define HV_SINT_MASKED
Mask synthetic interrupt.
struct hv_post_message posted
Posted message.
#define HV_SIMP_ENABLE
Enable SynIC messages.
void hv_enable_sint(struct hv_hypervisor *hv, unsigned int sintx)
Enable synthetic interrupt.
int vmbus_probe(struct hv_hypervisor *hv, struct device *parent)
Probe Hyper-V virtual machine bus.
typeof(acpi_finder=acpi_find)
ACPI table finder.
static void hv_map_synic(struct hv_hypervisor *hv)
Map synthetic interrupt controller.
uint32_t flag
Flag number.
#define va_start(ap, last)
static int hv_check_hv(void)
Check whether or not we are running in Hyper-V.
#define HV_CPUID_INTERFACE_ID
Get interface identification.
#define HV_SINT_VECTOR_MASK
Synthetic interrupt vector mask.
#define NULL
NULL pointer (VOID *)
#define HV_MESSAGE_MAX_WAIT_MS
Maximum time to wait for a message response.
#define ETIMEDOUT
Connection timed out.
#define HV_SCONTROL_ENABLE
Enable SynIC.
#define HV_GUEST_OS_ID_IPXE
Guest OS identity for iPXE.
Model-specific registers.
static void hv_remove(struct root_device *rootdev)
Remove root device.
#define HV_SINT_VECTOR(x)
Synthetic interrupt vector.
struct root_device hv_root_device __root_device
Hyper-V root device.
struct hv_synic synic
Synthetic interrupt controller (SynIC)
void * memset(void *dest, int character, size_t len) __nonnull