赞
踩
1 基本概念
virtio共享内存使用的是guest GPA,由guest virtio front-end驱动初始化队列的时候分配,在back-end驱动中,QVM或者QEMU将GPA转换到HVA或者HPA地址再读写数据。
virtio front-end通知back-end方式:访问doorbell寄存器触发EPT misconfig(Extended Page Table)。x86 CPU EPT每级页表的每个entry中存放的一般都是下一级页表物理基地址的bit (N-1):12。
ARM-v8 TTBR: Tranlation Table Base Register
x86 CR3: Control Register
2 Protocol
2.1 virtio 0.95
Legacy模式只使用了PCI的BAR0
Figure 2-1 BAR0指向的寄存器
2.2 virtio 1.0
QNX hypervisor使用了virtio 1.0协议。
capability ID参考:include/uapi/linux/pci_regs.h
struct virtio_pci_cap {
__u8 cap_vndr;
__u8 cap_next;
__u8 cap_len;
__u8 cfg_type;
__u8 bar;
__u8 padding[3];
__le32 offset;
__le32 length;
};
根据上述结构体可知,每个能力在PCI配置空间中占用16个字节,并且capability ID(cap_vndr)= 0x09,virtio 1.0中五个cfg_type如下所示。
#define VIRTIO_PCI_CAP_COMMON_CFG 1 /* 占用PCI Bar内存0x38个字节 */
#define VIRTIO_PCI_CAP_NOTIFY_CFG 2 /* 占用PCI Bar内存8个字节 */
#define VIRTIO_PCI_CAP_ISR_CFG 3 /* 占用PCI Bar内存4个字节 */
#define VIRTIO_PCI_CAP_DEVICE_CFG 4 /* 占用PCI Bar内存0x0c个字节 */
#define VIRTIO_PCI_CAP_PCI_CFG 5 /* 占用PCI Bar内存0个字节 */
5个cfg_type仅占用一个PCI Bar,只是地址偏移offset和长度不一样。获取每个能力的offset和长度(都是小端格式),用户空间可以使用libpci库,为简单起见,示例代码中仅读取了4个字节,实际需要读取16个字节。
参数ptr是配置空间偏移0x34地址指向的一个字节。
static bool pci_is_pcie(struct pci_dev *pdev, unsigned char ptr)
{
unsigned int value;
unsigned int next_ptr;
unsigned int cap_id;
next_ptr = ptr;
if (0 == ptr) {
return false;
}
do {
value = pci_read_long(pdev, next_ptr);
next_ptr = (value >> 8) & 0xff;
cap_id = value & 0xff;
/* PCI Express Capability Structure */
if (cap_id == 0x10) {
return true;
}
} while (next_ptr);
return false;
}
2.3 virtio 1.1
- virtio 1.1,packed模式,将virtio 1.0中的3个ring合成一个
3 Abbreviations
fio:flexiable io
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。