| #ifndef _IPXE_HYPERV_H |
| #define _IPXE_HYPERV_H |
| |
| /** @file |
| * |
| * Hyper-V interface |
| * |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); |
| |
| #include <stdint.h> |
| #include <ipxe/io.h> |
| |
| /** Hyper-V interface identification */ |
| #define HV_INTERFACE_ID 0x31237648 /* "Hv#1" */ |
| |
| /** Guest OS identity for iPXE |
| * |
| * This field comprises: |
| * |
| * Bit 63 : set to 1 to indicate an open source OS |
| * Bits 62:56 : OS Type |
| * Bits 55:48 : OS ID |
| * Bits 47:16 : Version |
| * Bits 15:0 : Build number |
| * |
| * There appears to be no central registry for the "OS Type". The |
| * specification states that "Linux is 0x100", and the FreeBSD source |
| * states that "FreeBSD is 0x200". Both of these statements are |
| * actually referring to the combined "OS Type" and "OS ID" field. |
| * |
| * We choose to use 0x98ae: this is generated by setting bit 63 (to |
| * indicate an open source OS) and setting the OS Type+ID equal to the |
| * PnP vendor ID used in romprefix.S. No version information or build |
| * number is included. |
| */ |
| #define HV_GUEST_OS_ID_IPXE ( ( 1ULL << 63 ) | ( 0x18aeULL << 48 ) ) |
| |
| /** Guest OS identity for Gen 2 UEFI firmware |
| * |
| * This does not conform to the documented structure for guest OS |
| * identities. |
| */ |
| #define HV_GUEST_OS_ID_UEFI ( 1ULL << 40 ) |
| |
| /** Enable hypercall page */ |
| #define HV_HYPERCALL_ENABLE 0x00000001UL |
| |
| /** Enable SynIC */ |
| #define HV_SCONTROL_ENABLE 0x00000001UL |
| |
| /** Enable SynIC event flags */ |
| #define HV_SIEFP_ENABLE 0x00000001UL |
| |
| /** Enable SynIC messages */ |
| #define HV_SIMP_ENABLE 0x00000001UL |
| |
| /** Perform implicit EOI upon synthetic interrupt delivery */ |
| #define HV_SINT_AUTO_EOI 0x00020000UL |
| |
| /** Mask synthetic interrupt */ |
| #define HV_SINT_MASKED 0x00010000UL |
| |
| /** Synthetic interrupt vector */ |
| #define HV_SINT_VECTOR(x) ( (x) << 0 ) |
| |
| /** 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 |
| |
| /** A posted message |
| * |
| * This is the input parameter list for the HvPostMessage hypercall. |
| */ |
| struct hv_post_message { |
| /** Connection ID */ |
| uint32_t id; |
| /** Padding */ |
| uint32_t reserved; |
| /** Type */ |
| uint32_t type; |
| /** Length of message */ |
| uint32_t len; |
| /** Message */ |
| uint8_t data[240]; |
| } __attribute__ (( packed )); |
| |
| /** A received message |
| * |
| * This is the HV_MESSAGE structure from the Hypervisor Top-Level |
| * Functional Specification. The field order given in the |
| * documentation is incorrect. |
| */ |
| struct hv_message { |
| /** Type */ |
| uint32_t type; |
| /** Length of message */ |
| uint8_t len; |
| /** Flags */ |
| uint8_t flags; |
| /** Padding */ |
| uint16_t reserved; |
| /** Origin */ |
| uint64_t origin; |
| /** Message */ |
| uint8_t data[240]; |
| } __attribute__ (( packed )); |
| |
| /** Signal event */ |
| #define HV_SIGNAL_EVENT 0x005d |
| |
| /** A signalled event */ |
| struct hv_signal_event { |
| /** Connection ID */ |
| uint32_t id; |
| /** Flag number */ |
| uint16_t flag; |
| /** Reserved */ |
| uint16_t reserved; |
| } __attribute__ (( packed )); |
| |
| /** A received event */ |
| struct hv_event { |
| /** Event flags */ |
| uint8_t flags[256]; |
| } __attribute__ (( packed )); |
| |
| /** A monitor trigger group |
| * |
| * This is the HV_MONITOR_TRIGGER_GROUP structure from the Hypervisor |
| * Top-Level Functional Specification. |
| */ |
| struct hv_monitor_trigger { |
| /** Pending events */ |
| uint32_t pending; |
| /** Armed events */ |
| uint32_t armed; |
| } __attribute__ (( packed )); |
| |
| /** A monitor parameter set |
| * |
| * This is the HV_MONITOR_PARAMETER structure from the Hypervisor |
| * Top-Level Functional Specification. |
| */ |
| struct hv_monitor_parameter { |
| /** Connection ID */ |
| uint32_t id; |
| /** Flag number */ |
| uint16_t flag; |
| /** Reserved */ |
| uint16_t reserved; |
| } __attribute__ (( packed )); |
| |
| /** A monitor page |
| * |
| * This is the HV_MONITOR_PAGE structure from the Hypervisor Top-Level |
| * Functional Specification. |
| */ |
| struct hv_monitor { |
| /** Flags */ |
| uint32_t flags; |
| /** Reserved */ |
| uint8_t reserved_a[4]; |
| /** Trigger groups */ |
| struct hv_monitor_trigger trigger[4]; |
| /** Reserved */ |
| uint8_t reserved_b[536]; |
| /** Latencies */ |
| uint16 latency[4][32]; |
| /** Reserved */ |
| uint8_t reserved_c[256]; |
| /** Parameters */ |
| struct hv_monitor_parameter param[4][32]; |
| /** Reserved */ |
| uint8_t reserved_d[1984]; |
| } __attribute__ (( packed )); |
| |
| /** A synthetic interrupt controller */ |
| struct hv_synic { |
| /** Message page */ |
| struct hv_message *message; |
| /** Event flag page */ |
| struct hv_event *event; |
| }; |
| |
| /** A message buffer */ |
| union hv_message_buffer { |
| /** Posted message */ |
| struct hv_post_message posted; |
| /** Received message */ |
| struct hv_message received; |
| /** Signalled event */ |
| struct hv_signal_event signalled; |
| }; |
| |
| /** A Hyper-V hypervisor */ |
| struct hv_hypervisor { |
| /** Hypercall page */ |
| void *hypercall; |
| /** Synthetic interrupt controller (SynIC) */ |
| struct hv_synic synic; |
| /** Message buffer */ |
| union hv_message_buffer *message; |
| /** Virtual machine bus */ |
| struct vmbus *vmbus; |
| }; |
| |
| #include <bits/hyperv.h> |
| |
| /** |
| * Calculate the number of pages covering an address range |
| * |
| * @v data Start of data |
| * @v len Length of data (must be non-zero) |
| * @ret pfn_count Number of pages covered |
| */ |
| static inline unsigned int hv_pfn_count ( physaddr_t data, size_t len ) { |
| unsigned int first_pfn = ( data / PAGE_SIZE ); |
| unsigned int last_pfn = ( ( data + len - 1 ) / PAGE_SIZE ); |
| |
| return ( last_pfn - first_pfn + 1 ); |
| } |
| |
| extern __attribute__ (( sentinel )) int |
| hv_alloc_pages ( struct hv_hypervisor *hv, ... ); |
| extern __attribute__ (( sentinel )) void |
| hv_free_pages ( struct hv_hypervisor *hv, ... ); |
| extern void hv_enable_sint ( struct hv_hypervisor *hv, unsigned int sintx ); |
| extern void hv_disable_sint ( struct hv_hypervisor *hv, unsigned int sintx ); |
| extern int hv_post_message ( struct hv_hypervisor *hv, unsigned int id, |
| unsigned int type, const void *data, size_t len ); |
| extern int hv_wait_for_message ( struct hv_hypervisor *hv, unsigned int sintx ); |
| extern int hv_signal_event ( struct hv_hypervisor *hv, unsigned int id, |
| unsigned int flag ); |
| |
| #endif /* _IPXE_HYPERV_H */ |