virtio desc

/* Virtio ring descriptors: 16 bytes.  These can chain together via "next". */
struct vring_desc {
    /* Address (guest-physical). */
    __virtio64 addr;
    /* Length. */
    __virtio32 len;
    /* The flags as indicated above. */
    __virtio16 flags;
    /* We chain unused descriptors via this, too */
    __virtio16 next;
};

struct vring_avail {
    __virtio16 flags;
    __virtio16 idx;
    __virtio16 ring[];
};

/* uint32_t is used here for ids for padding reasons. */
struct vring_used_elem {
    /* Index of start of used descriptor chain. */
    __virtio32 id;
    /* Total length of the descriptor chain which was used (written to) */
    __virtio32 len;
};

typedef struct vring_used_elem __attribute__((aligned(VRING_USED_ALIGN_SIZE)))
    vring_used_elem_t;

struct vring_used {
    __virtio16 flags;
    __virtio16 idx;
    vring_used_elem_t ring[];
};

/*
 * The ring element addresses are passed between components with different
 * alignments assumptions. Thus, we might need to decrease the compiler-selected
 * alignment, and so must use a typedef to make sure the aligned attribute
 * actually takes hold:
 *
 * https://gcc.gnu.org/onlinedocs//gcc/Common-Type-Attributes.html#Common-Type-Attributes
 *
 * When used on a struct, or struct member, the aligned attribute can only
 * increase the alignment; in order to decrease it, the packed attribute must
 * be specified as well. When used as part of a typedef, the aligned attribute
 * can both increase and decrease alignment, and specifying the packed
 * attribute generates a warning.
 */
typedef struct vring_desc __attribute__((aligned(VRING_DESC_ALIGN_SIZE)))
    vring_desc_t;
typedef struct vring_avail __attribute__((aligned(VRING_AVAIL_ALIGN_SIZE)))
    vring_avail_t;
typedef struct vring_used __attribute__((aligned(VRING_USED_ALIGN_SIZE)))
    vring_used_t;

struct vring {
    unsigned int num;

    vring_desc_t *desc;

    vring_avail_t *avail;

    vring_used_t *used;
};
vhost_net_start
  ├─virtio_pci_set_guest_notifiers
  |   └─virtio_pci_set_guest_notifier
  ├─vhost_net_start_one
  |   ├─vhost_net_start_one
  |   |   └─vhost_dev_enable_notifiers
  |   |       └─virtio_bus_set_host_notifier
  |   |           ├─event_notifier_init
  |   |           └─virtio_pci_ioeventfd_assign
  |   └─vhost_dev_start
  |        └─vhost_virtqueue_start
  |             ├─vhost_kernel_set_vring_num
  |             ├─vhost_kernel_set_vring_base把内核vring的三个地址设置和用户态一样
  |             ├─vhost_kernel_set_vring_endian
  |             ├─vhost_virtqueue_set_addr
  |             |   └─vhost_kernel_set_vring_addr
  |             ├─vhost_kernel_set_vring_kick
  |             └─vhost_kernel_set_vring_call
  └─vhost_set_vring_enable
static inline void vring_init(struct vring *vr, unsigned int num, void *p,
                  unsigned long align)
{
    vr->num = num;
    vr->desc = p;
    vr->avail = (struct vring_avail *)((char *)p + num * sizeof(struct vring_desc));
    vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] + sizeof(__virtio16)
        + align-1) & ~(align - 1));
}
原文地址:https://www.cnblogs.com/dream397/p/14368059.html