QEMU Devices
megasas 向 HBA 添加两个 SCSI LUN 来模拟megasas -device megasas,id=scsi0 \ -device scsi-hd,drive=drive0,bus=scsi0.0,channel=0,scsi-id=0,lun=0 \ -drive file=disk1.qcow2,if=none,id=drive0 \ -device scsi-hd,drive=drive1,bus=scsi0.0,channel=0,scsi-id=1,lun=0 \ -drive file=disk2.qcow2,if=none,id=drive1 SCSI 总线拓扑,有两个 SCSI 适配器(每个适配器都有一个 SCSI LUN)通过同一 SCSI 通道连接到 HBA。 从虚拟机提取的系统日志输出验证内核扫描的 SCSI 总线拓扑是否与 QEMU 的配置匹配。唯一的例外是 QEMU 指定通道 ID 为 1,而内核分配的通道 ID 为 2。磁盘 disk1.qcow2 和 disk2.qcow2 分别映射到 '2:2:0:0' 和 '2:2:1:0'。 [ 2.439170] scsi host2: Avago SAS based MegaRAID driver [ 2.445926] scsi 2:2:0:0: Direct-Access QEMU QEMU HARDDISK 2.5+ PQ: 0 ANSI: 5 [ 2.446098] scsi 2:2:1:0: Direct-Access QEMU QEMU HARDDISK 2.5+ PQ: 0 ANSI: 5 [ 2.463466] sd 2:2:0:0: Attached scsi generic sg1 type 0 [ 2.467891] sd 2:2:1:0: Attached scsi generic sg2 type 0 [ 2.478002] sd 2:2:0:0: [sdb] Attached SCSI disk [ 2.485895] sd 2:2:1:0: [sdc] Attached SCSI disk lsi53c895a 向 HBA 添加两个 SCSI LUN 来模拟 lsi53c895a。 -device lsi53c895a,id=scsi0 \ -device scsi-hd,drive=drive0,bus=scsi0.0,channel=0,scsi-id=0,lun=0 \ -drive file=disk1.qcow2,if=none,id=drive0 \ -device scsi-hd,drive=drive1,bus=scsi0.0,channel=0,scsi-id=1,lun=0 \ -drive file=disk2.qcow2,if=none,id=drive1 SCSI 总线拓扑,有两个 SCSI 适配器(每个适配器都有一个 SCSI LUN)通过同一 SCSI 通道连接到 HBA。 与 megasas 一样,虚拟机的系统日志输出显示内核扫描的 SCSI 总线拓扑与使用 QEMU 配置的拓扑相匹配。磁盘 disk1.qcow2 和 disk2.qcow2 分别映射到 '2:0:0:0' 和 '2:0:1:0'。 [ 2.443221] scsi host2: sym-2.2.3 [ 5.534188] scsi 2:0:0:0: Direct-Access QEMU QEMU HARDDISK 2.5+ PQ: 0 ANSI: 5 [ 5.544931] scsi 2:0:1:0: Direct-Access QEMU QEMU HARDDISK 2.5+ PQ: 0 ANSI: 5 [ 5.558896] sd 2:0:0:0: Attached scsi generic sg1 type 0 [ 5.559889] sd 2:0:1:0: Attached scsi generic sg2 type 0 [ 5.574487] sd 2:0:0:0: [sdb] Attached SCSI disk [ 5.579512] sd 2:0:1:0: [sdc] Attached SCSI disk virtio-scsi 本节演示了半虚拟化虚拟 virtio-scsi 的用法。virtio-scsi 设备提供了非常好的“多队列”支持。因此,它可用于研究或调试SCSI和块层的“多队列”功能。下面的示例创建一个具有两个 LUN(它们都属于同一 SCSI 目标)的 4 队列虚拟 SCSI HBA。 -device virtio-scsi-pci,id=scsi0,num_queues=4 \ -device scsi-hd,drive=drive0,bus=scsi0.0,channel=0,scsi-id=0,lun=0 \ -drive file=disk1.qcow2,if=none,id=drive0 \ -device scsi-hd,drive=drive1,bus=scsi0.0,channel=0,scsi-id=0,lun=1 \ -drive file=disk2.qcow2,if=none,id=drive1 SCSI 总线拓扑,该拓扑具有一个带有两个 LUN 的 SCSI 适配器。 与前面的示例一样,从虚拟机中提取的系统日志验证内核扫描的 SCSI 总线拓扑是否与 QEMU 的配置匹配。在此方案中,磁盘 disk1.qcow2 和 disk2.qcow2 分别映射到“2:0:0:0”和“2:0:0:1”。 [ 1.212182] scsi host2: Virtio SCSI HBA [ 1.213616] scsi 2:0:0:0: Direct-Access QEMU QEMU HARDDISK 2.5+ PQ: 0 ANSI: 5 [ 1.213851] scsi 2:0:0:1: Direct-Access QEMU QEMU HARDDISK 2.5+ PQ: 0 ANSI: 5 [ 1.371305] sd 2:0:0:0: [sdb] Attached SCSI disk [ 1.372284] sd 2:0:0:1: [sdc] Attached SCSI disk [ 2.400542] sd 2:0:0:0: Attached scsi generic sg0 type 0 [ 2.403724] sd 2:0:0:1: Attached scsi generic sg1 type 0 以下从虚拟机中提取的信息确认虚拟 SCSI HBA 有 4 个 I/O 队列。每个 I/O 队列都有一个 virtio0 请求中断。 # ls /sys/block/sdb/mq/ 0 1 2 3 # ls /sys/block/sdc/mq/ 0 1 2 3 24: 0 0 0 0 PCI-MSI 65536-edge virtio0-config 25: 0 0 0 0 PCI-MSI 65537-edge virtio0-control 26: 0 0 0 0 PCI-MSI 65538-edge virtio0-event 27: 30 0 0 0 PCI-MSI 65539-edge virtio0-request 28: 0 140 0 0 PCI-MSI 65540-edge virtio0-request 29: 0 0 34 0 PCI-MSI 65541-edge virtio0-request 30: 0 0 0 276 PCI-MSI 65542-edge virtio0-request virtio-blk 半虚拟化虚拟 virtio-blk 设备。此示例显示了具有 4 个 I/O 队列的 virtio-blk,后端设备为 disk.qcow2 -device virtio-blk-pci,drive=drive0,id=virtblk0,num-queues=4 \ -drive file=disk.qcow2,if=none,id=drive0 以下从虚拟机中提取的信息确认虚拟 blk 设备有 4 个 I/O 队列。每个 I/O 队列都有一个 virtio0-req。X 中断。 # ls /sys/block/vda/mq/ 0 1 2 3 24: 0 0 0 0 PCI-MSI 65536-edge virtio0-config 25: 3 0 0 0 PCI-MSI 65537-edge virtio0-req.0 26: 0 31 0 0 PCI-MSI 65538-edge virtio0-req.1 27: 0 0 33 0 PCI-MSI 65539-edge virtio0-req.2 28: 0 0 0 0 PCI-MSI 65540-edge virtio0-req.3 sata -drive file=disk.qcow2,if=none,id=sata \ -device ich9-ahci,id=ahci \ -device ide-drive,drive=sata,bus=ahci.0 \ [ 1.518092] ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300) [ 1.371305] sd 2:0:0:0: [sdb] Attached SCSI disk [ 2.400542] sd 2:0:0:0: Attached scsi generic sg0 type 0 nvme 模拟 NVMe。此示例显示具有 8 个硬件队列的 NVMe 设备。由于虚拟机有 4 个 vcpu,因此只会使用 4 个硬件队列。后端 NVMe 设备是 disk.qcow2 -device nvme,drive=nvme0,serial=deadbeaf1,num_queues=8 \ -drive file=disk.qcow2,if=none,id=nvme0 从虚拟机中提取的系统日志可确保 Linux 内核成功检测到 NVMe 设备。 [ 1.181405] nvme nvme0: pci function 0000:00:04.0 [ 1.212434] nvme nvme0: 4/0/0 default/read/poll queues 以下从虚拟机获取的信息确认,除了管理队列外,NVMe 设备还有 4 个 I/O 队列。每个队列都有一个 nvme0qX 中断。 24: 0 11 0 0 PCI-MSI 65536-edge nvme0q0 25: 40 0 0 0 PCI-MSI 65537-edge nvme0q1 26: 0 41 0 0 PCI-MSI 65538-edge nvme0q2 27: 0 0 0 0 PCI-MSI 65539-edge nvme0q3 28: 0 0 0 4 PCI-MSI 65540-edge nvme0q4 QEMU 中的 NVMe 还支持“cmb_size_mb”,用于配置可用作控制器内存缓冲区 (CMB) 的内存量。此外,上游开发不断向 QEMU 的 NVMe 仿真添加更多功能,例如多个命名空间。 nvdimm 向虚拟机添加一个 6GB NVDIMM 来模拟 NVDIMM。 -machine pc,nvdimm \ -m 2G,maxmem=10G,slots=4 \ -object memory-backend-file,share,id=md1,mem-path=nvdimm.img,size=6G \ -device nvdimm,memdev=md1,id=nvdimm1 从虚拟机中提取的以下信息表明 NVDIMM 设备导出为块设备 /dev/pmem0。 # dmesg | grep NVDIMM [ 0.020285] ACPI: SSDT 0x000000007FFDFD85 0002CD (v01 BOCHS NVDIMM 00000001 BXPC 00000001) # ndctl list [ { "dev":"namespace0.0", "mode":"raw", "size":6442450944, "sector_size":512, "blockdev":"pmem0" } ] # lsblk | grep pmem pmem0 259:0 0 6G 0 disk NVDIMM 功能和配置非常复杂,QEMU 不断添加额外的支持。有关 QEMU 的更多 NVDIMM 用法,请参阅 QEMU NVDIMM 文档,网址为 https://docs.pmem.io Power Management 使用 QEMU 来模拟电源管理,例如冻结/恢复。虽然这不仅限于块设备,但我们将演示如何使用 NVMe 设备。这有助于了解块设备驱动程序如何与电源管理配合使用。 第一步是使用 NVMe 设备引导虚拟机。与前面的 NVMe 示例的唯一区别是使用“-monitor stdio”而不是“-serial stdio”来促进通过 shell 与 QEMU 的交互。 -device nvme,drive=nvme0,serial=deadbeaf1,num_queues=8 \ -drive file=disk.qcow2,if=none,id=nvme0 要挂起操作系统,请在虚拟机中运行以下命令: # echo freeze > /sys/power/state 这将具有冻结虚拟机的效果。要恢复,请从 QEMU 外壳运行以下命令: (qemu) system_powerdown 以下虚拟机系统日志摘录演示了 Linux 内核在冻结/恢复周期中的行为。 [ 26.945439] PM: suspend entry (s2idle) [ 26.951256] Filesystems sync: 0.005 seconds [ 26.951922] Freezing user space processes ... (elapsed 0.000 seconds) done. [ 26.953489] OOM killer disabled. [ 26.953942] Freezing remaining freezable tasks ... (elapsed 0.000 seconds) done. [ 26.955631] printk: Suspending console(s) (use no_console_suspend to debug) [ 26.962704] sd 0:0:0:0: [sda] Synchronizing SCSI cache [ 26.962972] sd 0:0:0:0: [sda] Stopping disk [ 54.674206] sd 0:0:0:0: [sda] Starting disk [ 54.678859] nvme nvme0: 4/0/0 default/read/poll queues [ 54.707283] OOM killer enabled. [ 54.707710] Restarting tasks ... done. [ 54.708596] PM: suspend exit [ 54.834191] ata2.01: NODEV after polling detection [ 54.834379] ata1.01: NODEV after polling detection [ 56.770115] e1000: ens3 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX 此方法可用于重现和分析与 NVMe 和电源管理相关的错误,例如 http://lists.infradead.org/pipermail/linux-nvme/2019-April/023237.html

