iPXE
|
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 */