该文是通过对virtio-1.2官方文档翻译生成的,文档的下载地址为: http://docs.oasis-open.org/virtio/virtio/v1.2/

Virtio Over MMIO

  • 4.2 Virtio Over MMIO
    • 4.2.1 MMIO Device Discovery
    • 4.2.2 MMIO Device Register Layout
      • 4.2.2.1 Device Requirements: MMIO Device Register Layout
      • 4.2.2.2 Driver Requirements: MMIO Device Register Layout
    • 4.2.3 MMIO-specific Initialization And Device Operation
      • 4.2.3.1 Device Initialization
        • 4.2.3.1.1 Driver Requirements: Device Initialization
      • 4.2.3.2 Virtqueue Configuration
      • 4.2.3.3 Available Buffer Notifications
      • 4.2.3.4 Notifications From The Device
      • 4.2.3.4.1 Driver Requirements: Notifications From The Device
    • 4.2.4 Legacy interface

4.2 Virtio Over MMIO

Virtual environments without PCI support (a common situation in embedded devices models) might use simple memory mapped device (“virtio-mmio”) instead of the PCI device.
不支持PCI的虚拟环境(嵌入式设备模型中的常见情况)可能使用简单的内存映射设备(“virtio-mmio”)取代PCI设备。
The memory mapped virtio device behaviour is based on the PCI device specification. Therefore most operations including device initialization, queues configuration and buffer transfers are nearly identical. Existing differences are described in the following sections.
内存映射的virtio设备行为是基于PCI设备规范的。因此,包括设备初始化、队列配置和缓冲区传输在内的大多数操作几乎都是相同的。现有的差异将在下面的部分中进行描述。

4.2.1 MMIO Device Discovery

Unlike PCI, MMIO provides no generic device discovery mechanism. For each device, the guest OS will need to know the location of the registers and interrupt(s) used. The suggested binding for systems using flattened device trees is shown in this example:
与PCI不同,MMIO不提供通用的设备发现机制。对于每个设备,guest操作系统将需要知道所使用的寄存器和中断的位置。使用扁平设备树的系统的建议绑定如下:

// EXAMPLE: virtio_block device taking 512 bytes at 0x1e000, interrupt 42.
virtio_block@1e000 {compatible = "virtio,mmio";reg = <0x1e000 0x200>;interrupts = <42>;
}

4.2.2 MMIO Device Register Layout

MMIO virtio devices provide a set of memory mapped control registers followed by a device-specific configuration space, described in the table 4.1.
MMIO virtio设备提供了一组内存映射的控制寄存器,然后是一组设备特定的配置空间,详见表4.1。
All register values are organized as Little Endian.
所有的寄存器值都被组织为小端。
MagicValue 0x000: Magic value 0x74726976 (a Little Endian equivalent of the “virt” string)
Version 0x004:Device version number 0x2
Note: Legacy devices (see 4.2.4 Legacy interface) used 0x1.
遗留设备(见4.2.4遗留接口)使用了0x1。
DeviceID 0x008:Virtio Subsystem Device ID
See 5 Device Types for possible values. Value zero (0x0) is used to define a system memory map with placeholder devices at static, well known addresses, assigning functions to them depending on user’s needs
有关可能的值,请参见5个设备类型。值0(0x0)用于定义一个系统内存映射,其中具有静态占位符设备的知名地址,并根据用户的需要为它们分配函数。
VendorID 0x00c:Virtio Subsystem Vendor ID
DeviceFeatures 0x010:Flags representing features the device supports
Reading from this register returns 32 consecutive flag bits, the least significant bit depending on the last value written to DeviceFeaturesSel. Access to this register returns bits DeviceFeaturesSel * 32 to (DeviceFeaturesSel * 32)+31, eg. feature bits 0 to 31 if DeviceFeaturesSel is set to 0 and features
bits 32 to 63 if DeviceFeaturesSel is set to 1. Also see 2.2 Feature Bits.
DeviceFeaturesSel 0x014:Device (host) features word selection.
Writing to this register selects a set of 32 device feature bits accessible by reading from DeviceFeatures.
DriverFeatures 0x020:Flags representing device features understood and activated by the
driver
Writing to this register sets 32 consecutive flag bits, the least significant bit depending on the last value written to DriverFeaturesSel. Access to this register sets bits DriverFeaturesSel ∗ 32 to (DriverFeaturesSel ∗ 32) + 31, eg. feature bits 0 to 31 if DriverFeaturesSel is set to 0 and features bits 32 to 63 if DriverFeaturesSel is set to 1. Also see 2.2 Feature Bits.
DriverFeaturesSel 0x024:Activated (guest) features word selection
Writing to this register selects a set of 32 activated feature bits accessible by writing to DriverFeatures.
QueueSel 0x030:Virtual queue index
Writing to this register selects the virtual queue that the following operations on QueueNumMax, QueueNum, QueueReady, QueueDescLow, QueueDescHigh, QueueDriverlLow, QueueDriverHigh, QueueDeviceLow, QueueDeviceHigh and QueueReset apply to. The index number of the first queue is zero (0x0).
QueueNumMax 0x034:Maximum virtual queue size
Reading from the register returns the maximum size (number of elements) of the queue the device is ready to process or zero (0x0) if the queue is not available. This applies to the queue selected by writing to QueueSel.
QueueNum 0x038:Virtual queue size
Queue size is the number of elements in the queue. Writing to this register notifies the device what size of the queue the driver will use. This applies to the queue selected by writing to QueueSel.
QueueReady 0x044:Virtual queue ready bit
Writing one (0x1) to this register notifies the device that it can execute re- quests from this virtual queue. Reading from this register returns the last value written to it. Both read and write accesses apply to the queue selected by writing to QueueSel.
QueueNotify 0x050:Queue notifier
Writing a value to this register notifies the device that there are new buffers to process in a queue.
When VIRTIO_F_NOTIFICATION_DATA has not been negotiated, the value written is the queue index.
When VIRTIO_F_NOTIFICATION_DATA has been negotiated, the Notifi- cation data value has the following format:

