You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

hyperv.h 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #ifndef _IPXE_HYPERV_H
  2. #define _IPXE_HYPERV_H
  3. /** @file
  4. *
  5. * Hyper-V interface
  6. *
  7. */
  8. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  9. #include <stdint.h>
  10. #include <ipxe/io.h>
  11. /** Hyper-V interface identification */
  12. #define HV_INTERFACE_ID 0x31237648 /* "Hv#1" */
  13. /** Guest OS identity for iPXE
  14. *
  15. * This field comprises:
  16. *
  17. * Bit 63 : set to 1 to indicate an open source OS
  18. * Bits 62:56 : OS Type
  19. * Bits 55:48 : OS ID
  20. * Bits 47:16 : Version
  21. * Bits 15:0 : Build number
  22. *
  23. * There appears to be no central registry for the "OS Type". The
  24. * specification states that "Linux is 0x100", and the FreeBSD source
  25. * states that "FreeBSD is 0x200". Both of these statements are
  26. * actually referring to the combined "OS Type" and "OS ID" field.
  27. *
  28. * We choose to use 0x98ae: this is generated by setting bit 63 (to
  29. * indicate an open source OS) and setting the OS Type+ID equal to the
  30. * PnP vendor ID used in romprefix.S. No version information or build
  31. * number is included.
  32. */
  33. #define HV_GUEST_OS_ID_IPXE ( ( 1ULL << 63 ) | ( 0x18aeULL << 48 ) )
  34. /** Guest OS identity for Gen 2 UEFI firmware
  35. *
  36. * This does not conform to the documented structure for guest OS
  37. * identities.
  38. */
  39. #define HV_GUEST_OS_ID_UEFI ( 1ULL << 40 )
  40. /** Enable hypercall page */
  41. #define HV_HYPERCALL_ENABLE 0x00000001UL
  42. /** Enable SynIC */
  43. #define HV_SCONTROL_ENABLE 0x00000001UL
  44. /** Enable SynIC event flags */
  45. #define HV_SIEFP_ENABLE 0x00000001UL
  46. /** Enable SynIC messages */
  47. #define HV_SIMP_ENABLE 0x00000001UL
  48. /** Perform implicit EOI upon synthetic interrupt delivery */
  49. #define HV_SINT_AUTO_EOI 0x00020000UL
  50. /** Mask synthetic interrupt */
  51. #define HV_SINT_MASKED 0x00010000UL
  52. /** Synthetic interrupt vector */
  53. #define HV_SINT_VECTOR(x) ( (x) << 0 )
  54. /** Synthetic interrupt vector mask */
  55. #define HV_SINT_VECTOR_MASK HV_SINT_VECTOR ( 0xff )
  56. /** Maximum synthetic interrupt number */
  57. #define HV_SINT_MAX 15
  58. /** Post message */
  59. #define HV_POST_MESSAGE 0x005c
  60. /** A posted message
  61. *
  62. * This is the input parameter list for the HvPostMessage hypercall.
  63. */
  64. struct hv_post_message {
  65. /** Connection ID */
  66. uint32_t id;
  67. /** Padding */
  68. uint32_t reserved;
  69. /** Type */
  70. uint32_t type;
  71. /** Length of message */
  72. uint32_t len;
  73. /** Message */
  74. uint8_t data[240];
  75. } __attribute__ (( packed ));
  76. /** A received message
  77. *
  78. * This is the HV_MESSAGE structure from the Hypervisor Top-Level
  79. * Functional Specification. The field order given in the
  80. * documentation is incorrect.
  81. */
  82. struct hv_message {
  83. /** Type */
  84. uint32_t type;
  85. /** Length of message */
  86. uint8_t len;
  87. /** Flags */
  88. uint8_t flags;
  89. /** Padding */
  90. uint16_t reserved;
  91. /** Origin */
  92. uint64_t origin;
  93. /** Message */
  94. uint8_t data[240];
  95. } __attribute__ (( packed ));
  96. /** Signal event */
  97. #define HV_SIGNAL_EVENT 0x005d
  98. /** A signalled event */
  99. struct hv_signal_event {
  100. /** Connection ID */
  101. uint32_t id;
  102. /** Flag number */
  103. uint16_t flag;
  104. /** Reserved */
  105. uint16_t reserved;
  106. } __attribute__ (( packed ));
  107. /** A received event */
  108. struct hv_event {
  109. /** Event flags */
  110. uint8_t flags[256];
  111. } __attribute__ (( packed ));
  112. /** A monitor trigger group
  113. *
  114. * This is the HV_MONITOR_TRIGGER_GROUP structure from the Hypervisor
  115. * Top-Level Functional Specification.
  116. */
  117. struct hv_monitor_trigger {
  118. /** Pending events */
  119. uint32_t pending;
  120. /** Armed events */
  121. uint32_t armed;
  122. } __attribute__ (( packed ));
  123. /** A monitor parameter set
  124. *
  125. * This is the HV_MONITOR_PARAMETER structure from the Hypervisor
  126. * Top-Level Functional Specification.
  127. */
  128. struct hv_monitor_parameter {
  129. /** Connection ID */
  130. uint32_t id;
  131. /** Flag number */
  132. uint16_t flag;
  133. /** Reserved */
  134. uint16_t reserved;
  135. } __attribute__ (( packed ));
  136. /** A monitor page
  137. *
  138. * This is the HV_MONITOR_PAGE structure from the Hypervisor Top-Level
  139. * Functional Specification.
  140. */
  141. struct hv_monitor {
  142. /** Flags */
  143. uint32_t flags;
  144. /** Reserved */
  145. uint8_t reserved_a[4];
  146. /** Trigger groups */
  147. struct hv_monitor_trigger trigger[4];
  148. /** Reserved */
  149. uint8_t reserved_b[536];
  150. /** Latencies */
  151. uint16 latency[4][32];
  152. /** Reserved */
  153. uint8_t reserved_c[256];
  154. /** Parameters */
  155. struct hv_monitor_parameter param[4][32];
  156. /** Reserved */
  157. uint8_t reserved_d[1984];
  158. } __attribute__ (( packed ));
  159. /** A synthetic interrupt controller */
  160. struct hv_synic {
  161. /** Message page */
  162. struct hv_message *message;
  163. /** Event flag page */
  164. struct hv_event *event;
  165. };
  166. /** A message buffer */
  167. union hv_message_buffer {
  168. /** Posted message */
  169. struct hv_post_message posted;
  170. /** Received message */
  171. struct hv_message received;
  172. /** Signalled event */
  173. struct hv_signal_event signalled;
  174. };
  175. /** A Hyper-V hypervisor */
  176. struct hv_hypervisor {
  177. /** Hypercall page */
  178. void *hypercall;
  179. /** Synthetic interrupt controller (SynIC) */
  180. struct hv_synic synic;
  181. /** Message buffer */
  182. union hv_message_buffer *message;
  183. /** Virtual machine bus */
  184. struct vmbus *vmbus;
  185. };
  186. #include <bits/hyperv.h>
  187. /**
  188. * Calculate the number of pages covering an address range
  189. *
  190. * @v data Start of data
  191. * @v len Length of data (must be non-zero)
  192. * @ret pfn_count Number of pages covered
  193. */
  194. static inline unsigned int hv_pfn_count ( physaddr_t data, size_t len ) {
  195. unsigned int first_pfn = ( data / PAGE_SIZE );
  196. unsigned int last_pfn = ( ( data + len - 1 ) / PAGE_SIZE );
  197. return ( last_pfn - first_pfn + 1 );
  198. }
  199. extern __attribute__ (( sentinel )) int
  200. hv_alloc_pages ( struct hv_hypervisor *hv, ... );
  201. extern __attribute__ (( sentinel )) void
  202. hv_free_pages ( struct hv_hypervisor *hv, ... );
  203. extern void hv_enable_sint ( struct hv_hypervisor *hv, unsigned int sintx );
  204. extern void hv_disable_sint ( struct hv_hypervisor *hv, unsigned int sintx );
  205. extern int hv_post_message ( struct hv_hypervisor *hv, unsigned int id,
  206. unsigned int type, const void *data, size_t len );
  207. extern int hv_wait_for_message ( struct hv_hypervisor *hv, unsigned int sintx );
  208. extern int hv_signal_event ( struct hv_hypervisor *hv, unsigned int id,
  209. unsigned int flag );
  210. #endif /* _IPXE_HYPERV_H */