VIRTIO VRING工作机制分 析

本文详细分析了VIRTIO VRING的工作流程,包括初始化、Guest写入、QEMU处理和Guest中断响应。重点讨论了VRING的结构布局、Guest如何添加请求、QEMU如何处理请求以及中断通知机制。通过对各个环节的解析,揭示了虚拟化环境中高效I/O通信的秘密。
摘要由CSDN通过智能技术生成

1.VRing的初始化

QEMU下的VRing

typedef struct VRing

{//vring中最多有多少各request

unsigned int num;

unsigned int num_default;

//数据对齐比例尺

unsigned int align;

//VRingDesc结构存储对应的gpa

hwaddr desc;

hwaddr avail;

hwaddr used;

} VRing;

VirtQueue在QEMU端的初始化,即virtio_add_queue, virtio最多有1024个虚拟队列,且每个队列最多容纳1024个request单位

if (i == VIRTIO_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE)

abort();

vdev->vq[i].vring.num = queue_size;

vdev->vq[i].vring.num_default = queue_size;

vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN;

vdev->vq[i].handle_output = handle_output;

vdev->vq[i].handle_aio_output = NULL;

QEMU初始化了vring.num和handle_output.

回到guest中的virtio驱动, vm_setup_vq负责建立和qemu对应的virtqueue,

info->num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX);

上条代码帮助guest获取了vring.num, vring的内存从guest memory中申请:

info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);

vring_new_virtqueue初始化了guest的结构体vring_virtqueue

struct vring_virtqueue {

struct virtqueue vq;

/* Actual memory layout for this queue */
struct vring vring;

/* Can we use weak barriers? */
bool weak_barriers;

/* Other side has made a mess, don't try any more. */
bool broken;

/* Host supports indirect buffers */
bool indirect;

/* Host publishes avail event idx */
bool event;

/* Head of free buffer list. */
unsigned int free_head;

/* Number we've added since last sync. */
unsigned int num_added;

/* Last used index we've seen. */
u16 last_used_idx;

/* Last written value to avail->flags */
u16 avail_flags_shadow;

/* Last written value to avail->idx in guest byte order */
u16 avail_idx_shadow;

/* How to notify other side. FIXME: commonalize hcalls! */
bool (*notify)(struct virtqueue *vq);

/* Tokens for callbacks. 比如virtblk_req */
void *data[];

};

size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN));

//guest分配内存给vring

info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);

其中vring_size可以看出vring的组成形式

static inline unsigned vring_size(unsigned int num, unsigned long align)

{return ((sizeof(struct vring_desc) * num + sizeof(__virtio16) * (3 + num) + ali
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值