le32 {vqn : 16;next_off : 15;next_wrap : 1;
};

See 2.9 Driver Notifications for the definition of the components.
InterruptStatus 0x60:Interrupt status
Reading from this register returns a bit mask of events that caused the de- vice interrupt to be asserted. The following events are possible:
Used Buffer Notification - bit 0 - the interrupt was asserted because the device has used a buffer in at least one of the active virtual queues.
Configuration Change Notification - bit 1 - the interrupt was asserted be- cause the configuration of the device has changed.
InterruptACK 0x064:Interrupt acknowledge
Writing a value with bits set as defined in InterruptStatus to this register notifies the device that events causing the interrupt have been handled.
Status 0x070:Device status
Reading from this register returns the current device status flags. Writing non-zero values to this register sets the status flags, indicating the driver progress. Writing zero (0x0) to this register triggers a device reset. See also p. 4.2.3.1 Device Initialization.
QueueDescLow 0x080
QueueDescHigh 0x084:Virtual queue’s Descriptor Area 64 bit long physical address
Writing to these two registers (lower 32 bits of the address to QueueDescLow, higher 32 bits to QueueDescHigh) notifies the device about location of the Descriptor Area of the queue selected by writing to QueueSel register.
QueueDriverLow 0x090
QueueDriverHigh 0x094:Virtual queue’s Driver Area 64 bit long physical address
Writing to these two registers (lower 32 bits of the address to QueueDriver- Low, higher 32 bits to QueueDriverHigh) notifies the device about location of the Driver Area of the queue selected by writing to QueueSel.
QueueDeviceLow 0x0a0
QueueDeviceHigh 0x0a4:Virtual queue’s Device Area 64 bit long physical address
Writing to these two registers (lower 32 bits of the address to QueueDe- viceLow, higher 32 bits to QueueDeviceHigh) notifies the device about lo- cation of the Device Area of the queue selected by writing to QueueSel.
SHMSel 0x0ac:Shared memory id
Writing to this register selects the shared memory region 2.10 following op- erations on SHMLenLow, SHMLenHigh, SHMBaseLow and SHMBaseHigh apply to.
SHMLenLow 0x0b0
SHMLenHigh 0x0b4:Shared memory region 64 bit long length
These registers return the length of the shared memory region in bytes, as defined by the device for the region selected by the SHMSel register. The lower 32 bits of the length are read from SHMLenLow and the higher 32 bits from SHMLenHigh. Reading from a non-existent region (i.e. where the ID written to SHMSel is unused) results in a length of - 1.
SHMBaseLow 0x0b8
SHMBaseHigh 0x0bc:Shared memory region 64 bit long physical address
The driver reads these registers to discover the base address of the region in physical address space. This address is chosen by the device (or other part of the VMM). The lower 32 bits of the address are read from SHMBaseLow with the higher 32 bits from SHMBaseHigh. Reading from a non-existent region (i.e. where the ID written to SHMSel is unused) results in a base
address of 0xffffffffffffffff.
QueueReset 0x0c0:Virtual queue reset bit
If VIRTIO_F_RING_RESET has been negotiated, writing one (0x1) to this register selectively resets the queue. Both read and write accesses apply to the queue selected by writing to QueueSel.
ConfigGeneration 0x0fc:Configuration atomicity value
Reading from this register returns a value describing a version of the device- specific configuration space (see Config). The driver can then access the configuration space and, when finished, read ConfigGeneration again. If no part of the configuration space has changed between these two ConfigGen- eration reads, the returned values are identical. If the values are different, the configuration space accesses were not atomic and the driver has to perform the operations again. See also 2.5.
Config 0x100:Configuration space
Device-specific configuration space starts at the offset 0x100 and is ac- cessed with byte alignment. Its meaning and size depend on the device and the driver.

