OpenAMP Library  latest
Loading...
Searching...
No Matches
virtqueue.h
Go to the documentation of this file.
1#ifndef VIRTQUEUE_H_
2#define VIRTQUEUE_H_
3
4/*-
5 * Copyright (c) 2011, Bryan Venteicher <bryanv@FreeBSD.org>
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: BSD-2-Clause
9 *
10 * $FreeBSD$
11 */
12
13#include <stdbool.h>
14#include <stdint.h>
15
16#if defined __cplusplus
17extern "C" {
18#endif
19
20#include <openamp/virtio_ring.h>
21#include <metal/alloc.h>
22#include <metal/io.h>
23#include <metal/cache.h>
24
25/* Error Codes */
26#define VQ_ERROR_BASE -3000
27#define ERROR_VRING_FULL (VQ_ERROR_BASE - 1)
28#define ERROR_INVLD_DESC_IDX (VQ_ERROR_BASE - 2)
29#define ERROR_EMPTY_RING (VQ_ERROR_BASE - 3)
30#define ERROR_NO_MEM (VQ_ERROR_BASE - 4)
31#define ERROR_VRING_MAX_DESC (VQ_ERROR_BASE - 5)
32#define ERROR_VRING_ALIGN (VQ_ERROR_BASE - 6)
33#define ERROR_VRING_NO_BUFF (VQ_ERROR_BASE - 7)
34#define ERROR_VQUEUE_INVLD_PARAM (VQ_ERROR_BASE - 8)
35
36#define VQUEUE_SUCCESS 0
37
38/* The maximum virtqueue size is 2^15. Use that value as the end of
39 * descriptor chain terminator since it will never be a valid index
40 * in the descriptor table. This is used to verify we are correctly
41 * handling vq_free_cnt.
42 */
43#define VQ_RING_DESC_CHAIN_END 32768
44
45/* Support for indirect buffer descriptors. */
46#define VIRTIO_RING_F_INDIRECT_DESC (1 << 28)
47
48/* Support to suppress interrupt until specific index is reached. */
49#define VIRTIO_RING_F_EVENT_IDX (1 << 29)
50
51#if defined(VIRTIO_USE_DCACHE)
52#define VRING_FLUSH(x, s) metal_cache_flush(x, s)
53#define VRING_INVALIDATE(x, s) metal_cache_invalidate(x, s)
54#else
55#define VRING_FLUSH(x, s) do { } while (0)
56#define VRING_INVALIDATE(x, s) do { } while (0)
57#endif /* VIRTIO_USE_DCACHE */
58
62 void *buf;
63
65 int len;
66};
67
71 void *cookie;
72
74 uint16_t ndescs;
75};
76
78struct virtqueue {
81
83 const char *vq_name;
84
87
89 uint16_t vq_nentries;
90
92 void (*callback)(struct virtqueue *vq);
93
95 void *priv;
96
98 void (*notify)(struct virtqueue *vq);
99
102
104 uint16_t vq_free_cnt;
105
108
113 struct metal_io_region *shm_io;
114
120
123
126
127#ifdef VQUEUE_DEBUG
129 bool vq_inuse;
130#endif
131
137};
138
142 void *vaddr;
143
145 uint32_t align;
146
148 uint16_t num_descs;
149
151 uint16_t pad;
152};
153
154typedef void (*vq_callback)(struct virtqueue *);
155typedef void (*vq_notify)(struct virtqueue *);
156
157#ifdef VQUEUE_DEBUG
158#include <metal/log.h>
159#include <metal/assert.h>
160
161#define VQASSERT(_vq, _exp, _msg) \
162 do { \
163 if (!(_exp)) { \
164 metal_log(METAL_LOG_EMERGENCY, \
165 "%s: %s - "_msg, __func__, (_vq)->vq_name); \
166 metal_assert(_exp); \
167 } \
168 } while (0)
169
170#define VQ_RING_ASSERT_VALID_IDX(_vq, _idx) \
171 VQASSERT((_vq), (_idx) < (_vq)->vq_nentries, "invalid ring index")
172
173#define VQ_RING_ASSERT_CHAIN_TERM(_vq) \
174 VQASSERT((_vq), (_vq)->vq_desc_head_idx == \
175 VQ_RING_DESC_CHAIN_END, \
176 "full ring terminated incorrectly: invalid head")
177
178#define VQ_PARAM_CHK(condition, status_var, status_err) \
179 do { \
180 if (((status_var) == 0) && (condition)) { \
181 status_var = status_err; \
182 } \
183 } while (0)
184
185#define VQUEUE_BUSY(vq) \
186 do { \
187 if (!(vq)->vq_inuse) \
188 (vq)->vq_inuse = true; \
189 else \
190 VQASSERT(vq, !(vq)->vq_inuse,\
191 "VirtQueue already in use"); \
192 } while (0)
193
194#define VQUEUE_IDLE(vq) ((vq)->vq_inuse = false)
195
196#else
197
198#define VQASSERT(_vq, _exp, _msg)
199#define VQ_RING_ASSERT_VALID_IDX(_vq, _idx)
200#define VQ_RING_ASSERT_CHAIN_TERM(_vq)
201#define VQ_PARAM_CHK(condition, status_var, status_err)
202#define VQUEUE_BUSY(vq)
203#define VQUEUE_IDLE(vq)
204
205#endif
206
224int virtqueue_create(struct virtio_device *device, unsigned short id,
225 const char *name, struct vring_alloc_info *ring,
226 void (*callback)(struct virtqueue *vq),
227 void (*notify)(struct virtqueue *vq),
228 struct virtqueue *vq);
229
230/*
231 * virtqueue_set_shmem_io
232 *
233 * set virtqueue shared memory I/O region
234 *
235 * @vq - virt queue
236 * @io - pointer to the shared memory I/O region
237 */
238static inline void virtqueue_set_shmem_io(struct virtqueue *vq,
239 struct metal_io_region *io)
240{
241 vq->shm_io = io;
242}
243
258int virtqueue_add_buffer(struct virtqueue *vq, struct virtqueue_buf *buf_list,
259 int readable, int writable, void *cookie);
260
272void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx);
273
285void *virtqueue_get_first_avail_buffer(struct virtqueue *vq, uint16_t *avail_idx,
286 uint32_t *len);
287
310void *virtqueue_get_next_avail_buffer(struct virtqueue *vq, uint16_t idx,
311 uint16_t *next_idx, uint32_t *next_len);
312
324int virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx,
325 uint32_t len);
326
334void virtqueue_disable_cb(struct virtqueue *vq);
335
345int virtqueue_enable_cb(struct virtqueue *vq);
346
354void virtqueue_kick(struct virtqueue *vq);
355
356static inline struct virtqueue *virtqueue_allocate(unsigned int num_desc_extra)
357{
358 struct virtqueue *vqs;
359 uint32_t vq_size = sizeof(struct virtqueue) +
360 num_desc_extra * sizeof(struct vq_desc_extra);
361
362 vqs = (struct virtqueue *)metal_allocate_memory(vq_size);
363 if (vqs) {
364 memset(vqs, 0x00, vq_size);
365 }
366
367 return vqs;
368}
369
377void virtqueue_free(struct virtqueue *vq);
378
386void virtqueue_dump(struct virtqueue *vq);
387
388void virtqueue_notification(struct virtqueue *vq);
389
399uint32_t virtqueue_get_desc_size(struct virtqueue *vq);
400
401uint32_t virtqueue_get_buffer_length(struct virtqueue *vq, uint16_t idx);
402void *virtqueue_get_buffer_addr(struct virtqueue *vq, uint16_t idx);
403
411static inline int virtqueue_empty(struct virtqueue *vq)
412{
413 return (vq->vq_nentries == vq->vq_free_cnt);
414}
415
423static inline int virtqueue_full(struct virtqueue *vq)
424{
425 return (vq->vq_free_cnt == 0);
426}
427
428#if defined __cplusplus
429}
430#endif
431
432#endif /* VIRTQUEUE_H_ */
Structure definition for virtio devices for use by the applications/drivers.
Definition virtio.h:176
Buffer descriptor.
Definition virtqueue.h:60
void * buf
Address of the buffer.
Definition virtqueue.h:62
int len
Size of the buffer.
Definition virtqueue.h:65
Local virtio queue to manage a virtio ring for sending or receiving.
Definition virtqueue.h:78
struct metal_io_region * shm_io
Metal I/O region of the buffers.
Definition virtqueue.h:113
struct vq_desc_extra vq_descx[0]
Used by the host side during callback.
Definition virtqueue.h:136
void(* callback)(struct virtqueue *vq)
Function to invoke, when message is available on the virtio queue.
Definition virtqueue.h:92
uint16_t vq_queue_index
Index of the virtio queue.
Definition virtqueue.h:86
void(* notify)(struct virtqueue *vq)
Function to invoke, to inform the other side about an update in the virtio queue.
Definition virtqueue.h:98
uint16_t vq_queued_cnt
Number of queued buffer in the virtio ring.
Definition virtqueue.h:107
uint16_t vq_available_idx
Last consumed descriptor in the available table, used by the consumer side.
Definition virtqueue.h:125
uint16_t vq_used_cons_idx
Last consumed descriptor in the used table, trails vq_ring.used->idx.
Definition virtqueue.h:122
uint16_t vq_desc_head_idx
Head of the free chain in the descriptor table.
Definition virtqueue.h:119
uint16_t vq_nentries
Max number of buffers in the virtio queue.
Definition virtqueue.h:89
void * priv
Private data associated to the virtio queue.
Definition virtqueue.h:95
uint16_t vq_free_cnt
Number of free descriptor in the virtio ring.
Definition virtqueue.h:104
const char * vq_name
Name of the virtio queue.
Definition virtqueue.h:83
struct virtio_device * vq_dev
Associated virtio device.
Definition virtqueue.h:80
struct vring vq_ring
Associated virtio ring.
Definition virtqueue.h:101
Vring descriptor extra information for buffer list management.
Definition virtqueue.h:69
void * cookie
Pointer to first descriptor.
Definition virtqueue.h:71
uint16_t ndescs
Number of chained descriptors.
Definition virtqueue.h:74
Virtio ring specific information.
Definition virtqueue.h:140
void * vaddr
Vring address.
Definition virtqueue.h:142
uint16_t pad
Padding.
Definition virtqueue.h:151
uint16_t num_descs
Number of descriptors in the vring.
Definition virtqueue.h:148
uint32_t align
Vring alignment.
Definition virtqueue.h:145
The virtqueue layout structure.
Definition virtio_ring.h:157
void * virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx)
Definition virtqueue.c:135
uint32_t virtqueue_get_desc_size(struct virtqueue *vq)
Definition virtqueue.c:367
static int virtqueue_empty(struct virtqueue *vq)
Test if virtqueue is empty.
Definition virtqueue.h:411
int virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx, uint32_t len)
Definition virtqueue.c:258
void(* vq_notify)(struct virtqueue *)
Definition virtqueue.h:155
void * virtqueue_get_next_avail_buffer(struct virtqueue *vq, uint16_t idx, uint16_t *next_idx, uint32_t *next_len)
Definition virtqueue.c:234
void * virtqueue_get_first_avail_buffer(struct virtqueue *vq, uint16_t *avail_idx, uint32_t *len)
Definition virtqueue.c:203
void virtqueue_dump(struct virtqueue *vq)
Definition virtqueue.c:348
void virtqueue_notification(struct virtqueue *vq)
Definition virtqueue.c:620
int virtqueue_add_buffer(struct virtqueue *vq, struct virtqueue_buf *buf_list, int readable, int writable, void *cookie)
Definition virtqueue.c:80
uint32_t virtqueue_get_buffer_length(struct virtqueue *vq, uint16_t idx)
Definition virtqueue.c:174
void virtqueue_free(struct virtqueue *vq)
Definition virtqueue.c:190
void virtqueue_kick(struct virtqueue *vq)
Definition virtqueue.c:333
static int virtqueue_full(struct virtqueue *vq)
Test if virtqueue is full.
Definition virtqueue.h:423
void(* vq_callback)(struct virtqueue *)
Definition virtqueue.h:154
static struct virtqueue * virtqueue_allocate(unsigned int num_desc_extra)
Definition virtqueue.h:356
static void virtqueue_set_shmem_io(struct virtqueue *vq, struct metal_io_region *io)
Definition virtqueue.h:238
int virtqueue_create(struct virtio_device *device, unsigned short id, const char *name, struct vring_alloc_info *ring, void(*callback)(struct virtqueue *vq), void(*notify)(struct virtqueue *vq), struct virtqueue *vq)
Definition virtqueue.c:45
void virtqueue_disable_cb(struct virtqueue *vq)
Definition virtqueue.c:300
void * virtqueue_get_buffer_addr(struct virtqueue *vq, uint16_t idx)
Definition virtqueue.c:182
int virtqueue_enable_cb(struct virtqueue *vq)
Definition virtqueue.c:295