iPXE
vmbus.h
Go to the documentation of this file.
00001 #ifndef _IPXE_VMBUS_H
00002 #define _IPXE_VMBUS_H
00003 
00004 /** @file
00005  *
00006  * Hyper-V virtual machine bus
00007  *
00008  */
00009 
00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00011 
00012 #include <byteswap.h>
00013 #include <ipxe/uuid.h>
00014 #include <ipxe/device.h>
00015 #include <ipxe/tables.h>
00016 #include <ipxe/uaccess.h>
00017 #include <ipxe/iobuf.h>
00018 #include <ipxe/hyperv.h>
00019 
00020 /** VMBus message connection ID */
00021 #define VMBUS_MESSAGE_ID 1
00022 
00023 /** VMBus event connection ID */
00024 #define VMBUS_EVENT_ID 2
00025 
00026 /** VMBus message type */
00027 #define VMBUS_MESSAGE_TYPE 1
00028 
00029 /** VMBus message synthetic interrupt */
00030 #define VMBUS_MESSAGE_SINT 2
00031 
00032 /** VMBus version number */
00033 union vmbus_version {
00034         /** Raw version */
00035         uint32_t raw;
00036         /** Major/minor version */
00037         struct {
00038                 /** Minor version */
00039                 uint16_t minor;
00040                 /** Major version */
00041                 uint16_t major;
00042         };
00043 } __attribute__ (( packed ));
00044 
00045 /** Known VMBus protocol versions */
00046 enum vmbus_raw_version {
00047         /** Windows Server 2008 */
00048         VMBUS_VERSION_WS2008 = ( ( 0 << 16 ) | ( 13 << 0 ) ),
00049         /** Windows 7 */
00050         VMBUS_VERSION_WIN7 = ( ( 1 << 16 ) | ( 1 << 0 ) ),
00051         /** Windows 8 */
00052         VMBUS_VERSION_WIN8 = ( ( 2 << 16 ) | ( 4 << 0 ) ),
00053         /** Windows 8.1 */
00054         VMBUS_VERSION_WIN8_1 = ( ( 3 << 16 ) | ( 0 << 0 ) ),
00055 };
00056 
00057 /** Guest physical address range descriptor */
00058 struct vmbus_gpa_range {
00059         /** Byte count */
00060         uint32_t len;
00061         /** Starting byte offset */
00062         uint32_t offset;
00063         /** Page frame numbers
00064          *
00065          * The length of this array is implied by the byte count and
00066          * starting offset.
00067          */
00068         uint64_t pfn[0];
00069 } __attribute__ (( packed ));
00070 
00071 /** VMBus message header */
00072 struct vmbus_message_header {
00073         /** Message type */
00074         uint32_t type;
00075         /** Reserved */
00076         uint32_t reserved;
00077 } __attribute__ (( packed ));
00078 
00079 /** VMBus message types */
00080 enum vmbus_message_type {
00081         VMBUS_OFFER_CHANNEL = 1,
00082         VMBUS_REQUEST_OFFERS = 3,
00083         VMBUS_ALL_OFFERS_DELIVERED = 4,
00084         VMBUS_OPEN_CHANNEL = 5,
00085         VMBUS_OPEN_CHANNEL_RESULT = 6,
00086         VMBUS_CLOSE_CHANNEL = 7,
00087         VMBUS_GPADL_HEADER = 8,
00088         VMBUS_GPADL_CREATED = 10,
00089         VMBUS_GPADL_TEARDOWN = 11,
00090         VMBUS_GPADL_TORNDOWN = 12,
00091         VMBUS_INITIATE_CONTACT = 14,
00092         VMBUS_VERSION_RESPONSE = 15,
00093         VMBUS_UNLOAD = 16,
00094         VMBUS_UNLOAD_RESPONSE = 17,
00095 };
00096 
00097 /** VMBus "offer channel" message */
00098 struct vmbus_offer_channel {
00099         /** Message header */
00100         struct vmbus_message_header header;
00101         /** Channel type */
00102         union uuid type;
00103         /** Channel instance */
00104         union uuid instance;
00105         /** Reserved */
00106         uint8_t reserved_a[16];
00107         /** Flags */
00108         uint16_t flags;
00109         /** Reserved */
00110         uint8_t reserved_b[2];
00111         /** User data */
00112         uint8_t data[120];
00113         /** Reserved */
00114         uint8_t reserved_c[4];
00115         /** Channel ID */
00116         uint32_t channel;
00117         /** Monitor ID */
00118         uint8_t monitor;
00119         /** Monitor exists */
00120         uint8_t monitored;
00121         /** Reserved */
00122         uint8_t reserved[2];
00123         /** Connection ID */
00124         uint32_t connection;
00125 } __attribute__ (( packed ));
00126 
00127 /** VMBus "open channel" message */
00128 struct vmbus_open_channel {
00129         /** Message header */
00130         struct vmbus_message_header header;
00131         /** Channel ID */
00132         uint32_t channel;
00133         /** Open ID */
00134         uint32_t id;
00135         /** Ring buffer GPADL ID */
00136         uint32_t gpadl;
00137         /** Reserved */
00138         uint32_t reserved;
00139         /** Outbound ring buffer size (in pages) */
00140         uint32_t out_pages;
00141         /** User-specific data */
00142         uint8_t data[120];
00143 } __attribute__ (( packed ));
00144 
00145 /** VMBus "open channel result" message */
00146 struct vmbus_open_channel_result {
00147         /** Message header */
00148         struct vmbus_message_header header;
00149         /** Channel ID */
00150         uint32_t channel;
00151         /** Open ID */
00152         uint32_t id;
00153         /** Status */
00154         uint32_t status;
00155 } __attribute__ (( packed ));
00156 
00157 /** VMBus "close channel" message */
00158 struct vmbus_close_channel {
00159         /** Message header */
00160         struct vmbus_message_header header;
00161         /** Channel ID */
00162         uint32_t channel;
00163 } __attribute__ (( packed ));
00164 
00165 /** VMBus "GPADL header" message */
00166 struct vmbus_gpadl_header {
00167         /** Message header */
00168         struct vmbus_message_header header;
00169         /** Channel ID */
00170         uint32_t channel;
00171         /** GPADL ID */
00172         uint32_t gpadl;
00173         /** Length of range descriptors */
00174         uint16_t range_len;
00175         /** Number of range descriptors */
00176         uint16_t range_count;
00177         /** Range descriptors */
00178         struct vmbus_gpa_range range[0];
00179 } __attribute__ (( packed ));
00180 
00181 /** VMBus "GPADL created" message */
00182 struct vmbus_gpadl_created {
00183         /** Message header */
00184         struct vmbus_message_header header;
00185         /** Channel ID */
00186         uint32_t channel;
00187         /** GPADL ID */
00188         uint32_t gpadl;
00189         /** Creation status */
00190         uint32_t status;
00191 } __attribute__ (( packed ));
00192 
00193 /** VMBus "GPADL teardown" message */
00194 struct vmbus_gpadl_teardown {
00195         /** Message header */
00196         struct vmbus_message_header header;
00197         /** Channel ID */
00198         uint32_t channel;
00199         /** GPADL ID */
00200         uint32_t gpadl;
00201 } __attribute__ (( packed ));
00202 
00203 /** VMBus "GPADL torndown" message */
00204 struct vmbus_gpadl_torndown {
00205         /** Message header */
00206         struct vmbus_message_header header;
00207         /** GPADL ID */
00208         uint32_t gpadl;
00209 } __attribute__ (( packed ));
00210 
00211 /** VMBus "initiate contact" message */
00212 struct vmbus_initiate_contact {
00213         /** Message header */
00214         struct vmbus_message_header header;
00215         /** Requested version */
00216         union vmbus_version version;
00217         /** Target virtual CPU */
00218         uint32_t vcpu;
00219         /** Interrupt page base address */
00220         uint64_t intr;
00221         /** Parent to child monitor page base address */
00222         uint64_t monitor_in;
00223         /** Child to parent monitor page base address */
00224         uint64_t monitor_out;
00225 } __attribute__ (( packed ));
00226 
00227 /** VMBus "version response" message */
00228 struct vmbus_version_response {
00229         /** Message header */
00230         struct vmbus_message_header header;
00231         /** Version is supported */
00232         uint8_t supported;
00233         /** Reserved */
00234         uint8_t reserved[3];
00235         /** Version */
00236         union vmbus_version version;
00237 } __attribute__ (( packed ));
00238 
00239 /** VMBus message */
00240 union vmbus_message {
00241         /** Common message header */
00242         struct vmbus_message_header header;
00243         /** "Offer channel" message */
00244         struct vmbus_offer_channel offer;
00245         /** "Open channel" message */
00246         struct vmbus_open_channel open;
00247         /** "Open channel result" message */
00248         struct vmbus_open_channel_result opened;
00249         /** "Close channel" message */
00250         struct vmbus_close_channel close;
00251         /** "GPADL header" message */
00252         struct vmbus_gpadl_header gpadlhdr;
00253         /** "GPADL created" message */
00254         struct vmbus_gpadl_created created;
00255         /** "GPADL teardown" message */
00256         struct vmbus_gpadl_teardown teardown;
00257         /** "GPADL torndown" message */
00258         struct vmbus_gpadl_torndown torndown;
00259         /** "Initiate contact" message */
00260         struct vmbus_initiate_contact initiate;
00261         /** "Version response" message */
00262         struct vmbus_version_response version;
00263 };
00264 
00265 /** VMBus packet header */
00266 struct vmbus_packet_header {
00267         /** Type */
00268         uint16_t type;
00269         /** Length of packet header (in quadwords) */
00270         uint16_t hdr_qlen;
00271         /** Length of packet (in quadwords) */
00272         uint16_t qlen;
00273         /** Flags */
00274         uint16_t flags;
00275         /** Transaction ID
00276          *
00277          * This is an opaque token: we therefore treat it as
00278          * native-endian and don't worry about byte-swapping.
00279          */
00280         uint64_t xid;
00281 } __attribute__ (( packed ));
00282 
00283 /** VMBus packet types */
00284 enum vmbus_packet_type {
00285         VMBUS_DATA_INBAND = 6,
00286         VMBUS_DATA_XFER_PAGES = 7,
00287         VMBUS_DATA_GPA_DIRECT = 9,
00288         VMBUS_CANCELLATION = 10,
00289         VMBUS_COMPLETION = 11,
00290 };
00291 
00292 /** VMBus packet flags */
00293 enum vmbus_packet_flags {
00294         VMBUS_COMPLETION_REQUESTED = 0x0001,
00295 };
00296 
00297 /** VMBus GPA direct header */
00298 struct vmbus_gpa_direct_header {
00299         /** Packet header */
00300         struct vmbus_packet_header header;
00301         /** Reserved */
00302         uint32_t reserved;
00303         /** Number of range descriptors */
00304         uint32_t range_count;
00305         /** Range descriptors */
00306         struct vmbus_gpa_range range[0];
00307 } __attribute__ (( packed ));
00308 
00309 /** VMBus transfer page range */
00310 struct vmbus_xfer_page_range {
00311         /** Length */
00312         uint32_t len;
00313         /** Offset */
00314         uint32_t offset;
00315 } __attribute__ (( packed ));
00316 
00317 /** VMBus transfer page header */
00318 struct vmbus_xfer_page_header {
00319         /** Packet header */
00320         struct vmbus_packet_header header;
00321         /** Page set ID */
00322         uint16_t pageset;
00323         /** Sender owns page set */
00324         uint8_t owner;
00325         /** Reserved */
00326         uint8_t reserved;
00327         /** Number of range descriptors */
00328         uint32_t range_count;
00329         /** Range descriptors */
00330         struct vmbus_xfer_page_range range[0];
00331 } __attribute__ (( packed ));
00332 
00333 /** Maximum expected size of VMBus packet header */
00334 #define VMBUS_PACKET_MAX_HEADER_LEN 64
00335 
00336 /** VMBus maximum-sized packet header */
00337 union vmbus_packet_header_max {
00338         /** Common header */
00339         struct vmbus_packet_header header;
00340         /** GPA direct header */
00341         struct vmbus_gpa_direct_header gpa;
00342         /** Transfer page header */
00343         struct vmbus_xfer_page_header xfer;
00344         /** Padding to maximum supported size */
00345         uint8_t padding[VMBUS_PACKET_MAX_HEADER_LEN];
00346 } __attribute__ (( packed ));
00347 
00348 /** VMBus packet footer */
00349 struct vmbus_packet_footer {
00350         /** Reserved */
00351         uint32_t reserved;
00352         /** Producer index of the first byte of the packet */
00353         uint32_t prod;
00354 } __attribute__ (( packed ));
00355 
00356 /** VMBus ring buffer
00357  *
00358  * This is the structure of the each of the ring buffers created when
00359  * a VMBus channel is opened.
00360  */
00361 struct vmbus_ring {
00362         /** Producer index (modulo ring length) */
00363         uint32_t prod;
00364         /** Consumer index (modulo ring length) */
00365         uint32_t cons;
00366         /** Interrupt mask */
00367         uint32_t intr_mask;
00368         /** Reserved */
00369         uint8_t reserved[4084];
00370         /** Ring buffer contents */
00371         uint8_t data[0];
00372 } __attribute__ (( packed ));
00373 
00374 /** VMBus interrupt page */
00375 struct vmbus_interrupt {
00376         /** Inbound interrupts */
00377         uint8_t in[ PAGE_SIZE / 2 ];
00378         /** Outbound interrupts */
00379         uint8_t out[ PAGE_SIZE / 2 ];
00380 } __attribute__ (( packed ));
00381 
00382 /** A virtual machine bus */
00383 struct vmbus {
00384         /** Interrupt page */
00385         struct vmbus_interrupt *intr;
00386         /** Inbound notifications */
00387         struct hv_monitor *monitor_in;
00388         /** Outbound notifications */
00389         struct hv_monitor *monitor_out;
00390         /** Received message buffer */
00391         const union vmbus_message *message;
00392 };
00393 
00394 struct vmbus_device;
00395 
00396 /** VMBus channel operations */
00397 struct vmbus_channel_operations {
00398         /**
00399          * Handle received control packet
00400          *
00401          * @v vmdev             VMBus device
00402          * @v xid               Transaction ID
00403          * @v data              Data
00404          * @v len               Length of data
00405          * @ret rc              Return status code
00406          */
00407         int ( * recv_control ) ( struct vmbus_device *vmdev, uint64_t xid,
00408                                  const void *data, size_t len );
00409         /**
00410          * Handle received data packet
00411          *
00412          * @v vmdev             VMBus device
00413          * @v xid               Transaction ID
00414          * @v data              Data
00415          * @v len               Length of data
00416          * @v list              List of I/O buffers
00417          * @ret rc              Return status code
00418          *
00419          * This function takes ownership of the I/O buffer.  It should
00420          * eventually call vmbus_send_completion() to indicate to the
00421          * host that the buffer can be reused.
00422          */
00423         int ( * recv_data ) ( struct vmbus_device *vmdev, uint64_t xid,
00424                               const void *data, size_t len,
00425                               struct list_head *list );
00426         /**
00427          * Handle received completion packet
00428          *
00429          * @v vmdev             VMBus device
00430          * @v xid               Transaction ID
00431          * @v data              Data
00432          * @v len               Length of data
00433          * @ret rc              Return status code
00434          */
00435         int ( * recv_completion ) ( struct vmbus_device *vmdev, uint64_t xid,
00436                                     const void *data, size_t len );
00437         /**
00438          * Handle received cancellation packet
00439          *
00440          * @v vmdev             VMBus device
00441          * @v xid               Transaction ID
00442          * @ret rc              Return status code
00443          */
00444         int ( * recv_cancellation ) ( struct vmbus_device *vmdev,
00445                                       uint64_t xid );
00446 };
00447 
00448 struct vmbus_xfer_pages;
00449 
00450 /** VMBus transfer page set operations */
00451 struct vmbus_xfer_pages_operations {
00452         /**
00453          * Copy data from transfer page
00454          *
00455          * @v pages             Transfer page set
00456          * @v data              Data buffer
00457          * @v offset            Offset within page set
00458          * @v len               Length within page set
00459          * @ret rc              Return status code
00460          */
00461         int ( * copy ) ( struct vmbus_xfer_pages *pages, void *data,
00462                          size_t offset, size_t len );
00463 };
00464 
00465 /** VMBus transfer page set */
00466 struct vmbus_xfer_pages {
00467         /** List of all transfer page sets */
00468         struct list_head list;
00469         /** Page set ID (in protocol byte order) */
00470         uint16_t pageset;
00471         /** Page set operations */
00472         struct vmbus_xfer_pages_operations *op;
00473 };
00474 
00475 /** A VMBus device */
00476 struct vmbus_device {
00477         /** Generic iPXE device */
00478         struct device dev;
00479         /** Hyper-V hypervisor */
00480         struct hv_hypervisor *hv;
00481 
00482         /** Channel instance */
00483         union uuid instance;
00484         /** Channel ID */
00485         unsigned int channel;
00486         /** Monitor ID */
00487         unsigned int monitor;
00488         /** Signal channel
00489          *
00490          * @v vmdev             VMBus device
00491          */
00492         void ( * signal ) ( struct vmbus_device *vmdev );
00493 
00494         /** Outbound ring buffer length */
00495         uint32_t out_len;
00496         /** Inbound ring buffer length */
00497         uint32_t in_len;
00498         /** Outbound ring buffer */
00499         struct vmbus_ring *out;
00500         /** Inbound ring buffer */
00501         struct vmbus_ring *in;
00502         /** Ring buffer GPADL ID */
00503         unsigned int gpadl;
00504 
00505         /** Channel operations */
00506         struct vmbus_channel_operations *op;
00507         /** Maximum expected data packet length */
00508         size_t mtu;
00509         /** Packet buffer */
00510         void *packet;
00511         /** List of transfer page sets */
00512         struct list_head pages;
00513 
00514         /** Driver */
00515         struct vmbus_driver *driver;
00516         /** Driver-private data */
00517         void *priv;
00518 };
00519 
00520 /** A VMBus device driver */
00521 struct vmbus_driver {
00522         /** Name */
00523         const char *name;
00524         /** Device type */
00525         union uuid type;
00526         /** Probe device
00527          *
00528          * @v vmdev             VMBus device
00529          * @ret rc              Return status code
00530          */
00531         int ( * probe ) ( struct vmbus_device *vmdev );
00532         /** Reset device
00533          *
00534          * @v vmdev             VMBus device
00535          * @ret rc              Return status code
00536          */
00537         int ( * reset ) ( struct vmbus_device *vmdev );
00538         /** Remove device
00539          *
00540          * @v vmdev             VMBus device
00541          */
00542         void ( * remove ) ( struct vmbus_device *vmdev );
00543 };
00544 
00545 /** VMBus device driver table */
00546 #define VMBUS_DRIVERS __table ( struct vmbus_driver, "vmbus_drivers" )
00547 
00548 /** Declare a VMBus device driver */
00549 #define __vmbus_driver __table_entry ( VMBUS_DRIVERS, 01 )
00550 
00551 /**
00552  * Set VMBus device driver-private data
00553  *
00554  * @v vmdev             VMBus device
00555  * @v priv              Private data
00556  */
00557 static inline void vmbus_set_drvdata ( struct vmbus_device *vmdev, void *priv ){
00558         vmdev->priv = priv;
00559 }
00560 
00561 /**
00562  * Get VMBus device driver-private data
00563  *
00564  * @v vmdev             VMBus device
00565  * @ret priv            Private data
00566  */
00567 static inline void * vmbus_get_drvdata ( struct vmbus_device *vmdev ) {
00568         return vmdev->priv;
00569 }
00570 
00571 /** Construct VMBus type */
00572 #define VMBUS_TYPE( a, b, c, d, e0, e1, e2, e3, e4, e5 ) {              \
00573         .canonical = {                                                  \
00574                 cpu_to_le32 ( a ), cpu_to_le16 ( b ),                   \
00575                 cpu_to_le16 ( c ), cpu_to_be16 ( d ),                   \
00576                 { e0, e1, e2, e3, e4, e5 }                              \
00577          } }
00578 
00579 /**
00580  * Check if data is present in ring buffer
00581  *
00582  * @v vmdev             VMBus device
00583  * @v has_data          Data is present
00584  */
00585 static inline __attribute__ (( always_inline )) int
00586 vmbus_has_data ( struct vmbus_device *vmdev ) {
00587 
00588         return ( vmdev->in->prod != vmdev->in->cons );
00589 }
00590 
00591 /**
00592  * Register transfer page set
00593  *
00594  * @v vmdev             VMBus device
00595  * @v pages             Transfer page set
00596  * @ret rc              Return status code
00597  */
00598 static inline __attribute__ (( always_inline )) int
00599 vmbus_register_pages ( struct vmbus_device *vmdev,
00600                        struct vmbus_xfer_pages *pages ) {
00601 
00602         list_add ( &pages->list, &vmdev->pages );
00603         return 0;
00604 }
00605 
00606 /**
00607  * Unregister transfer page set
00608  *
00609  * @v vmdev             VMBus device
00610  * @v pages             Transfer page set
00611  */
00612 static inline __attribute__ (( always_inline )) void
00613 vmbus_unregister_pages ( struct vmbus_device *vmdev,
00614                          struct vmbus_xfer_pages *pages ) {
00615 
00616         list_check_contains_entry ( pages, &vmdev->pages, list );
00617         list_del ( &pages->list );
00618 }
00619 
00620 extern unsigned int vmbus_obsolete_gpadl;
00621 
00622 /**
00623  * Check if GPADL is obsolete
00624  *
00625  * @v gpadl             GPADL ID
00626  * @v is_obsolete       GPADL ID is obsolete
00627  *
00628  * Check if GPADL is obsolete (i.e. was created before the most recent
00629  * Hyper-V reset).
00630  */
00631 static inline __attribute__ (( always_inline )) int
00632 vmbus_gpadl_is_obsolete ( unsigned int gpadl ) {
00633 
00634         return ( gpadl <= vmbus_obsolete_gpadl );
00635 }
00636 
00637 extern int vmbus_establish_gpadl ( struct vmbus_device *vmdev, userptr_t data,
00638                                    size_t len );
00639 extern int vmbus_gpadl_teardown ( struct vmbus_device *vmdev,
00640                                   unsigned int gpadl );
00641 extern int vmbus_open ( struct vmbus_device *vmdev,
00642                         struct vmbus_channel_operations *op,
00643                         size_t out_len, size_t in_len, size_t mtu );
00644 extern void vmbus_close ( struct vmbus_device *vmdev );
00645 extern int vmbus_send_control ( struct vmbus_device *vmdev, uint64_t xid,
00646                                 const void *data, size_t len );
00647 extern int vmbus_send_data ( struct vmbus_device *vmdev, uint64_t xid,
00648                              const void *data, size_t len,
00649                              struct io_buffer *iobuf );
00650 extern int vmbus_send_completion ( struct vmbus_device *vmdev, uint64_t xid,
00651                                    const void *data, size_t len );
00652 extern int vmbus_send_cancellation ( struct vmbus_device *vmdev, uint64_t xid );
00653 extern int vmbus_poll ( struct vmbus_device *vmdev );
00654 extern void vmbus_dump_channel ( struct vmbus_device *vmdev );
00655 
00656 extern int vmbus_probe ( struct hv_hypervisor *hv, struct device *parent );
00657 extern int vmbus_reset ( struct hv_hypervisor *hv, struct device *parent );
00658 extern void vmbus_remove ( struct hv_hypervisor *hv, struct device *parent );
00659 
00660 #endif /* _IPXE_VMBUS_H */