4.2.2.1 Device Requirements: MMIO Device Register Layout

The device MUST return 0x74726976 in MagicValue.
The device MUST return value 0x2 in Version.
The device MUST present each event by setting the corresponding bit in InterruptStatus from the moment it takes place, until the driver acknowledges the interrupt by writing a corresponding bit mask to the Inter- ruptACK register. Bits which do not represent events which took place MUST be zero.
Upon reset, the device MUST clear all bits in InterruptStatus and ready bits in the QueueReady register for all queues in the device.
The device MUST change value returned in ConfigGeneration if there is any risk of a driver seeing an inconsistent configuration state.
The device MUST NOT access virtual queue contents when QueueReady is zero (0x0). If VIRTIO_F_RING_RESET has been negotiated, the device MUST present a 0 in QueueReset on reset.
If VIRTIO_F_RING_RESET has been negotiated, The device MUST present a 0 in QueueReset after the virtqueue is enabled with QueueReady.
The device MUST reset the queue when 1 is written to QueueReset. The device MUST continue to present 1 in QueueReset as long as the queue reset is ongoing. The device MUST present 0 in both QueueReset and QueueReady when queue reset has completed. (see 2.6.1).

4.2.2.2 Driver Requirements: MMIO Device Register Layout

The driver MUST NOT access memory locations not described in the table 4.1 (or, in case of the configuration space, described in the device specification), MUST NOT write to the read-only registers (direction R) and MUST NOT read from the write-only registers (direction W).
The driver MUST only use 32 bit wide and aligned reads and writes to access the control registers described in table 4.1. For the device-specific configuration space, the driver MUST use 8 bit wide accesses for 8 bit
wide fields, 16 bit wide and aligned accesses for 16 bit wide fields and 32 bit wide and aligned accesses for 32 and 64 bit wide fields.
The driver MUST ignore a device with MagicValue which is not 0x74726976, although it MAY report an error. The driver MUST ignore a device with Version which is not 0x2, although it MAY report an error. The driver MUST ignore a device with DeviceID 0x0, but MUST NOT report any error.
Before reading from DeviceFeatures, the driver MUST write a value to DeviceFeaturesSel.
Before writing to the DriverFeatures register, the driver MUST write a value to the DriverFeaturesSel register.
The driver MUST write a value to QueueNum which is less than or equal to the value presented by the device in QueueNumMax.
When QueueReady is not zero, the driver MUST NOT access QueueNum, QueueDescLow, QueueDescHigh, QueueDriverLow, QueueDriverHigh, QueueDeviceLow, QueueDeviceHigh.
To stop using the queue the driver MUST write zero (0x0) to this QueueReady and MUST read the value back to ensure synchronization.
The driver MUST ignore undefined bits in InterruptStatus.
The driver MUST write a value with a bit mask describing events it handled into InterruptACK when it finishes handling an interrupt and MUST NOT set any of the undefined bits in the value.
If VIRTIO_F_RING_RESET has been negotiated, after the driver writes 1 to QueueReset to reset the queue, the driver MUST NOT consider queue reset to be complete until it reads back 0 in QueueReset. The driver MAY re-enable the queue by writing 1 to QueueReady after ensuring that other virtqueue fields have been set up correctly. The driver MAY set driver-writeable queue configuration values to different values than those that were used before the queue reset. (see 2.6.1).

