/* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) 2018, Microsoft Corporation. * All Rights Reserved. */ #ifndef _VMBUS_H_ #define _VMBUS_H_ /** * @file * * VMBUS Interface */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Forward declarations */ struct rte_vmbus_device; struct rte_vmbus_driver; struct rte_vmbus_bus; struct vmbus_channel; struct vmbus_mon_page; TAILQ_HEAD(rte_vmbus_device_list, rte_vmbus_device); TAILQ_HEAD(rte_vmbus_driver_list, rte_vmbus_driver); /* VMBus iterators */ #define FOREACH_DEVICE_ON_VMBUS(p) \ TAILQ_FOREACH(p, &(rte_vmbus_bus.device_list), next) #define FOREACH_DRIVER_ON_VMBUS(p) \ TAILQ_FOREACH(p, &(rte_vmbus_bus.driver_list), next) /** Maximum number of VMBUS resources. */ enum hv_uio_map { HV_TXRX_RING_MAP = 0, HV_INT_PAGE_MAP, HV_MON_PAGE_MAP, HV_RECV_BUF_MAP, HV_SEND_BUF_MAP }; #define VMBUS_MAX_RESOURCE 5 /** * A structure describing a VMBUS device. */ struct rte_vmbus_device { TAILQ_ENTRY(rte_vmbus_device) next; /**< Next probed VMBUS device */ const struct rte_vmbus_driver *driver; /**< Associated driver */ struct rte_device device; /**< Inherit core device */ rte_uuid_t device_id; /**< VMBUS device id */ rte_uuid_t class_id; /**< VMBUS device type */ uint32_t relid; /**< id for primary */ uint8_t monitor_id; /**< monitor page */ int uio_num; /**< UIO device number */ uint32_t *int_page; /**< VMBUS interrupt page */ struct vmbus_channel *primary; /**< VMBUS primary channel */ struct vmbus_mon_page *monitor_page; /**< VMBUS monitor page */ struct rte_intr_handle intr_handle; /**< Interrupt handle */ struct rte_mem_resource resource[VMBUS_MAX_RESOURCE]; }; /** * Initialization function for the driver called during VMBUS probing. */ typedef int (vmbus_probe_t)(struct rte_vmbus_driver *, struct rte_vmbus_device *); /** * Initialization function for the driver called during hot plugging. */ typedef int (vmbus_remove_t)(struct rte_vmbus_device *); /** * A structure describing a VMBUS driver. */ struct rte_vmbus_driver { TAILQ_ENTRY(rte_vmbus_driver) next; /**< Next in list. */ struct rte_driver driver; struct rte_vmbus_bus *bus; /**< VM bus reference. */ vmbus_probe_t *probe; /**< Device Probe function. */ vmbus_remove_t *remove; /**< Device Remove function. */ const rte_uuid_t *id_table; /**< ID table. */ }; /** * Structure describing the VM bus */ struct rte_vmbus_bus { struct rte_bus bus; /**< Inherit the generic class */ struct rte_vmbus_device_list device_list; /**< List of devices */ struct rte_vmbus_driver_list driver_list; /**< List of drivers */ }; /** * Scan the content of the VMBUS bus, and the devices in the devices * list * * @return * 0 on success, negative on error */ int rte_vmbus_scan(void); /** * Probe the VMBUS bus * * @return * - 0 on success. * - !0 on error. */ int rte_vmbus_probe(void); /** * Map the VMBUS device resources in user space virtual memory address * * @param dev * A pointer to a rte_vmbus_device structure describing the device * to use * * @return * 0 on success, negative on error and positive if no driver * is found for the device. */ int rte_vmbus_map_device(struct rte_vmbus_device *dev); /** * Unmap this device * * @param dev * A pointer to a rte_vmbus_device structure describing the device * to use */ void rte_vmbus_unmap_device(struct rte_vmbus_device *dev); /** * Get connection to primary VMBUS channel * * @param device * A pointer to a rte_vmbus_device structure describing the device * @param chan * A pointer to a VMBUS channel pointer that will be filled. * @return * - 0 Success; channel opened. * - -ENOMEM: Not enough memory available. * - -EINVAL: Regions could not be mapped. */ int rte_vmbus_chan_open(struct rte_vmbus_device *device, struct vmbus_channel **chan); /** * Free connection to VMBUS channel * * @param chan * VMBUS channel */ void rte_vmbus_chan_close(struct vmbus_channel *chan); /** * Gets the maximum number of channels supported on device * * @param device * A pointer to a rte_vmbus_device structure describing the device * @return * Number of channels available. */ int rte_vmbus_max_channels(const struct rte_vmbus_device *device); /** * Get a connection to new secondary vmbus channel * * @param primary * A pointer to primary VMBUS channel * @param chan * A pointer to a secondary VMBUS channel pointer that will be filled. * @return * - 0 Success; channel opened. * - -ENOMEM: Not enough memory available. * - -EINVAL: Regions could not be mapped. */ int rte_vmbus_subchan_open(struct vmbus_channel *primary, struct vmbus_channel **new_chan); /** * Disable IRQ for device * * @param device * VMBUS device */ void rte_vmbus_irq_mask(struct rte_vmbus_device *device); /** * Enable IRQ for device * * @param device * VMBUS device */ void rte_vmbus_irq_unmask(struct rte_vmbus_device *device); /** * Read (and wait) for IRQ * * @param device * VMBUS device */ int rte_vmbus_irq_read(struct rte_vmbus_device *device); /** * Test if channel is empty * * @param channel * Pointer to vmbus_channel structure. * @return * Return true if no data present in incoming ring. */ bool rte_vmbus_chan_rx_empty(const struct vmbus_channel *channel); /** * Send the specified buffer on the given channel * * @param channel * Pointer to vmbus_channel structure. * @param type * Type of packet that is being send e.g. negotiate, time * packet etc. * @param data * Pointer to the buffer to send * @param dlen * Number of bytes of data to send * @param xact * Identifier of the request * @param flags * Message type inband, rxbuf, gpa * @param need_sig * Is host signal tx is required (optional) * * Sends data in buffer directly to hyper-v via the vmbus */ int rte_vmbus_chan_send(struct vmbus_channel *channel, uint16_t type, void *data, uint32_t dlen, uint64_t xact, uint32_t flags, bool *need_sig); /** * Explicitly signal host that data is available * * @param * Pointer to vmbus_channel structure. * * Used when batching multiple sends and only signaling host * after the last send. */ void rte_vmbus_chan_signal_tx(const struct vmbus_channel *channel); /* Structure for scatter/gather I/O */ struct iova_list { rte_iova_t addr; uint32_t len; }; #define MAX_PAGE_BUFFER_COUNT 32 /** * Send a scattered buffer on the given channel * * @param channel * Pointer to vmbus_channel structure. * @param type * Type of packet that is being send e.g. negotiate, time * packet etc. * @param gpa * Array of buffers to send * @param gpacnt * Number of elements in iov * @param data * Pointer to the buffer additional data to send * @param dlen * Maximum size of what the the buffer will hold * @param xact * Identifier of the request * @param flags * Message type inband, rxbuf, gpa * @param need_sig * Is host signal tx is required (optional) * * Sends data in buffer directly to hyper-v via the vmbus */ int rte_vmbus_chan_send_sglist(struct vmbus_channel *channel, struct vmbus_gpa gpa[], uint32_t gpacnt, void *data, uint32_t dlen, uint64_t xact, bool *need_sig); /** * Receive response to request on the given channel * skips the channel header. * * @param channel * Pointer to vmbus_channel structure. * @param data * Pointer to the buffer you want to receive the data into. * @param len * Pointer to size of receive buffer (in/out) * @param * Pointer to received transaction_id * @return * On success, returns 0 * On failure, returns negative errno. */ int rte_vmbus_chan_recv(struct vmbus_channel *chan, void *data, uint32_t *len, uint64_t *request_id); /** * Receive response to request on the given channel * includes the channel header. * * @param channel * Pointer to vmbus_channel structure. * @param data * Pointer to the buffer you want to receive the data into. * @param len * Pointer to size of receive buffer (in/out) * @return * On success, returns number of bytes read. * On failure, returns negative errno. */ int rte_vmbus_chan_recv_raw(struct vmbus_channel *chan, void *data, uint32_t *len); /** * Notify host of bytes read (after recv_raw) * Signals host if required. * * @param channel * Pointer to vmbus_channel structure. * @param bytes_read * Number of bytes read since last signal */ void rte_vmbus_chan_signal_read(struct vmbus_channel *chan, uint32_t bytes_read); /** * Determine sub channel index of the given channel * * @param channel * Pointer to vmbus_channel structure. * @return * Sub channel index (0 for primary) */ uint16_t rte_vmbus_sub_channel_index(const struct vmbus_channel *chan); /** * Set the host monitor latency hint * * @param dev * VMBUS device * @param chan * Pointer to vmbus_channel structure. * @param latency * Approximate wait period between hypervisor examinations of * the trigger page (in nanoseconds). */ void rte_vmbus_set_latency(const struct rte_vmbus_device *dev, const struct vmbus_channel *chan, uint32_t latency); /** * Register a VMBUS driver. * * @param driver * A pointer to a rte_vmbus_driver structure describing the driver * to be registered. */ void rte_vmbus_register(struct rte_vmbus_driver *driver); /** * For debug dump contents of ring buffer. * * @param channel * Pointer to vmbus_channel structure. */ void rte_vmbus_chan_dump(FILE *f, const struct vmbus_channel *chan); /** * Unregister a VMBUS driver. * * @param driver * A pointer to a rte_vmbus_driver structure describing the driver * to be unregistered. */ void rte_vmbus_unregister(struct rte_vmbus_driver *driver); /** Helper for VMBUS device registration from driver instance */ #define RTE_PMD_REGISTER_VMBUS(nm, vmbus_drv) \ RTE_INIT(vmbusinitfn_ ##nm) \ { \ (vmbus_drv).driver.name = RTE_STR(nm); \ rte_vmbus_register(&vmbus_drv); \ } \ RTE_PMD_EXPORT_NAME(nm, __COUNTER__) #ifdef __cplusplus } #endif #endif /* _VMBUS_H_ */