xref: /spdk/include/spdk_internal/virtio.h (revision 3f912cf0e905f0862cf767064ac23579f1fb08fb)
1488570ebSJim Harris /*   SPDX-License-Identifier: BSD-3-Clause
29dde5e5cSDariusz Stojaczyk  *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
39dde5e5cSDariusz Stojaczyk  *   All rights reserved.
49dde5e5cSDariusz Stojaczyk  */
59dde5e5cSDariusz Stojaczyk 
69dde5e5cSDariusz Stojaczyk #ifndef SPDK_VIRTIO_H
79dde5e5cSDariusz Stojaczyk #define SPDK_VIRTIO_H
89dde5e5cSDariusz Stojaczyk 
99dde5e5cSDariusz Stojaczyk #include "spdk/stdinc.h"
109dde5e5cSDariusz Stojaczyk 
119dde5e5cSDariusz Stojaczyk #include <linux/virtio_ring.h>
129dde5e5cSDariusz Stojaczyk #include <linux/virtio_pci.h>
139dde5e5cSDariusz Stojaczyk #include <linux/virtio_config.h>
149dde5e5cSDariusz Stojaczyk 
154e8e97c8STomasz Zawadzki #include "spdk/log.h"
169dde5e5cSDariusz Stojaczyk #include "spdk/likely.h"
179dde5e5cSDariusz Stojaczyk #include "spdk/queue.h"
189dde5e5cSDariusz Stojaczyk #include "spdk/json.h"
19a83f91c2SBen Walker #include "spdk/thread.h"
20724c9aa7SDariusz Stojaczyk #include "spdk/pci_ids.h"
2137fb6222SDariusz Stojaczyk #include "spdk/env.h"
229dde5e5cSDariusz Stojaczyk 
239dde5e5cSDariusz Stojaczyk /**
249dde5e5cSDariusz Stojaczyk  * The maximum virtqueue size is 2^15. Use that value as the end of
259dde5e5cSDariusz Stojaczyk  * descriptor chain terminator since it will never be a valid index
269dde5e5cSDariusz Stojaczyk  * in the descriptor table. This is used to verify we are correctly
279dde5e5cSDariusz Stojaczyk  * handling vq_free_cnt.
289dde5e5cSDariusz Stojaczyk  */
299dde5e5cSDariusz Stojaczyk #define VQ_RING_DESC_CHAIN_END 32768
309dde5e5cSDariusz Stojaczyk 
319dde5e5cSDariusz Stojaczyk #define SPDK_VIRTIO_MAX_VIRTQUEUES 0x100
329dde5e5cSDariusz Stojaczyk 
339dde5e5cSDariusz Stojaczyk /* Extra status define for readability */
349dde5e5cSDariusz Stojaczyk #define VIRTIO_CONFIG_S_RESET 0
359dde5e5cSDariusz Stojaczyk 
369dde5e5cSDariusz Stojaczyk struct virtio_dev_ops;
379dde5e5cSDariusz Stojaczyk 
389dde5e5cSDariusz Stojaczyk struct virtio_dev {
399dde5e5cSDariusz Stojaczyk 	struct virtqueue **vqs;
409dde5e5cSDariusz Stojaczyk 
419dde5e5cSDariusz Stojaczyk 	/** Name of this virtio dev set by backend */
429dde5e5cSDariusz Stojaczyk 	char		*name;
439dde5e5cSDariusz Stojaczyk 
447755bed3SDariusz Stojaczyk 	/** Fixed number of backend-specific non-I/O virtqueues. */
457755bed3SDariusz Stojaczyk 	uint16_t	fixed_queues_num;
467755bed3SDariusz Stojaczyk 
477755bed3SDariusz Stojaczyk 	/** Max number of virtqueues the host supports. */
489dde5e5cSDariusz Stojaczyk 	uint16_t	max_queues;
499dde5e5cSDariusz Stojaczyk 
509dde5e5cSDariusz Stojaczyk 	/** Common device & guest features. */
519dde5e5cSDariusz Stojaczyk 	uint64_t	negotiated_features;
529dde5e5cSDariusz Stojaczyk 
539dde5e5cSDariusz Stojaczyk 	int		is_hw;
549dde5e5cSDariusz Stojaczyk 
559dde5e5cSDariusz Stojaczyk 	/** Modern/legacy virtio device flag. */
569dde5e5cSDariusz Stojaczyk 	uint8_t		modern;
579dde5e5cSDariusz Stojaczyk 
589dde5e5cSDariusz Stojaczyk 	/** Mutex for asynchronous virtqueue-changing operations. */
599dde5e5cSDariusz Stojaczyk 	pthread_mutex_t	mutex;
609dde5e5cSDariusz Stojaczyk 
619dde5e5cSDariusz Stojaczyk 	/** Backend-specific callbacks. */
629dde5e5cSDariusz Stojaczyk 	const struct virtio_dev_ops *backend_ops;
639dde5e5cSDariusz Stojaczyk 
649dde5e5cSDariusz Stojaczyk 	/** Context for the backend ops */
659dde5e5cSDariusz Stojaczyk 	void		*ctx;
669dde5e5cSDariusz Stojaczyk };
679dde5e5cSDariusz Stojaczyk 
689dde5e5cSDariusz Stojaczyk struct virtio_dev_ops {
6962844ae3SDariusz Stojaczyk 	int (*read_dev_cfg)(struct virtio_dev *hw, size_t offset,
709dde5e5cSDariusz Stojaczyk 			    void *dst, int len);
7162844ae3SDariusz Stojaczyk 	int (*write_dev_cfg)(struct virtio_dev *hw, size_t offset,
729dde5e5cSDariusz Stojaczyk 			     const void *src, int len);
739dde5e5cSDariusz Stojaczyk 	uint8_t (*get_status)(struct virtio_dev *hw);
749dde5e5cSDariusz Stojaczyk 	void (*set_status)(struct virtio_dev *hw, uint8_t status);
759dde5e5cSDariusz Stojaczyk 
769dde5e5cSDariusz Stojaczyk 	/**
779dde5e5cSDariusz Stojaczyk 	 * Get device features. The features might be already
789dde5e5cSDariusz Stojaczyk 	 * negotiated with driver (guest) features.
799dde5e5cSDariusz Stojaczyk 	 */
809dde5e5cSDariusz Stojaczyk 	uint64_t (*get_features)(struct virtio_dev *vdev);
819dde5e5cSDariusz Stojaczyk 
829dde5e5cSDariusz Stojaczyk 	/**
839dde5e5cSDariusz Stojaczyk 	 * Negotiate and set device features.
849dde5e5cSDariusz Stojaczyk 	 * The negotiation can fail with return code -1.
859dde5e5cSDariusz Stojaczyk 	 * This function should also set vdev->negotiated_features field.
869dde5e5cSDariusz Stojaczyk 	 */
879dde5e5cSDariusz Stojaczyk 	int (*set_features)(struct virtio_dev *vdev, uint64_t features);
889dde5e5cSDariusz Stojaczyk 
899dde5e5cSDariusz Stojaczyk 	/** Destruct virtio device */
909dde5e5cSDariusz Stojaczyk 	void (*destruct_dev)(struct virtio_dev *vdev);
919dde5e5cSDariusz Stojaczyk 
920a1a4ce1SDariusz Stojaczyk 	uint16_t (*get_queue_size)(struct virtio_dev *vdev, uint16_t queue_id);
939dde5e5cSDariusz Stojaczyk 	int (*setup_queue)(struct virtio_dev *hw, struct virtqueue *vq);
949dde5e5cSDariusz Stojaczyk 	void (*del_queue)(struct virtio_dev *hw, struct virtqueue *vq);
959dde5e5cSDariusz Stojaczyk 	void (*notify_queue)(struct virtio_dev *hw, struct virtqueue *vq);
969dde5e5cSDariusz Stojaczyk 
971a6dac40SPawel Wodkowski 	void (*dump_json_info)(struct virtio_dev *hw, struct spdk_json_write_ctx *w);
981a6dac40SPawel Wodkowski 	void (*write_json_config)(struct virtio_dev *hw, struct spdk_json_write_ctx *w);
999dde5e5cSDariusz Stojaczyk };
1009dde5e5cSDariusz Stojaczyk 
1019dde5e5cSDariusz Stojaczyk struct vq_desc_extra {
1029dde5e5cSDariusz Stojaczyk 	void *cookie;
1039dde5e5cSDariusz Stojaczyk 	uint16_t ndescs;
1049dde5e5cSDariusz Stojaczyk };
1059dde5e5cSDariusz Stojaczyk 
1069dde5e5cSDariusz Stojaczyk struct virtqueue {
1079dde5e5cSDariusz Stojaczyk 	struct virtio_dev *vdev; /**< owner of this virtqueue */
1089dde5e5cSDariusz Stojaczyk 	struct vring vq_ring;  /**< vring keeping desc, used and avail */
1099dde5e5cSDariusz Stojaczyk 	/**
1109dde5e5cSDariusz Stojaczyk 	 * Last consumed descriptor in the used table,
1119dde5e5cSDariusz Stojaczyk 	 * trails vq_ring.used->idx.
1129dde5e5cSDariusz Stojaczyk 	 */
1139dde5e5cSDariusz Stojaczyk 	uint16_t vq_used_cons_idx;
1149dde5e5cSDariusz Stojaczyk 	uint16_t vq_nentries;  /**< vring desc numbers */
1159dde5e5cSDariusz Stojaczyk 	uint16_t vq_free_cnt;  /**< num of desc available */
1169dde5e5cSDariusz Stojaczyk 	uint16_t vq_avail_idx; /**< sync until needed */
1179dde5e5cSDariusz Stojaczyk 
1189dde5e5cSDariusz Stojaczyk 	void *vq_ring_virt_mem;  /**< virtual address of vring */
1199dde5e5cSDariusz Stojaczyk 	unsigned int vq_ring_size;
1209dde5e5cSDariusz Stojaczyk 
1219dde5e5cSDariusz Stojaczyk 	uint64_t vq_ring_mem; /**< physical address of vring */
1229dde5e5cSDariusz Stojaczyk 
1239dde5e5cSDariusz Stojaczyk 	/**
1249dde5e5cSDariusz Stojaczyk 	 * Head of the free chain in the descriptor table. If
1259dde5e5cSDariusz Stojaczyk 	 * there are no free descriptors, this will be set to
1269dde5e5cSDariusz Stojaczyk 	 * VQ_RING_DESC_CHAIN_END.
1279dde5e5cSDariusz Stojaczyk 	 */
1289dde5e5cSDariusz Stojaczyk 	uint16_t  vq_desc_head_idx;
1299dde5e5cSDariusz Stojaczyk 
1309dde5e5cSDariusz Stojaczyk 	/**
1319dde5e5cSDariusz Stojaczyk 	 * Tail of the free chain in desc table. If
1329dde5e5cSDariusz Stojaczyk 	 * there are no free descriptors, this will be set to
1339dde5e5cSDariusz Stojaczyk 	 * VQ_RING_DESC_CHAIN_END.
1349dde5e5cSDariusz Stojaczyk 	 */
1359dde5e5cSDariusz Stojaczyk 	uint16_t  vq_desc_tail_idx;
1369dde5e5cSDariusz Stojaczyk 	uint16_t  vq_queue_index;   /**< PCI queue index */
1379dde5e5cSDariusz Stojaczyk 	uint16_t  *notify_addr;
1389dde5e5cSDariusz Stojaczyk 
1399dde5e5cSDariusz Stojaczyk 	/** Thread that's polling this queue. */
1409dde5e5cSDariusz Stojaczyk 	struct spdk_thread *owner_thread;
1419dde5e5cSDariusz Stojaczyk 
1429dde5e5cSDariusz Stojaczyk 	uint16_t req_start;
1439dde5e5cSDariusz Stojaczyk 	uint16_t req_end;
14403b12a98SDariusz Stojaczyk 	uint16_t reqs_finished;
1459dde5e5cSDariusz Stojaczyk 
1469dde5e5cSDariusz Stojaczyk 	struct vq_desc_extra vq_descx[0];
1479dde5e5cSDariusz Stojaczyk };
1489dde5e5cSDariusz Stojaczyk 
1499dde5e5cSDariusz Stojaczyk enum spdk_virtio_desc_type {
1509dde5e5cSDariusz Stojaczyk 	SPDK_VIRTIO_DESC_RO = 0, /**< Read only */
1519dde5e5cSDariusz Stojaczyk 	SPDK_VIRTIO_DESC_WR = VRING_DESC_F_WRITE, /**< Write only */
1529dde5e5cSDariusz Stojaczyk 	/* TODO VIRTIO_DESC_INDIRECT */
1539dde5e5cSDariusz Stojaczyk };
1549dde5e5cSDariusz Stojaczyk 
1559dde5e5cSDariusz Stojaczyk /** Context for creating PCI virtio_devs */
1569dde5e5cSDariusz Stojaczyk struct virtio_pci_ctx;
1579dde5e5cSDariusz Stojaczyk 
1589dde5e5cSDariusz Stojaczyk /**
1599dde5e5cSDariusz Stojaczyk  * Callback for creating virtio_dev from a PCI device.
1605c0c104bSDariusz Stojaczyk  * \param pci_ctx PCI context to be associated with a virtio_dev
1615c0c104bSDariusz Stojaczyk  * \param ctx context provided by the user
1629dde5e5cSDariusz Stojaczyk  * \return 0 on success, -1 on error.
1639dde5e5cSDariusz Stojaczyk  */
1645c0c104bSDariusz Stojaczyk typedef int (*virtio_pci_create_cb)(struct virtio_pci_ctx *pci_ctx, void *ctx);
1659dde5e5cSDariusz Stojaczyk 
1669dde5e5cSDariusz Stojaczyk uint16_t virtio_recv_pkts(struct virtqueue *vq, void **io, uint32_t *len, uint16_t io_cnt);
1679dde5e5cSDariusz Stojaczyk 
1689dde5e5cSDariusz Stojaczyk /**
169587002f5SDariusz Stojaczyk  * Start a new request on the current vring head position and associate it
170587002f5SDariusz Stojaczyk  * with an opaque cookie object. The previous request in given vq will be
171587002f5SDariusz Stojaczyk  * made visible to the device in hopes it can be processed early, but there's
172587002f5SDariusz Stojaczyk  * no guarantee it will be until the device is notified with \c
173587002f5SDariusz Stojaczyk  * virtqueue_req_flush. This behavior is simply an optimization and virtqueues
174587002f5SDariusz Stojaczyk  * must always be flushed. Empty requests (with no descriptors added) will be
175587002f5SDariusz Stojaczyk  * ignored. The device owning given virtqueue must be started.
1769dde5e5cSDariusz Stojaczyk  *
1779dde5e5cSDariusz Stojaczyk  * \param vq virtio queue
178587002f5SDariusz Stojaczyk  * \param cookie opaque object to associate with this request. Once the request
1799dde5e5cSDariusz Stojaczyk  * is sent, processed and a response is received, the same object will be
180587002f5SDariusz Stojaczyk  * returned to the user after calling the virtio poll API.
1819dde5e5cSDariusz Stojaczyk  * \param iovcnt number of required iovectors for the request. This can be
1828b94174aSDariusz Stojaczyk  * higher than than the actual number of iovectors to be added.
1838b94174aSDariusz Stojaczyk  * \return 0 on success or negative errno otherwise. If the `iovcnt` is
1848b94174aSDariusz Stojaczyk  * greater than virtqueue depth, -EINVAL is returned. If simply not enough
1858b94174aSDariusz Stojaczyk  * iovectors are available, -ENOMEM is returned.
1869dde5e5cSDariusz Stojaczyk  */
1879dde5e5cSDariusz Stojaczyk int virtqueue_req_start(struct virtqueue *vq, void *cookie, int iovcnt);
1889dde5e5cSDariusz Stojaczyk 
1899dde5e5cSDariusz Stojaczyk /**
190587002f5SDariusz Stojaczyk  * Flush a virtqueue. This will notify the device if it's required.
191587002f5SDariusz Stojaczyk  * The device owning given virtqueue must be started.
1929dde5e5cSDariusz Stojaczyk  *
1939dde5e5cSDariusz Stojaczyk  * \param vq virtio queue
1949dde5e5cSDariusz Stojaczyk  */
1959dde5e5cSDariusz Stojaczyk void virtqueue_req_flush(struct virtqueue *vq);
1969dde5e5cSDariusz Stojaczyk 
1979dde5e5cSDariusz Stojaczyk /**
1989dde5e5cSDariusz Stojaczyk  * Abort the very last request in a virtqueue. This will restore virtqueue
1999dde5e5cSDariusz Stojaczyk  * state to the point before the last request was created. Note that this
2009dde5e5cSDariusz Stojaczyk  * is only effective if a queue hasn't been flushed yet.  The device owning
2019dde5e5cSDariusz Stojaczyk  * given virtqueue must be started.
2029dde5e5cSDariusz Stojaczyk  *
2039dde5e5cSDariusz Stojaczyk  * \param vq virtio queue
2049dde5e5cSDariusz Stojaczyk  */
2059dde5e5cSDariusz Stojaczyk void virtqueue_req_abort(struct virtqueue *vq);
2069dde5e5cSDariusz Stojaczyk 
2079dde5e5cSDariusz Stojaczyk /**
2089dde5e5cSDariusz Stojaczyk  * Add iovec chain to the last created request. This call does not provide any
2099dde5e5cSDariusz Stojaczyk  * error-checking. The caller has to ensure that he doesn't add more iovs than
2109dde5e5cSDariusz Stojaczyk  * what was specified during request creation. The device owning given virtqueue
2119dde5e5cSDariusz Stojaczyk  * must be started.
2129dde5e5cSDariusz Stojaczyk  *
2139dde5e5cSDariusz Stojaczyk  * \param vq virtio queue
2149dde5e5cSDariusz Stojaczyk  * \param iovs iovec array
2159dde5e5cSDariusz Stojaczyk  * \param iovcnt number of iovs in iovec array
2169dde5e5cSDariusz Stojaczyk  * \param desc_type type of all given iovectors
2179dde5e5cSDariusz Stojaczyk  */
2189dde5e5cSDariusz Stojaczyk void virtqueue_req_add_iovs(struct virtqueue *vq, struct iovec *iovs, uint16_t iovcnt,
2199dde5e5cSDariusz Stojaczyk 			    enum spdk_virtio_desc_type desc_type);
2209dde5e5cSDariusz Stojaczyk 
2219dde5e5cSDariusz Stojaczyk /**
2229dde5e5cSDariusz Stojaczyk  * Construct a virtio device.  The device will be in stopped state by default.
2239dde5e5cSDariusz Stojaczyk  * Before doing any I/O, it has to be manually started via \c virtio_dev_restart.
2249dde5e5cSDariusz Stojaczyk  *
2259dde5e5cSDariusz Stojaczyk  * \param vdev memory for virtio device, must be zeroed
226fb12bbecSDariusz Stojaczyk  * \param name name for the virtio device
2279dde5e5cSDariusz Stojaczyk  * \param ops backend callbacks
228fb12bbecSDariusz Stojaczyk  * \param ops_ctx argument for the backend callbacks
229fb12bbecSDariusz Stojaczyk  * \return zero on success, or negative error code otherwise
2309dde5e5cSDariusz Stojaczyk  */
231fb12bbecSDariusz Stojaczyk int virtio_dev_construct(struct virtio_dev *vdev, const char *name,
232fb12bbecSDariusz Stojaczyk 			 const struct virtio_dev_ops *ops, void *ops_ctx);
2339dde5e5cSDariusz Stojaczyk 
2349dde5e5cSDariusz Stojaczyk /**
2357755bed3SDariusz Stojaczyk  * Reset the device and prepare it to be `virtio_dev_start`ed.  This call
2367755bed3SDariusz Stojaczyk  * will also renegotiate feature flags.
2379dde5e5cSDariusz Stojaczyk  *
2389dde5e5cSDariusz Stojaczyk  * \param vdev virtio device
2399dde5e5cSDariusz Stojaczyk  * \param req_features features this driver supports. A VIRTIO_F_VERSION_1
2409dde5e5cSDariusz Stojaczyk  * flag will be automatically appended, as legacy devices are not supported.
2419dde5e5cSDariusz Stojaczyk  */
2427755bed3SDariusz Stojaczyk int virtio_dev_reset(struct virtio_dev *vdev, uint64_t req_features);
2437755bed3SDariusz Stojaczyk 
2447755bed3SDariusz Stojaczyk /**
2457755bed3SDariusz Stojaczyk  * Notify the host to start processing this virtio device.  This is
2467755bed3SDariusz Stojaczyk  * a blocking call that won't return until the host has started.
2477755bed3SDariusz Stojaczyk  * This will also allocate virtqueues.
2487755bed3SDariusz Stojaczyk  *
2497755bed3SDariusz Stojaczyk  * \param vdev virtio device
2507755bed3SDariusz Stojaczyk  * \param max_queues number of queues to allocate. The max number of
2517755bed3SDariusz Stojaczyk  * usable I/O queues is also limited by the host device. `vdev` will be
2527755bed3SDariusz Stojaczyk  * started successfully even if the host supports less queues than requested.
253*3f912cf0SMichal Berger  * \param fixed_queue_num number of queues preceding the first
2547755bed3SDariusz Stojaczyk  * request queue. For Virtio-SCSI this is equal to 2, as there are
2557755bed3SDariusz Stojaczyk  * additional event and control queues.
2567755bed3SDariusz Stojaczyk  */
2577755bed3SDariusz Stojaczyk int virtio_dev_start(struct virtio_dev *vdev, uint16_t max_queues,
2587755bed3SDariusz Stojaczyk 		     uint16_t fixed_queues_num);
2599dde5e5cSDariusz Stojaczyk 
2609dde5e5cSDariusz Stojaczyk /**
2619dde5e5cSDariusz Stojaczyk  * Stop the host from processing the device.  This is a blocking call
2629dde5e5cSDariusz Stojaczyk  * that won't return until all outstanding I/O has been processed on
2637755bed3SDariusz Stojaczyk  * the host (virtio device) side. In order to re-start the device, it
2647755bed3SDariusz Stojaczyk  * has to be `virtio_dev_reset` first.
2659dde5e5cSDariusz Stojaczyk  *
2669dde5e5cSDariusz Stojaczyk  * \param vdev virtio device
2679dde5e5cSDariusz Stojaczyk  */
2689dde5e5cSDariusz Stojaczyk void virtio_dev_stop(struct virtio_dev *vdev);
2699dde5e5cSDariusz Stojaczyk 
2709dde5e5cSDariusz Stojaczyk /**
2719dde5e5cSDariusz Stojaczyk  * Destruct a virtio device.  Note that it must be in the stopped state.
2729dde5e5cSDariusz Stojaczyk  * The virtio_dev should be manually freed afterwards.
2739dde5e5cSDariusz Stojaczyk  *
2749dde5e5cSDariusz Stojaczyk  * \param vdev virtio device
2759dde5e5cSDariusz Stojaczyk  */
2769dde5e5cSDariusz Stojaczyk void virtio_dev_destruct(struct virtio_dev *vdev);
2779dde5e5cSDariusz Stojaczyk 
2789dde5e5cSDariusz Stojaczyk /**
2799dde5e5cSDariusz Stojaczyk  * Bind a virtqueue with given index to the current thread;
2809dde5e5cSDariusz Stojaczyk  *
2819dde5e5cSDariusz Stojaczyk  * This function is thread-safe.
2829dde5e5cSDariusz Stojaczyk  *
2839dde5e5cSDariusz Stojaczyk  * \param vdev vhost device
2849dde5e5cSDariusz Stojaczyk  * \param index virtqueue index
2859dde5e5cSDariusz Stojaczyk  * \return 0 on success, -1 in case a virtqueue with given index either
2869dde5e5cSDariusz Stojaczyk  * does not exists or is already acquired.
2879dde5e5cSDariusz Stojaczyk  */
2889dde5e5cSDariusz Stojaczyk int virtio_dev_acquire_queue(struct virtio_dev *vdev, uint16_t index);
2899dde5e5cSDariusz Stojaczyk 
2909dde5e5cSDariusz Stojaczyk /**
2919dde5e5cSDariusz Stojaczyk  * Look for unused queue and bind it to the current thread.  This will
2929dde5e5cSDariusz Stojaczyk  * scan the queues in range from *start_index* (inclusive) up to
2939dde5e5cSDariusz Stojaczyk  * vdev->max_queues (exclusive).
2949dde5e5cSDariusz Stojaczyk  *
2959dde5e5cSDariusz Stojaczyk  * This function is thread-safe.
2969dde5e5cSDariusz Stojaczyk  *
2979dde5e5cSDariusz Stojaczyk  * \param vdev vhost device
2989dde5e5cSDariusz Stojaczyk  * \param start_index virtqueue index to start looking from
2999dde5e5cSDariusz Stojaczyk  * \return index of acquired queue or -1 in case no unused queue in given range
3009dde5e5cSDariusz Stojaczyk  * has been found
3019dde5e5cSDariusz Stojaczyk  */
3029dde5e5cSDariusz Stojaczyk int32_t virtio_dev_find_and_acquire_queue(struct virtio_dev *vdev, uint16_t start_index);
3039dde5e5cSDariusz Stojaczyk 
3049dde5e5cSDariusz Stojaczyk /**
3059dde5e5cSDariusz Stojaczyk  * Get thread that acquired given virtqueue.
3069dde5e5cSDariusz Stojaczyk  *
3079dde5e5cSDariusz Stojaczyk  * This function is thread-safe.
3089dde5e5cSDariusz Stojaczyk  *
3099dde5e5cSDariusz Stojaczyk  * \param vdev vhost device
3109dde5e5cSDariusz Stojaczyk  * \param index index of virtqueue
3119dde5e5cSDariusz Stojaczyk  * \return thread that acquired given virtqueue. If the queue is unused
3129dde5e5cSDariusz Stojaczyk  * or doesn't exist a NULL is returned.
3139dde5e5cSDariusz Stojaczyk  */
3149dde5e5cSDariusz Stojaczyk struct spdk_thread *virtio_dev_queue_get_thread(struct virtio_dev *vdev, uint16_t index);
3159dde5e5cSDariusz Stojaczyk 
3169dde5e5cSDariusz Stojaczyk /**
3179dde5e5cSDariusz Stojaczyk  * Check if virtqueue with given index is acquired.
3189dde5e5cSDariusz Stojaczyk  *
3199dde5e5cSDariusz Stojaczyk  * This function is thread-safe.
3209dde5e5cSDariusz Stojaczyk  *
3219dde5e5cSDariusz Stojaczyk  * \param vdev vhost device
3229dde5e5cSDariusz Stojaczyk  * \param index index of virtqueue
3239dde5e5cSDariusz Stojaczyk  * \return virtqueue acquire status. in case of invalid index *false* is returned.
3249dde5e5cSDariusz Stojaczyk  */
3259dde5e5cSDariusz Stojaczyk bool virtio_dev_queue_is_acquired(struct virtio_dev *vdev, uint16_t index);
3269dde5e5cSDariusz Stojaczyk 
3279dde5e5cSDariusz Stojaczyk /**
3289dde5e5cSDariusz Stojaczyk  * Release previously acquired queue.
3299dde5e5cSDariusz Stojaczyk  *
3309dde5e5cSDariusz Stojaczyk  * This function must be called from the thread that acquired the queue.
3319dde5e5cSDariusz Stojaczyk  *
3329dde5e5cSDariusz Stojaczyk  * \param vdev vhost device
3339dde5e5cSDariusz Stojaczyk  * \param index index of virtqueue to release
3349dde5e5cSDariusz Stojaczyk  */
3359dde5e5cSDariusz Stojaczyk void virtio_dev_release_queue(struct virtio_dev *vdev, uint16_t index);
3369dde5e5cSDariusz Stojaczyk 
3379dde5e5cSDariusz Stojaczyk /**
3389dde5e5cSDariusz Stojaczyk  * Get Virtio status flags.
3399dde5e5cSDariusz Stojaczyk  *
3409dde5e5cSDariusz Stojaczyk  * \param vdev virtio device
3419dde5e5cSDariusz Stojaczyk  */
3429dde5e5cSDariusz Stojaczyk uint8_t virtio_dev_get_status(struct virtio_dev *vdev);
3439dde5e5cSDariusz Stojaczyk 
3449dde5e5cSDariusz Stojaczyk /**
3459dde5e5cSDariusz Stojaczyk  * Set Virtio status flag.  The flags have to be set in very specific order
3469dde5e5cSDariusz Stojaczyk  * defined the VIRTIO 1.0 spec section 3.1.1. To unset the flags, stop the
3479dde5e5cSDariusz Stojaczyk  * device or set \c VIRTIO_CONFIG_S_RESET status flag. There is no way to
3489dde5e5cSDariusz Stojaczyk  * unset only particular flags.
3499dde5e5cSDariusz Stojaczyk  *
3509dde5e5cSDariusz Stojaczyk  * \param vdev virtio device
3519dde5e5cSDariusz Stojaczyk  * \param flag flag to set
3529dde5e5cSDariusz Stojaczyk  */
3539dde5e5cSDariusz Stojaczyk void virtio_dev_set_status(struct virtio_dev *vdev, uint8_t flag);
3549dde5e5cSDariusz Stojaczyk 
3559dde5e5cSDariusz Stojaczyk /**
3569dde5e5cSDariusz Stojaczyk  * Write raw data into the device config at given offset.  This call does not
3579dde5e5cSDariusz Stojaczyk  * provide any error checking.
3589dde5e5cSDariusz Stojaczyk  *
3599dde5e5cSDariusz Stojaczyk  * \param vdev virtio device
3609dde5e5cSDariusz Stojaczyk  * \param offset offset in bytes
3619dde5e5cSDariusz Stojaczyk  * \param src pointer to data to copy from
3629dde5e5cSDariusz Stojaczyk  * \param len length of data to copy in bytes
36362844ae3SDariusz Stojaczyk  * \return 0 on success, negative errno otherwise
3649dde5e5cSDariusz Stojaczyk  */
36562844ae3SDariusz Stojaczyk int virtio_dev_write_dev_config(struct virtio_dev *vdev, size_t offset, const void *src, int len);
3669dde5e5cSDariusz Stojaczyk 
3679dde5e5cSDariusz Stojaczyk /**
3689dde5e5cSDariusz Stojaczyk  * Read raw data from the device config at given offset.  This call does not
3699dde5e5cSDariusz Stojaczyk  * provide any error checking.
3709dde5e5cSDariusz Stojaczyk  *
3719dde5e5cSDariusz Stojaczyk  * \param vdev virtio device
3729dde5e5cSDariusz Stojaczyk  * \param offset offset in bytes
3739dde5e5cSDariusz Stojaczyk  * \param dst pointer to buffer to copy data into
3749dde5e5cSDariusz Stojaczyk  * \param len length of data to copy in bytes
37562844ae3SDariusz Stojaczyk  * \return 0 on success, negative errno otherwise
3769dde5e5cSDariusz Stojaczyk  */
37762844ae3SDariusz Stojaczyk int virtio_dev_read_dev_config(struct virtio_dev *vdev, size_t offset, void *dst, int len);
3789dde5e5cSDariusz Stojaczyk 
3799dde5e5cSDariusz Stojaczyk /**
3809dde5e5cSDariusz Stojaczyk  * Get backend-specific ops for given device.
3819dde5e5cSDariusz Stojaczyk  *
3829dde5e5cSDariusz Stojaczyk  * \param vdev virtio device
3839dde5e5cSDariusz Stojaczyk  */
3849dde5e5cSDariusz Stojaczyk const struct virtio_dev_ops *virtio_dev_backend_ops(struct virtio_dev *vdev);
3859dde5e5cSDariusz Stojaczyk 
3869dde5e5cSDariusz Stojaczyk /**
3879dde5e5cSDariusz Stojaczyk  * Check if the device has negotiated given feature bit.
3889dde5e5cSDariusz Stojaczyk  *
3899dde5e5cSDariusz Stojaczyk  * \param vdev virtio device
3909dde5e5cSDariusz Stojaczyk  * \param bit feature bit
3919dde5e5cSDariusz Stojaczyk  */
3929dde5e5cSDariusz Stojaczyk static inline bool
virtio_dev_has_feature(struct virtio_dev * vdev,uint64_t bit)3939dde5e5cSDariusz Stojaczyk virtio_dev_has_feature(struct virtio_dev *vdev, uint64_t bit)
3949dde5e5cSDariusz Stojaczyk {
3959dde5e5cSDariusz Stojaczyk 	return !!(vdev->negotiated_features & (1ULL << bit));
3969dde5e5cSDariusz Stojaczyk }
3979dde5e5cSDariusz Stojaczyk 
3989dde5e5cSDariusz Stojaczyk /**
3999dde5e5cSDariusz Stojaczyk  * Dump all device specific information into given json stream.
4009dde5e5cSDariusz Stojaczyk  *
4019dde5e5cSDariusz Stojaczyk  * \param vdev virtio device
4029dde5e5cSDariusz Stojaczyk  * \param w json stream
4039dde5e5cSDariusz Stojaczyk  */
4041a6dac40SPawel Wodkowski void virtio_dev_dump_json_info(struct virtio_dev *vdev, struct spdk_json_write_ctx *w);
4059dde5e5cSDariusz Stojaczyk 
4069dde5e5cSDariusz Stojaczyk /**
407724c9aa7SDariusz Stojaczyk  * Enumerate all PCI Virtio devices of given type on the system.
4089dde5e5cSDariusz Stojaczyk  *
4099dde5e5cSDariusz Stojaczyk  * \param enum_cb a function to be called for each valid PCI device.
4105c0c104bSDariusz Stojaczyk  * If a virtio_dev is has been created, the callback should return 0.
4119dde5e5cSDariusz Stojaczyk  * Returning any other value will cause the PCI context to be freed,
4129dde5e5cSDariusz Stojaczyk  * making it unusable.
4135c0c104bSDariusz Stojaczyk  * \param enum_ctx additional opaque context to be passed into `enum_cb`
414724c9aa7SDariusz Stojaczyk  * \param pci_device_id PCI Device ID of devices to iterate through
4159dde5e5cSDariusz Stojaczyk  */
4165c0c104bSDariusz Stojaczyk int virtio_pci_dev_enumerate(virtio_pci_create_cb enum_cb, void *enum_ctx,
4175c0c104bSDariusz Stojaczyk 			     uint16_t pci_device_id);
4189dde5e5cSDariusz Stojaczyk 
4199dde5e5cSDariusz Stojaczyk /**
42037fb6222SDariusz Stojaczyk  * Attach a PCI Virtio device of given type.
42137fb6222SDariusz Stojaczyk  *
42237fb6222SDariusz Stojaczyk  * \param create_cb callback to create a virtio_dev.
42337fb6222SDariusz Stojaczyk  * If virtio_dev is has been created, the callback should return 0.
42437fb6222SDariusz Stojaczyk  * Returning any other value will cause the PCI context to be freed,
42537fb6222SDariusz Stojaczyk  * making it unusable.
42637fb6222SDariusz Stojaczyk  * \param enum_ctx additional opaque context to be passed into `enum_cb`
4274c890c31SJin Yu  * \param device_id Device ID of devices to iterate through
42837fb6222SDariusz Stojaczyk  * \param pci_addr PCI address of the device to attach
42937fb6222SDariusz Stojaczyk  */
43037fb6222SDariusz Stojaczyk int virtio_pci_dev_attach(virtio_pci_create_cb create_cb, void *enum_ctx,
4314c890c31SJin Yu 			  uint16_t device_id, struct spdk_pci_addr *pci_addr);
43237fb6222SDariusz Stojaczyk 
43337fb6222SDariusz Stojaczyk /**
4349dde5e5cSDariusz Stojaczyk  * Connect to a vhost-user device and init corresponding virtio_dev struct.
4359dde5e5cSDariusz Stojaczyk  * The virtio_dev will have to be freed with \c virtio_dev_free.
4369dde5e5cSDariusz Stojaczyk  *
4379dde5e5cSDariusz Stojaczyk  * \param vdev preallocated vhost device struct to operate on
4389dde5e5cSDariusz Stojaczyk  * \param name name of this virtio device
4399dde5e5cSDariusz Stojaczyk  * \param path path to the Unix domain socket of the vhost-user device
4409dde5e5cSDariusz Stojaczyk  * \param queue_size size of each of the queues
4419dde5e5cSDariusz Stojaczyk  * \return virtio device
4429dde5e5cSDariusz Stojaczyk  */
4439dde5e5cSDariusz Stojaczyk int virtio_user_dev_init(struct virtio_dev *vdev, const char *name, const char *path,
4447755bed3SDariusz Stojaczyk 			 uint32_t queue_size);
4459dde5e5cSDariusz Stojaczyk 
4469dde5e5cSDariusz Stojaczyk /**
447295e54d1SChangpeng Liu  * Connect to a vfio-user device and init corresponding virtio_dev struct.
448295e54d1SChangpeng Liu  * The virtio_dev will have to be freed with \c virtio_dev_free.
449295e54d1SChangpeng Liu  *
450295e54d1SChangpeng Liu  * \param vdev preallocated vhost device struct to operate on
451295e54d1SChangpeng Liu  * \param name name of this virtio device
452295e54d1SChangpeng Liu  * \param path path to the Unix domain socket of the vhost-user device
453295e54d1SChangpeng Liu  * \return virtio device
454295e54d1SChangpeng Liu  */
455295e54d1SChangpeng Liu int virtio_vfio_user_dev_init(struct virtio_dev *vdev, const char *name, const char *path);
456295e54d1SChangpeng Liu 
457295e54d1SChangpeng Liu /**
4587755bed3SDariusz Stojaczyk  * Initialize virtio_dev for a given PCI device.
4599dde5e5cSDariusz Stojaczyk  * The virtio_dev has to be freed with \c virtio_dev_destruct.
4609dde5e5cSDariusz Stojaczyk  *
4619dde5e5cSDariusz Stojaczyk  * \param vdev preallocated vhost device struct to operate on
4629dde5e5cSDariusz Stojaczyk  * \param name name of this virtio device
4639dde5e5cSDariusz Stojaczyk  * \param pci_ctx context of the PCI device
4649dde5e5cSDariusz Stojaczyk  * \return 0 on success, -1 on error.
4659dde5e5cSDariusz Stojaczyk  */
4669dde5e5cSDariusz Stojaczyk int virtio_pci_dev_init(struct virtio_dev *vdev, const char *name,
4679dde5e5cSDariusz Stojaczyk 			struct virtio_pci_ctx *pci_ctx);
4689dde5e5cSDariusz Stojaczyk 
469ebea4dd6SJin Yu /**
470ebea4dd6SJin Yu  * Process the uevent which is accepted from the kernel and the
471ebea4dd6SJin Yu  * uevent descript the physical device hot add or remove action.
472ebea4dd6SJin Yu  *
473ebea4dd6SJin Yu  * \param fd the file descriptor of the kobject netlink socket
474ebea4dd6SJin Yu  * \param device_id virtio device ID used to represent virtio-blk or other device.
475ebea4dd6SJin Yu  * \return the name of the virtio device on success, NULL means it
476ebea4dd6SJin Yu  * is not a suitable uevent.
477ebea4dd6SJin Yu  */
4788dd1cd21SBen Walker const char *virtio_pci_dev_event_process(int fd, uint16_t device_id);
479ebea4dd6SJin Yu 
4809dde5e5cSDariusz Stojaczyk #endif /* SPDK_VIRTIO_H */
481