4.2.3 MMIO-specific Initialization And Device Operation

4.2.3.1 Device Initialization

4.2.3.1.1 Driver Requirements: Device Initialization

The driver MUST start the device initialization by reading and checking values from MagicValue and Version. If both values are valid, it MUST read DeviceID and if its value is zero (0x0) MUST abort initialization and MUST NOT access any other register.
Drivers not expecting shared memory MUST NOT use the shared memory registers.
Further initialization MUST follow the procedure described in 3.1 Device Initialization.

4.2.3.2 Virtqueue Configuration

The driver will typically initialize the virtual queue in the following way:

  1. Select the queue writing its index (first queue is 0) to QueueSel.
  2. Check if the queue is not already in use: read QueueReady, and expect a returned value of zero (0x0).
  3. Read maximum queue size (number of elements) from QueueNumMax. If the returned value is zero (0x0) the queue is not available.
  4. Allocate and zero the queue memory, making sure the memory is physically contiguous.
  5. Notify the device about the queue size by writing the size to QueueNum.
  6. Write physical addresses of the queue’s Descriptor Area, Driver Area and Device Area to (respectively) the QueueDescLow/QueueDescHigh, QueueDriverLow/QueueDriverHigh and QueueDeviceLow/QueueDeviceHigh register pairs.
  7. Write 0x1 to QueueReady.

4.2.3.3 Available Buffer Notifications

When VIRTIO_F_NOTIFICATION_DATA has not been negotiated, the driver sends an available buffer no- tification to the device by writing the 16-bit virtqueue index of the queue to be notified to QueueNotify.
When VIRTIO_F_NOTIFICATION_DATA has been negotiated, the driver sends an available buffer notifica- tion to the device by writing the following 32-bit value to QueueNotify:

le32 {vqn : 16;next_off : 15;next_wrap : 1;
};

See 2.9 Driver Notifications for the definition of the components.

4.2.3.4 Notifications From The Device

The memory mapped virtio device is using a single, dedicated interrupt signal, which is asserted when at least one of the bits described in the description of InterruptStatus is set. This is how the device sends a used buffer notification or a configuration change notification to the device.

4.2.3.4.1 Driver Requirements: Notifications From The Device

After receiving an interrupt, the driver MUST read InterruptStatus to check what caused the interrupt (see the register description). The used buffer notification bit being set SHOULD be interpreted as a used buffer notification for each active virtqueue. After the interrupt is handled, the driver MUST acknowledge it by writing a bit mask corresponding to the handled events to the InterruptACK register.

4.2.4 Legacy interface

The legacy MMIO transport used page-based addressing, resulting in a slightly different control register layout, the device initialization and the virtual queue configuration procedure.
Table 4.2 presents control registers layout, omitting descriptions of registers which did not change their function nor behaviour:


The virtual queue page size is defined by writing to GuestPageSize, as written by the guest. The driver does this before the virtual queues are configured.
The virtual queue layout follows p. 2.7.2 Legacy Interfaces: A Note on Virtqueue Layout, with the alignment defined in QueueAlign.
The virtual queue is configured as follows:

  1. Select the queue writing its index (first queue is 0) to QueueSel.
  2. Check if the queue is not already in use: read QueuePFN, expecting a returned value of zero (0x0).
  3. Read maximum queue size (number of elements) from QueueNumMax. If the returned value is zero (0x0) the queue is not available.
  4. Allocate and zero the queue pages in contiguous virtual memory, aligning the Used Ring to an opti- mal boundary (usually page size). The driver should choose a queue size smaller than or equal to QueueNumMax.
  5. Notify the device about the queue size by writing the size to QueueNum.
  6. Notify the device about the used alignment by writing its value in bytes to QueueAlign.
  7. Write the physical number of the first page of the queue to the QueuePFN register.
    Notification mechanisms did not change.

