iPXE
hyperv.h
Go to the documentation of this file.
00001 #ifndef _IPXE_HYPERV_H
00002 #define _IPXE_HYPERV_H
00003 
00004 /** @file
00005  *
00006  * Hyper-V interface
00007  *
00008  */
00009 
00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00011 
00012 #include <stdint.h>
00013 #include <ipxe/io.h>
00014 
00015 /** Hyper-V interface identification */
00016 #define HV_INTERFACE_ID 0x31237648 /* "Hv#1" */
00017 
00018 /** Guest OS identity for iPXE
00019  *
00020  * This field comprises:
00021  *
00022  * Bit  63    : set to 1 to indicate an open source OS
00023  * Bits 62:56 : OS Type
00024  * Bits 55:48 : OS ID
00025  * Bits 47:16 : Version
00026  * Bits 15:0  : Build number
00027  *
00028  * There appears to be no central registry for the "OS Type".  The
00029  * specification states that "Linux is 0x100", and the FreeBSD source
00030  * states that "FreeBSD is 0x200".  Both of these statements are
00031  * actually referring to the combined "OS Type" and "OS ID" field.
00032  *
00033  * We choose to use 0x98ae: this is generated by setting bit 63 (to
00034  * indicate an open source OS) and setting the OS Type+ID equal to the
00035  * PnP vendor ID used in romprefix.S.  No version information or build
00036  * number is included.
00037  */
00038 #define HV_GUEST_OS_ID_IPXE ( ( 1ULL << 63 ) | ( 0x18aeULL << 48 ) )
00039 
00040 /** Guest OS identity for Gen 2 UEFI firmware
00041  *
00042  * This does not conform to the documented structure for guest OS
00043  * identities.
00044  */
00045 #define HV_GUEST_OS_ID_UEFI ( 1ULL << 40 )
00046 
00047 /** Enable hypercall page */
00048 #define HV_HYPERCALL_ENABLE 0x00000001UL
00049 
00050 /** Enable SynIC */
00051 #define HV_SCONTROL_ENABLE 0x00000001UL
00052 
00053 /** Enable SynIC event flags */
00054 #define HV_SIEFP_ENABLE 0x00000001UL
00055 
00056 /** Enable SynIC messages */
00057 #define HV_SIMP_ENABLE 0x00000001UL
00058 
00059 /** Perform implicit EOI upon synthetic interrupt delivery */
00060 #define HV_SINT_AUTO_EOI 0x00020000UL
00061 
00062 /** Mask synthetic interrupt */
00063 #define HV_SINT_MASKED 0x00010000UL
00064 
00065 /** Synthetic interrupt vector */
00066 #define HV_SINT_VECTOR(x) ( (x) << 0 )
00067 
00068 /** Synthetic interrupt vector mask */
00069 #define HV_SINT_VECTOR_MASK HV_SINT_VECTOR ( 0xff )
00070 
00071 /** Maximum synthetic interrupt number */
00072 #define HV_SINT_MAX 15
00073 
00074 /** Post message */
00075 #define HV_POST_MESSAGE 0x005c
00076 
00077 /** A posted message
00078  *
00079  * This is the input parameter list for the HvPostMessage hypercall.
00080  */
00081 struct hv_post_message {
00082         /** Connection ID */
00083         uint32_t id;
00084         /** Padding */
00085         uint32_t reserved;
00086         /** Type */
00087         uint32_t type;
00088         /** Length of message */
00089         uint32_t len;
00090         /** Message */
00091         uint8_t data[240];
00092 } __attribute__ (( packed ));
00093 
00094 /** A received message
00095  *
00096  * This is the HV_MESSAGE structure from the Hypervisor Top-Level
00097  * Functional Specification.  The field order given in the
00098  * documentation is incorrect.
00099  */
00100 struct hv_message {
00101         /** Type */
00102         uint32_t type;
00103         /** Length of message */
00104         uint8_t len;
00105         /** Flags */
00106         uint8_t flags;
00107         /** Padding */
00108         uint16_t reserved;
00109         /** Origin */
00110         uint64_t origin;
00111         /** Message */
00112         uint8_t data[240];
00113 } __attribute__ (( packed ));
00114 
00115 /** Signal event */
00116 #define HV_SIGNAL_EVENT 0x005d
00117 
00118 /** A signalled event */
00119 struct hv_signal_event {
00120         /** Connection ID */
00121         uint32_t id;
00122         /** Flag number */
00123         uint16_t flag;
00124         /** Reserved */
00125         uint16_t reserved;
00126 } __attribute__ (( packed ));
00127 
00128 /** A received event */
00129 struct hv_event {
00130         /** Event flags */
00131         uint8_t flags[256];
00132 } __attribute__ (( packed ));
00133 
00134 /** A monitor trigger group
00135  *
00136  * This is the HV_MONITOR_TRIGGER_GROUP structure from the Hypervisor
00137  * Top-Level Functional Specification.
00138  */
00139 struct hv_monitor_trigger {
00140         /** Pending events */
00141         uint32_t pending;
00142         /** Armed events */
00143         uint32_t armed;
00144 } __attribute__ (( packed ));
00145 
00146 /** A monitor parameter set
00147  *
00148  * This is the HV_MONITOR_PARAMETER structure from the Hypervisor
00149  * Top-Level Functional Specification.
00150  */
00151 struct hv_monitor_parameter {
00152         /** Connection ID */
00153         uint32_t id;
00154         /** Flag number */
00155         uint16_t flag;
00156         /** Reserved */
00157         uint16_t reserved;
00158 } __attribute__ (( packed ));
00159 
00160 /** A monitor page
00161  *
00162  * This is the HV_MONITOR_PAGE structure from the Hypervisor Top-Level
00163  * Functional Specification.
00164  */
00165 struct hv_monitor {
00166         /** Flags */
00167         uint32_t flags;
00168         /** Reserved */
00169         uint8_t reserved_a[4];
00170         /** Trigger groups */
00171         struct hv_monitor_trigger trigger[4];
00172         /** Reserved */
00173         uint8_t reserved_b[536];
00174         /** Latencies */
00175         uint16 latency[4][32];
00176         /** Reserved */
00177         uint8_t reserved_c[256];
00178         /** Parameters */
00179         struct hv_monitor_parameter param[4][32];
00180         /** Reserved */
00181         uint8_t reserved_d[1984];
00182 } __attribute__ (( packed ));
00183 
00184 /** A synthetic interrupt controller */
00185 struct hv_synic {
00186         /** Message page */
00187         struct hv_message *message;
00188         /** Event flag page */
00189         struct hv_event *event;
00190 };
00191 
00192 /** A message buffer */
00193 union hv_message_buffer {
00194         /** Posted message */
00195         struct hv_post_message posted;
00196         /** Received message */
00197         struct hv_message received;
00198         /** Signalled event */
00199         struct hv_signal_event signalled;
00200 };
00201 
00202 /** A Hyper-V hypervisor */
00203 struct hv_hypervisor {
00204         /** Hypercall page */
00205         void *hypercall;
00206         /** Synthetic interrupt controller (SynIC) */
00207         struct hv_synic synic;
00208         /** Message buffer */
00209         union hv_message_buffer *message;
00210         /** Virtual machine bus */
00211         struct vmbus *vmbus;
00212 };
00213 
00214 #include <bits/hyperv.h>
00215 
00216 /**
00217  * Calculate the number of pages covering an address range
00218  *
00219  * @v data              Start of data
00220  * @v len               Length of data (must be non-zero)
00221  * @ret pfn_count       Number of pages covered
00222  */
00223 static inline unsigned int hv_pfn_count ( physaddr_t data, size_t len ) {
00224         unsigned int first_pfn = ( data / PAGE_SIZE );
00225         unsigned int last_pfn = ( ( data + len - 1 ) / PAGE_SIZE );
00226 
00227         return ( last_pfn - first_pfn + 1 );
00228 }
00229 
00230 extern __attribute__ (( sentinel )) int
00231 hv_alloc_pages ( struct hv_hypervisor *hv, ... );
00232 extern __attribute__ (( sentinel )) void
00233 hv_free_pages ( struct hv_hypervisor *hv, ... );
00234 extern void hv_enable_sint ( struct hv_hypervisor *hv, unsigned int sintx );
00235 extern void hv_disable_sint ( struct hv_hypervisor *hv, unsigned int sintx );
00236 extern int hv_post_message ( struct hv_hypervisor *hv, unsigned int id,
00237                              unsigned int type, const void *data, size_t len );
00238 extern int hv_wait_for_message ( struct hv_hypervisor *hv, unsigned int sintx );
00239 extern int hv_signal_event ( struct hv_hypervisor *hv, unsigned int id,
00240                              unsigned int flag );
00241 
00242 #endif /* _IPXE_HYPERV_H */