dpdk/drivers/crypto/virtio/virtio_ring.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2018 HUAWEI TECHNOLOGIES CO., LTD.
   3 */
   4
   5#ifndef _VIRTIO_RING_H_
   6#define _VIRTIO_RING_H_
   7
   8#include <stdint.h>
   9
  10#include <rte_common.h>
  11
  12/* This marks a buffer as continuing via the next field. */
  13#define VRING_DESC_F_NEXT       1
  14/* This marks a buffer as write-only (otherwise read-only). */
  15#define VRING_DESC_F_WRITE      2
  16/* This means the buffer contains a list of buffer descriptors. */
  17#define VRING_DESC_F_INDIRECT   4
  18
  19/* The Host uses this in used->flags to advise the Guest: don't kick me
  20 * when you add a buffer.  It's unreliable, so it's simply an
  21 * optimization.  Guest will still kick if it's out of buffers.
  22 */
  23#define VRING_USED_F_NO_NOTIFY  1
  24/* The Guest uses this in avail->flags to advise the Host: don't
  25 * interrupt me when you consume a buffer.  It's unreliable, so it's
  26 * simply an optimization.
  27 */
  28#define VRING_AVAIL_F_NO_INTERRUPT  1
  29
  30/* VirtIO ring descriptors: 16 bytes.
  31 * These can chain together via "next".
  32 */
  33struct vring_desc {
  34        uint64_t addr;  /*  Address (guest-physical). */
  35        uint32_t len;   /* Length. */
  36        uint16_t flags; /* The flags as indicated above. */
  37        uint16_t next;  /* We chain unused descriptors via this. */
  38};
  39
  40struct vring_avail {
  41        uint16_t flags;
  42        uint16_t idx;
  43        uint16_t ring[0];
  44};
  45
  46/* id is a 16bit index. uint32_t is used here for ids for padding reasons. */
  47struct vring_used_elem {
  48        /* Index of start of used descriptor chain. */
  49        uint32_t id;
  50        /* Total length of the descriptor chain which was written to. */
  51        uint32_t len;
  52};
  53
  54struct vring_used {
  55        uint16_t flags;
  56        volatile uint16_t idx;
  57        struct vring_used_elem ring[0];
  58};
  59
  60struct vring {
  61        unsigned int num;
  62        struct vring_desc  *desc;
  63        struct vring_avail *avail;
  64        struct vring_used  *used;
  65};
  66
  67/* The standard layout for the ring is a continuous chunk of memory which
  68 * looks like this.  We assume num is a power of 2.
  69 *
  70 * struct vring {
  71 *      // The actual descriptors (16 bytes each)
  72 *      struct vring_desc desc[num];
  73 *
  74 *      // A ring of available descriptor heads with free-running index.
  75 *      __u16 avail_flags;
  76 *      __u16 avail_idx;
  77 *      __u16 available[num];
  78 *      __u16 used_event_idx;
  79 *
  80 *      // Padding to the next align boundary.
  81 *      char pad[];
  82 *
  83 *      // A ring of used descriptor heads with free-running index.
  84 *      __u16 used_flags;
  85 *      __u16 used_idx;
  86 *      struct vring_used_elem used[num];
  87 *      __u16 avail_event_idx;
  88 * };
  89 *
  90 * NOTE: for VirtIO PCI, align is 4096.
  91 */
  92
  93/*
  94 * We publish the used event index at the end of the available ring, and vice
  95 * versa. They are at the end for backwards compatibility.
  96 */
  97#define vring_used_event(vr)  ((vr)->avail->ring[(vr)->num])
  98#define vring_avail_event(vr) (*(uint16_t *)&(vr)->used->ring[(vr)->num])
  99
 100static inline size_t
 101vring_size(unsigned int num, unsigned long align)
 102{
 103        size_t size;
 104
 105        size = num * sizeof(struct vring_desc);
 106        size += sizeof(struct vring_avail) + (num * sizeof(uint16_t));
 107        size = RTE_ALIGN_CEIL(size, align);
 108        size += sizeof(struct vring_used) +
 109                (num * sizeof(struct vring_used_elem));
 110        return size;
 111}
 112
 113static inline void
 114vring_init(struct vring *vr, unsigned int num, uint8_t *p,
 115        unsigned long align)
 116{
 117        vr->num = num;
 118        vr->desc = (struct vring_desc *) p;
 119        vr->avail = (struct vring_avail *) (p +
 120                num * sizeof(struct vring_desc));
 121        vr->used = (void *)
 122                RTE_ALIGN_CEIL((uintptr_t)(&vr->avail->ring[num]), align);
 123}
 124
 125/*
 126 * The following is used with VIRTIO_RING_F_EVENT_IDX.
 127 * Assuming a given event_idx value from the other size, if we have
 128 * just incremented index from old to new_idx, should we trigger an
 129 * event?
 130 */
 131static inline int
 132vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old)
 133{
 134        return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);
 135}
 136
 137#endif /* _VIRTIO_RING_H_ */
 138