Virtio Over MMIO相关推荐

  1. VIRTIO 前后端驱动中 GPA,HVA 转换原理

    先说几个英文缩写: GVA - Guest Virtual Address,虚拟机的虚拟地址 GPA - Guest Physical Address,虚拟机的物理地址 HVA - Host Virt ...

  2. KVM中virtio之vring(八)

    1 virtio原理 拿网络驱动部分做案例,网络驱动virtio-net有两个队列:接收队列和发送队列:每个队列都对应一个virtqueue,两个队列之间是互不影响的. 前后端利用virtqueue的 ...

  3. KVM中virtio、vhost 和vhost-user比较(十一)

    virtio 在虚拟机中,可以通过qemu模拟e1000网卡,这样的经典网卡一般各种客户操作系统都会提供inbox驱动,所以从兼容性上来看,使用类似e1000的模拟网卡是非常一个不错的选择. 但是,e ...

  4. virtio、vhost和vhost-user比较

    1. virtio:针对Linux的I/O的虚拟化框架 在虚机中,可以通过qemu模拟e1000网卡,这样的经典网卡一般各种客户操作系统都会提供inbox驱动,所以从兼容性上来看,使用类似e1000的 ...

  5. 《深入浅出DPDK》读书笔记(十二):DPDK虚拟化技术篇(半虚拟化Virtio)

    Table of Contents 半虚拟化Virtio 132.Virtio使用场景 133.Virtio规范和原理 11.2.1 设备的配置 1. 设备的初始化 2. 设备的发现 3. 传统模式v ...

  6. fuchsia中virtio 后端实现

    ================================================涉及的其他类 class PciDevice PCI设备基类,存储pci设备状态,提供ReadBar.W ...

  7. IO虚拟化 - virtio介绍及代码分析【转】

    1. 概述 Virtio是linux平台下一种IO半虚拟化框架,virtio 由 Rusty Russell 开发,他当时的目的是支持自己的虚拟化解决方案 lguest.而在KVM中也广泛使用了vir ...

  8. 基于qemu-riscv从0开始构建嵌入式linux系统ch10. qemu之virtio与fw_cfg

    基于qemu-riscv从0开始构建嵌入式linux系统ch10. qemu之virtio与fw_cfg 上一节我们已经基本完成了uboot的移植,下一步自然就是移植linux kernel.在真实的 ...

  9. virtio frontend and backend

    1,QEMU如何模拟virtio设备 一个virtio设备被QEMU虚拟出来呈现给guest OS时,guest OS中的virtio driver是为前端,而QEMU中的virtio device是 ...

最新文章

  1. 桶排序 Bin Sort
  2. 理解 Python 中的 *args 和 **kwargs
  3. ustc小道消息20211225
  4. 百度为什么发现不了旗下网站的恶意代码?
  5. 1014. Best Sightseeing Pair
  6. win10无法运行C语言文件,主编告诉你win10打不开pdf文件的详尽处理办法
  7. 一台手机苹果含泪赚4000?iPhone 12硬件成本曝光
  8. [转载] NumPy 基本操作(ndarray通用函数 / 常用函数)
  9. solr面试题_查看您的Solr缓存大小:Eclipse Memory Analyzer
  10. 黑客帝国产业链调查:熊猫烧香作者一年赚千万
  11. 那些年你错过的SOA
  12. 【B站】陈睿:令人刮目相看的年轻一代
  13. Vue----组件注册
  14. SUSE 助力某头部基金公司 PaaS 平台建设
  15. windows画图板 ESL转RGB 实现区间渐变色
  16. 安装时间大于30秒_30个住宅室内消防设置检验要点!硬核干货!
  17. MAC电脑配置maven
  18. MySQL数据库服务的简单开启和关闭
  19. Angular 服务端渲染(SSR) 学习笔记
  20. ijk的那些事(一)编译项目

热门文章

  1. 实现一个有衰减的 Planar Shadow
  2. 安装pycharm教程
  3. BinWalk安装和命令参数详解
  4. centos添加明细路由的方法
  5. PS:晚上拍的照片,把它调成像白天照的效果
  6. dw html设置字体颜色,字体颜色怎么设置-dreamweaver编辑字体大小、颜色样式方法...
  7. 南京大学在职研究生计算机,报考南京大学在职研究生究竟能得到什么?值不值得?...
  8. 微信小程序如何发红包?
  9. Windows 10 Mobile Build 10586.71截图泄露
  10. 直接作用于治疗环节的可穿戴设备都长什么样