USB虚拟化

在虚拟机中访问USB设备是非常常见的需求。我们可以从USB基础知识入手,加上虚拟化的基本概念,便可掌握USB虚拟化的方法。

USB基础知识

理解USB虚拟化首先得具备一些基础的USB知识,我们可以从硬件角度和软件角度建立基本的USB的概念。

USB硬件基础

USB虚拟化_第1张图片
从硬件架构示意图上我们可以看出USB的系统组成、硬件拓扑结构。USB的关键组成一个是挂在在PCI总线上的USB主机控制器,另一个就是可热插拔的USB设备。USB主机控制器有不同的版本,分别是UHCI/OHCI对应USB1.1,EHCI对应USB2.0,XHCI对应USB 3.0。对于USB的虚拟化,要添加虚拟的USB设备,我们首先需要给虚拟机添加USB主机控制器。XHCI向前兼容USB1.1和USB2.0的设备,在2010年以后的系统中都支持XHCI,所以如果客户机操作系统如果是2010以后的系统,推荐使用XHCI。另外由于有些老的系统不支持XHCI,我们需要创建UHCI或EHCI以兼容老的Guest系统。

USB软件栈

USB虚拟化_第2张图片
基于硬件之上的USB软件栈,内核部分主要包括USB总线驱动和USB设备驱动,USB总线驱动负责驱动USB主机控制器,用于主机和设备间的数据传输。基于USB总线驱动,USB设备驱动是对设备命令的封装,控制USB设备按照命令进行工作。用户空间的USB应用程序利用文件系统接口调用USB设备驱动实现设备的读写控制。

虚拟化

虚拟化就是将物理机上的CPU、内存、存储、网络等资源以虚拟化的方式让多个虚拟机共享。我们先介绍虚拟化的基本架构,然后再看看在虚拟化环境下虚拟机如何实现对USB的访问。

虚拟化的基本架构

USB虚拟化_第3张图片
一个虚拟化系统由硬件平台、虚拟机管理器(Hypervisor)和若干个虚拟机组成。所有的硬件资源由虚拟机管理器统一掌握,由它向上呈现出一组虚拟的CPU、内存及其他相关资源给虚拟机,并实现虚拟机之间的相互隔离,另外提供全局资源的保护。

I/O虚拟化

虚拟机对设备的访问是透过一种前后端分离模型来实现的。
USB虚拟化_第4张图片
虚拟机管理器里面通过程序一个虚拟的设备给虚拟机.在虚拟机内部,应用程序按照传统的方式对设备发起访问。虚拟机内部的驱动称为前端驱动。来自虚拟机的对设备的访问都会被虚拟机管理器拦截,然后交由由虚拟机管理器的后端驱动去执行。而后端驱动本质上是调用主机上的本地驱动程序去完成对物理设备的访问。

具体到USB设备的虚拟化分两种形式,一种是让虚拟机访问主机本地的USB设备,这种叫做USB虚拟化;一种是在虚拟机访问位于远端的USB设备,这种叫做USB重定向。

USB虚拟化

USB虚拟机又主要有两种方式,一种是通过将USB主机控制器透传给虚拟机,一种是将USB端口透传给虚拟机。

USB主机控制器透传

USB虚拟化_第5张图片

这种形式是通过系统的VFIO框架和IOMMU硬件实现USB主机控制器的透传,这样在虚拟机里面就可以不受虚拟机管理器的拦截而直接访问物理的USB主机控制器。在物理的主机管理器动态插拔USB设备也都能被虚拟机直接感知到。但是这样透传整个USB主机控制器的只能被一个虚拟机所使用,主机和其他虚拟机都无法使用其下所挂载的USB设备,缺乏灵活性。

USB端口透传

USB虚拟化_第6张图片
基于USB端口的透传允许仅仅透传指定的USB端口给虚拟机,这样挂载在同一主机控制器下的不同的USB设备也可以分配给不同的虚拟机。

USB重定向

USB虚拟化_第7张图片
USB重定向通过网络协议将USB总线拉远,在客户端我们安装一个组件用于监听本地设备的USB设备接入、移除等状态信息,同时实现USB端口或着USB设备的重定向,将USB设备的相应操作通过截获,封装成行相应格式用过网络将其传输到远端的主机服务器,同时接收远端主机服务器发送回来的数据,并进行相应处理。

QEMU的USB虚拟化相关支持

QEMU源码对USB的支持

编译时根据需要打开相应的编译开关
“CONFIG_USB_OHCI=y”
“CONFIG_USB_UHCI=y”
“CONFIG_USB_EHCI=y”
“CONFIG_USB_XHCI=y”

模拟USB主机控制器

虚拟USB3.0主机控制器: -device qemu-xhci
虚拟USB2.0主机控制器: -device usb-ehci,
虚拟USB1.1主机控制器: -usb

透传USB主机控制器

比如透传BDF为0000:02:00.0的主机控制器: -device vfio-pci,host=0000:02:00.0,id=hostdev0

透传USB端口

根据USB的总线和端口地址透传USB端口: -device usb-host,hostbus=bus,hostaddr=addr
根据USB设备的PID/VID透传USB端口: -device usb-host,vendorid=vendor,productid=product
根据USB的总线和端口号进行USB透传: -device usb-host,hostbus=bus,hostport=port

USB重定向

创建一个spice虚拟机通道:-chardev spicevmc,id=charredir0,name=usbredir
创建一个USB重定向设备:-device usb-redir,chardev=charredir0,id=redir0,bus=usb.0,port=2
根据需要可以创建多个USB重定向设备:
-chardev spicevmc,id=charredir1,name=usbredir
-device usb-redir,chardev=charredir1,id=redir1,bus=usb.0,port=3

USB设备查询

在Qemu的Monitor控制台上可以进行查询主机上和客户机上的USB设备:

  • 查询位于客户机的USB设备: info usb
  • 查询位于主机的USB设备: info usbhost

USB设备动态热插拔

在Qemu的Monitor控制台上可以进行USB设备的动态热插拔:

  • 插入:usb_add host:0951:1665 #0951 is a vender ID and 1665 is a product ID.
  • 拔出: usb_del 0.3 # 0.3 means that the bus number is 0 and the address of USB device is 3.

参考链接

  1. USB虚拟化和虚拟桌面USB重定向
  2. USB 3.0 flash drive not accessible on Windows guest
  3. USB Quick Start
  4. 谈USB重定向的方式
  5. [QEMU]USB 仿真
  6. spice/qemu–usbredir

你可能感兴趣的:(虚拟化,硬件架构,教育电商,运维)