0 前言
转载请附上原文出处链接
稀土掘金本文链接:https://juejin.cn/spost/7418133431677829139
CSDN本文链接:https://blog.csdn.net/qq_43252610/article/details/142523607
1 问题概述
1.1 底子情况
【体系】Kylin-Desktop-V10-GFB-Release-2207-Build11-ARM64.iso(5.4.18-65-generic)
【CPU】vCPU
【显卡】virtio-gpu
1.2 问题现象
虚拟机添加多个串口设备后,启动失败
报错信息
- kvm: -device isa-serial,chardev=serial1: 'isa-serial' is not a valid device model name
- TASK ERROR: start failed: QEMU exited with code 1
复制代码 2 问题定位
从报错来看,是isa-serial这种类型不支持
2.1 X86架构对比验证
PVE也有x86架构的版本,x86架构添加多个串口设备并不会出现启动失败的问题
对比x86和aarch64下qemu支持的device
x86:
- /usr/bin/qemu-system-x86_64 -device help | grep serial
- name "isa-serial", bus ISA
- name "pci-serial", bus PCI
- name "pci-serial-2x", bus PCI
- name "pci-serial-4x", bus PCI
- name "usb-serial", bus usb-bus
- name "virtconsole", bus virtio-serial-bus
- name "virtio-serial-device", bus virtio-bus
- name "virtio-serial-pci", bus PCI, alias "virtio-serial"
- name "virtio-serial-pci-non-transitional", bus PCI
- name "virtio-serial-pci-transitional", bus PCI
- name "virtserialport", bus virtio-serial-bus
复制代码 aarch64:
- /usr/bin/qemu-system-aarch64 -device help | grep serial
- name "pci-serial", bus PCI
- name "pci-serial-2x", bus PCI
- name "pci-serial-4x", bus PCI
- name "usb-serial", bus usb-bus
- name "virtconsole", bus virtio-serial-bus
- name "virtio-serial-device", bus virtio-bus
- name "virtio-serial-pci", bus PCI, alias "virtio-serial"
- name "virtio-serial-pci-non-transitional", bus PCI
- name "virtio-serial-pci-transitional", bus PCI
- name "virtserialport", bus virtio-serial-bus
复制代码 可以看出aarch64架构中确实不包罗isa-serial设备
2.2 kvm启动参数分析
那么aarch64架构下,第一个串口设备是如何正常工作的呢?
对比下虚拟机的PVE设置文件的串口部分(去掉了无关信息)
x86:
- cat /etc/pve/qemu-server/103.conf
- serial0: socket
- serial1: socket
复制代码 aarch64:
- cat /etc/pve/qemu-server/142.conf
- serial0: socket
- serial1: socket
复制代码 从设置文件来看,串口设置信息是完全划一的
PVE底层是使用kvm启动虚拟机,对比看一下虚拟机在kvm的启动参数的串口部分(去掉了无关信息)
PVE自身提供对应的接口检察
x86:
- qm showcmd 103 --pretty
- -chardev 'socket,id=serial0,path=/var/run/qemu-server/103.serial0,server=on,wait=off'
- \
- -device 'isa-serial,chardev=serial0' \
- -chardev 'socket,id=serial1,path=/var/run/qemu-server/103.serial1,server=on,wait=off' \
- -device 'isa-serial,chardev=serial1' \
复制代码 aarch64:
- qm showcmd 142 --pretty
- -chardev 'socket,id=serial0,path=/var/run/qemu-server/142.serial0,server=on,wait=off' \
- -serial chardev:serial0 \
- -chardev 'socket,id=serial1,path=/var/run/qemu-server/142.serial1,server=on,wait=off' \
- -device 'isa-serial,chardev=serial1' \
复制代码 x86架构下第一个串口设备设置的是-device 'isa-serial,chardev=serial0',aarch64架构下第一个串口设备设置的却是-serial chardev:serial0
这也是为什么aarch64架构下第一个串口是能正常启动的,因为第一个串口没有使用isa-serial设备
PVE的虚拟机设置文件到kvm启动参数之间的转换,是由PVE实现并控制的,同样的虚拟机设置文件出现差别架构下的差别表现,须要分析PVE的相关代码
2.3 PVE代码分析
PVE的github官方只读镜像项目路径:https://github.com/proxmox
PVE的虚拟机设置文件到kvm启动参数之间的转换代码位于qemu-server的组件中,具体实现的代码文件如下:https://github.com/proxmox/qemu-server/blob/master/PVE/QemuServer.pm
- # serial devices
- for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
- my $path = $conf->{"serial$i"} or next;
- if ($path eq 'socket') {
- my $socket = "/var/run/qemu-server/${vmid}.serial$i";
- push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server=on,wait=off";
- # On aarch64, serial0 is the UART device. QEMU only allows
- # connecting UART devices via the '-serial' command line, as
- # the device has a fixed slot on the hardware...
- if ($arch eq 'aarch64' && $i == 0) {
- push @$devices, '-serial', "chardev:serial$i";
- } else {
- push @$devices, '-device', "isa-serial,chardev=serial$i";
- }
- } else {
- die "no such serial device\n" if ! -c $path;
- push @$devices, '-chardev', "serial,id=serial$i,path=$path";
- push @$devices, '-device', "isa-serial,chardev=serial$i";
- }
- }
复制代码 PVE在aarch64的架构情况下,第一个串口设备会进行特别处置惩罚,添加的实际是一个UART设备
2.3.1 PVE对于最大串口数量的限制
在这里稍微多说一点,MAX_SERIAL_PORTS的值即是4
因为isa-serial支持的最大数量是4,如果虚拟机启动时超过4个isa-serial时,qemu会报错
- kvm: -device isa-serial,chardev=serial4: Max. supported number of ISA serial ports is 4.
复制代码 然而使用libvirt管理并创建的虚拟机并不会有最大4个串口数量的限制,这是因为两者对于串口设备的创建方式及设备选型的差别
后续章节会简单剖析libvirt在串口这一块的处置惩罚
2.4 定位结论
如上述分析,虚拟机多串口启动失败的缘故起因为:aarch64架构下kvm不支持isa-serial的设备类型
3 机理分析
3.1 ISA总线介绍
以下内容引用维基百科:https://zh.wikipedia.org/wiki/工业尺度布局
工业尺度布局(Industry Standard Architecture,简称ISA)是IBM PC兼容机上的一种总线。
ISA在1981年诞生,并作为IBM PC的8位体系,1983年,ISA被升级作为XT总线体系。后来16位的ISA总线在1984年发布。由于ISA计划出来的目的是为了毗连扩展卡和主板,因此ISA的协议同样允许总线控制,尽管只有前16MB的存储器可以直接访问。
PCI是第一个在物理展上集成了ISA、MCA、EISA优点的扩展接口,并且它的出现直接地挤压了ISA在主板上的职位。起初,主板上依然是ISA占主流职位,但已经出现了PCI槽了。到了20世纪90年代中叶,两种插槽已经在主板上半斤八两了,而ISA插槽很快就在消费PC市场上成为了少数派。微软的PC 97规范更劝说ISA插槽应该完全被撤除,尽管当时的体系架构依然须要ISA存在于一些内部发育不良的管线去操纵软驱、串口、等等。ISA接口在随后的几年里依然存在,乃至瞥见AGP接口的诞生,之后遗留在主板上的ISA接口也退出汗青了。
固然物理设备上ISA已经退出汗青了,但是在PVE中,串口仍然默认使用的是ISA总线的串口设备
从上述介绍来看,aarch64架构不支持ISA总线也是完全正常的,毕竟ISA总线已经是汗青遗留的产物了
从qemu中也能看出aarch64架构完全不支持ISA总线
x86:
- /usr/bin/qemu-system-x86_64 -device help | grep isa
- name "isa-fdc", bus ISA, desc "virtual floppy controller"
- name "isa-ide", bus ISA
- name "ne2k_isa", bus ISA
- name "isa-parallel", bus ISA
- name "isa-serial", bus ISA
- name "isa-cirrus-vga", bus ISA
- name "isa-vga", bus ISA
- name "isa-applesmc", bus ISA
- name "isa-debug-exit", bus ISA
- name "isa-debugcon", bus ISA
- name "isa-ipmi-bt", bus ISA
- name "isa-ipmi-kcs", bus ISA
复制代码 aarch64:
- /usr/bin/qemu-system-aarch64 -device help | grep isa
复制代码 4 办理步伐
根据问题定位和机理分析章节,办理该问题须要更换aarch64架构下默认创建的串口设备类型
4.1 libvirt中的串口设备默认类型
libvirt是另一套提供管理虚拟化平台的工具包,可以参考一下libvirt在aarch64架构下是如何创建串口设备的
libvirt是使用xml格式管理虚拟机的设置文件,和PVE类似,虚拟机设置文件到kvm启动参数的转换逻辑是由libvirt处置惩罚的
virt-manager提供基于libvirt图形化界面管理虚拟机,看一下aarch64架构下默认添加的串口类型
重点关注写入的xml文件内容
- <serial type="pty">
- <target type="system-serial" port="2">
- <model name="pl011"/>
- </target>
- </serial>
复制代码 以下内容引用libvirt的官方文档:https://libvirt.org/formatdomain.html#serial-port
The target element can have an optional port attribute, which specifies the port number (starting from 0), and an optional type attribute: valid values are, since 1.0.2, isa-serial (usable with x86 guests), usb-serial (usable whenever USB support is available) and pci-serial (usable whenever PCI support is available); since 3.10.0, spapr-vio-serial (usable with ppc64/pseries guests), system-serial (usable with aarch64/virt and, since 4.7.0, riscv/virt guests), sclp-serial (usable with s390 and s390x guests) are available as well and since 8.1.0 isa-debug (usable with x86 guests).
Since 3.10.0, the target element can have an optional model subelement; valid values for its name attribute are: isa-serial (usable with the isa-serial target type); usb-serial (usable with the usb-serial target type); pci-serial (usable with the pci-serial target type); spapr-vty (usable with the spapr-vio-serial target type); pl011 and, since 4.7.0, 16550a (usable with the system-serial target type); sclpconsole and sclplmconsole (usable with the sclp-serial target type). Since: 8.1.0, isa-debugcon (usable with the isa-debug target type); provides a virtual console for receiving debug messages from the firmware on x86 platforms. Providing a target model is usually unnecessary: libvirt will automatically pick one that’s suitable for the chosen target type, and overriding that value is generally not recommended.
If any of the attributes is not specified by the user, libvirt will choose a value suitable for most users.
Most target types support configuring the guest-visible device address as documented in the Device Addresses section; more specifically, acceptable address types are isa (for isa-serial), usb (for usb-serial), pci (for pci-serial) and spapr-vio (for spapr-vio-serial). The system-serial and sclp-serial target types don’t support specifying an address.
For the relationship between serial ports and consoles, refer to the Relationship between serial ports and consoles section.
- serial:
有两种类型
pty以伪终端(Pseudo Terminal)形式创建,可以用source标签指定物理机中的pts终端设备,例如<source path='/dev/pts/3'/>
file以文件形式创建,可以用source标签指定物理机中的文件路径,例如<source path='/tmp/file' append='on'>
- target:类型很多,可以参考引用内容,此中aarch64架构下默认类型为sysem-serial
- model:类型很多,可以参考引用内容,此中aarch64架构下默认类型为pl011
最终虚拟机的kvm启动参数,可以在虚拟机启动后用ps -aux | grep kvm命令检察
- -chardev pty,id=charserial0
- -serial chardev:charserial0
- -chardev pty,id=charserial1
- -serial chardev:charserial1
- -chardev pty,id=charserial2
- -serial chardev:charserial2
复制代码 对比PVE平台的虚拟机的kvm启动参数,libvirt着实是创建UART类型的串口设备(chardev类型libvirt使用的是pty的形式,PVE使用的是socket的形式)
注意:libvirt此时添加的多个串口设备,实际只有一个设备生效,后续章节会进行具体阐明
4.2 qemu monitor
这里简单提一下qemu monitor几个调试命令,后续确认设备类型和设备状态都会用到
开启qemu monitor须要在虚拟机的kvm启动参数中添加-monitor stdio,且确保没有-daemonize参数
开启后在终端通过命令启动虚拟机,会主动跳转到qemu monitor界面
4.2.1 info pci
显示虚拟机的pci设备,例如
- info pci
- Bus 0, device 30, function 0:
- PCI bridge: PCI device 1b36:000c
- IRQ 255, pin A
- BUS 0.
- secondary bus 1.
- subordinate bus 1.
- IO range [0x1000, 0x1fff]
- memory range [0x10000000, 0x101fffff]
- prefetchable memory range [0x8000000000, 0x80001fffff]
- BAR0: 32 bit memory at 0x10444000 [0x10444fff].
- id "pcie.1"
复制代码 4.2.2 info qtree
显示虚拟机的所有设备,例如
- info qtree
- dev: kvm-arm-gicv3, id ""
- gpio-out "sysbus-irq" 32
- gpio-in "" 512
- num-cpu = 8 (0x8)
- num-irq = 288 (0x120)
- revision = 3 (0x3)
- has-lpi = false
- has-security-extensions = false
- force-8-bit-prio = false
- len-redist-region-count = 1 (0x1)
- mmio 0000000008000000/0000000000010000
- mmio 00000000080a0000/0000000000100000
复制代码 4.2.3 info usb
显示虚拟机的usb设备,例如
- info usb
- Device 0.1, Port 1, Speed 480 Mb/s, Product QEMU USB Tablet, ID: tablet
- Device 0.2, Port 2, Speed 480 Mb/s, Product QEMU USB Keyboard, ID: keyboard
复制代码 4.3 qemu中串口设备类型介绍
一般虚拟机要添加串口设备,和chardev、serial、device3个设置项相关
下面列举几个典范的例子:
- 虚拟机中的串口设备重定向到物理机的/dev/ttyS1设备
- 虚拟机中的串口设备重定向到物理机的伪终端(qemu主动创建新的伪终端)
- -chardev pty,id=charserial0
- -serial chardev:charserial0
复制代码 - 虚拟机中的串口设备(类型为usb-serial)重定向到物理机的伪终端(qemu主动创建新的伪终端)
- -chardev pty,id=charserial0
- -device usb-serial,chardev=charserial0,always-plugged=true
复制代码 4.3.1 chardev
字符设备完备的具体参数可参照官方文档:https://www.qemu.org/docs/master/system/qemu-manpage.html
参数格式:-chardev backend,id=id[,mux=on|off][,options]
可用的backend类型:
Backend is one of: null, socket, udp, msmouse, vc, ringbuf, file, pipe, console, serial, pty, stdio, braille, parallel, spicevmc, spiceport. The specific backend will determine the applicable options.
这里挑几个常用的,贴一下具体的参数阐明
- socket
PVE默认创建的就是该类型(xterm.js的串口控制台就是使用该socket实现)
- -chardev 'socket,id=serial0,path=/var/run/qemu-server/103.serial0,server=on,wait=off'
复制代码 - -chardev socket,id=id[,TCP options or unix options][,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,tls-creds=id][,tls-authz=id]
复制代码 Create a two-way stream socket, which can be either a TCP or a unix socket. A unix socket will be created if path is specified. Behaviour is undefined if TCP options are specified for a unix socket.
server=on|off specifies that the socket shall be a listening socket.
wait=on|off specifies that QEMU should not block waiting for a client to connect to a listening socket.
telnet=on|off specifies that traffic on the socket should interpret telnet escape sequences.
websocket=on|off specifies that the socket uses WebSocket protocol for communication.
reconnect sets the timeout for reconnecting on non-server sockets when the remote end goes away. qemu will delay this many seconds and then attempt to reconnect. Zero disables reconnecting, and is the default.
tls-creds requests enablement of the TLS protocol for encryption, and specifies the id of the TLS credentials to use for the handshake. The credentials must be previously created with the -object tls-creds argument.
tls-auth provides the ID of the QAuthZ authorization object against which the client’s x509 distinguished name will be validated. This object is only resolved at time of use, so can be deleted and recreated on the fly while the chardev server is active. If missing, it will default to denying access.
TCP and unix socket options are given below:
- TCP options: port=port[,host=host][,to=to][,ipv4=on|off][,ipv6=on|off][,nodelay=on|off]
host for a listening socket specifies the local address to be bound. For a connecting socket species the remote host to connect to. host is optional for listening sockets. If not specified it defaults to 0.0.0.0.port for a listening socket specifies the local port to be bound. For a connecting socket specifies the port on the remote host to connect to. port can be given as either a port number or a service name. port is required.to is only relevant to listening sockets. If it is specified, and port cannot be bound, QEMU will attempt to bind to subsequent ports up to and including to until it succeeds. to must be specified as a port number.ipv4=on|off and ipv6=on|off specify that either IPv4 or IPv6 must be used. If neither is specified the socket may use either protocol.nodelay=on|off disables the Nagle algorithm.
- unix options: path=path[,abstract=on|off][,tight=on|off]
path specifies the local path of the unix socket. path is required. abstract=on|off specifies the use of the abstract socket namespace, rather than the filesystem. Optional, defaults to false. tight=on|off sets the socket length of abstract sockets to their minimum, rather than the full sun_path length. Optional, defaults to true.
- serial
将字符设备映射到物理机串口设备中
- -chardev serial,id=serial0,path=/dev/ttyS0
复制代码 - -chardev serial,id=id,path=path
复制代码 Send traffic from the guest to a serial device on the host.
On Unix hosts serial will actually accept any tty device, not only serial lines.
path specifies the name of the serial device to open.
- pty
将字符设备映射到物理机的伪终端(qemu主动创建新的伪终端)
Create a new pseudo-terminal on the host and connect to it. pty does not take any options.
pty is not available on Windows hosts.
4.3.2 serial
serial是一种简写的方式,后端实现着实也是创建了chardev设备的
参数格式:-serial dev
这里挑几个常用的,贴一下具体的参数阐明
- pty
将串口映射到物理机的伪终端(qemu主动创建新的伪终端)
[Linux only] Pseudo TTY (a new PTY is automatically allocated)
等同于
- -chardev pty,id=serial0
- -serial chardev:serial0
复制代码 - chardev:id
使用-chardev默认的设备创建串口(存在差别架构下的差别表现)
aarch64:默认设备模型为pl011
x86:默认设备类型为isa-serial,设备模型为16550A
Use a named character device defined with the -chardev option.
- /dev/XXX
将字符设备映射到物理机串口设备中
[Linux only] Use host tty, e.g. /dev/ttyS0. The host serial port parameters are set according to the emulated ones.
等同于
- -chardev serial,id=serial0,path=/dev/ttyS0
- -serial chardev:serial0
复制代码 4.3.3 device
4.3.3.1 isa-serial
仅x86架构可用,须要有isa总线的支持,设备模型为16550A
在x86架构中默认创建的串口类型
在虚拟机中一般默认为ttyS*设备
- dmesg | grep tty
- [ 0.052049] printk: console [tty0] enabled
- [ 0.395284] 00:03: ttyS3 at I/O 0x2e8 (irq = 3, base_baud = 115200) is a 16550A
- [ 0.418666] 00:04: ttyS2 at I/O 0x3e8 (irq = 4, base_baud = 115200) is a 16550A
- [ 0.441999] 00:05: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A
- [ 0.465141] 00:06: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
复制代码 创建示例:
- -chardev pty,id=charserial0
- -device isa-serial,id=isaserial0,chardev=charserial0
复制代码 注意:单个虚拟机最大支持的isa-serial数量为4
qemu monitor中用info qtree确认设备树中最多只有4个isa-serial设备
- dev: isa-serial, id ""
- index = 3 (0x3)
- iobase = 744 (0x2e8)
- irq = 3 (0x3)
- dev: isa-serial, id ""
- index = 2 (0x2)
- iobase = 1000 (0x3e8)
- irq = 4 (0x4)
- dev: isa-serial, id ""
- index = 1 (0x1)
- iobase = 760 (0x2f8)
- irq = 3 (0x3)
- dev: isa-serial, id ""
- index = 0 (0x0)
- iobase = 1016 (0x3f8)
- irq = 4 (0x4)
复制代码 4.3.3.2 usb-serial
设备模型为FTDI FT232BM,体系须要加载相关驱动(usbserial、ftdi_sio)
支持的最大数量取决于USB控制器类型(PVE中MAX_USB_DEVICES写死为14)
在虚拟机中一般默认为ttyUSB*设备
- dmesg | grep tty
- [ 0.123973] ARMH0011:00: ttyAMA0 at MMIO 0x9000000 (irq = 4, base_baud = 0) is a SBSA
- [ 0.258444] console [ttyAMA0] enabled
- [ 3.552636] usb 1-4: FTDI USB Serial Device converter now attached to ttyUSB0
- [ 3.555623] usb 1-5: FTDI USB Serial Device converter now attached to ttyUSB1
- [ 3.558408] usb 1-6: FTDI USB Serial Device converter now attached to ttyUSB2
- [ 3.561142] usb 1-7: FTDI USB Serial Device converter now attached to ttyUSB3
复制代码- lsusb | grep Serial
- Bus 001 Device 009: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
- Bus 001 Device 008: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
- Bus 001 Device 007: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
- Bus 001 Device 006: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
- Bus 001 Device 005: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
- Bus 001 Device 004: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
复制代码 实际测试须要添加always-plugged=true才能正常辨认
always-plugged参数的提交:https://lists.nongnu.org/archive/html/qemu-devel/2020-10/msg07372.html
简单来说就是某些体系拔插USB设备后设备ID会厘革,须要将厘革通知到体系。这个参数则保证任何情况下始终保证USB的毗连状态,不受后端chardev的影响
- Some operating systems will generate a new device ID when a USB device is
- unplugged
- and then replugged into the USB. If this is done whilst switching between
- multiple
- applications over a virtual serial port, the change of device ID requires going
- back into the OS/application to locate the new device accordingly.
- Add a new always-plugged property that if specified will ensure that the device
- always remains attached to the USB regardless of the state of the backend
- chardev.
复制代码 创建示例:
在USB控制器使用qemu-xhci时,可不指定bus
- -chardev pty,id=charserial0
- -device usb-serial,id=usbserial0,chardev=charserial0,always-plugged=true,bus=xhci.0
复制代码 4.3.3.3 pci-serial
设备模型为对16550 UART的pci包装,详见:https://www.qemu.org/docs/master/specs/pci-serial.html
在虚拟机中一般默认为ttyS*设备
- dmesg | grep tty
- [ 5.440488] device: 'ttyS0': device_unregister
- [ 5.440622] PM: Removing info for No Bus:ttyS0
- [ 5.467484] 0000:00:02.0: ttyS0 at I/O 0x3120 (irq = 39, base_baud = 115200) is a 16550A
- [ 5.467576] device: 'ttyS0': device_add
- [ 5.467625] PM: Adding info for No Bus:ttyS0
- [ 5.478735] device: 'ttyS1': device_unregister
- [ 5.478856] PM: Removing info for No Bus:ttyS1
- [ 5.504207] 0000:00:03.0: ttyS1 at I/O 0x3128 (irq = 40, base_baud = 115200) is a 16550A
- [ 5.504304] device: 'ttyS1': device_add
- [ 5.504356] PM: Adding info for No Bus:ttyS1
- [ 5.506137] device: 'ttyS2': device_unregister
- [ 5.506233] PM: Removing info for No Bus:ttyS2
- [ 5.532378] 0000:00:04.0: ttyS2 at I/O 0x3130 (irq = 37, base_baud = 115200) is a 16550A
- [ 5.532486] device: 'ttyS2': device_add
- [ 5.532517] PM: Adding info for No Bus:ttyS2
复制代码- lspci | grep Serial
- 00:02.0 Serial controller: Red Hat, Inc. QEMU PCI 16550A Adapter (rev 01)
- 00:03.0 Serial controller: Red Hat, Inc. QEMU PCI 16550A Adapter (rev 01)
- 00:04.0 Serial controller: Red Hat, Inc. QEMU PCI 16550A Adapter (rev 01)
复制代码 创建示例:
- -chardev pty,id=charserial0
- -device pci-serial,id=pciserial0,chardev=charserial0,bus=pcie.0
复制代码 4.3.3.4 virtio-serial
virtio-serial差别于其他的serial设备,基于virtio设备框架,除了支持尺度的串行端口操纵,还可以用于传输命令、日志 、文件等,在qemu-guest-agent、spice中都有成熟的应用
virtio-serial原生支持多端口(单个设备最大支持31个端口),支持端口热拔插
在虚拟机中一般默认为vport*设备(/dev/virtio-ports/{portname})
- dmesg | grep vport
- [ 0.903643] device: 'vport0p1': device_add
- [ 0.903666] PM: Adding info for No Bus:vport0p1
- [ 0.903851] device: 'vport0p2': device_add
- [ 0.903889] PM: Adding info for No Bus:vport0p2
- [ 0.904031] device: 'vport0p3': device_add
- [ 0.904045] PM: Adding info for No Bus:vport0p3
复制代码 创建示例:
- -device virtio-serial,id=virtioserial,bus=pcie.0,addr=0x2
- -chardev pty,id=charserial0
- -device virtserialport,chardev=charserial0,name=virtserialport.0,bus=virtioserial.0
复制代码 4.3.3.5 UART(aarch64)
aarch64架构中默认创建的类型,设备模型为pl011(x86架构中无此类型)
在虚拟机中一般默认为ttyAMA*设备
- dmesg | grep tty
- [ 0.135970] ARMH0011:00: ttyAMA0 at MMIO 0x9000000 (irq = 4, base_baud = 0) is a SBSA
- [ 0.272514] console [ttyAMA0] enabled
- [ 175.413222] audit: type=1006 audit(1726283302.633:306): pid=3980 uid=0 old-auid=4294967295 auid=0 tty=(none) old-ses=4294967295 ses=3 res=1
复制代码 创建示例:
- -chardev pty,id=charserial0
- -serial chardev:charserial0
复制代码 注意:aarch64架构中单个虚拟机最大支持的数量为1
qemu monitor中用info qtree确认设备树中最多只有1个pl011设备
- dev: pl011, id ""
- gpio-out "sysbus-irq" 6
- clock-in "clk" freq_hz=0 Hz
- chardev = "charserial0"
- migrate-clk = true
- mmio ffffffffffffffff/0000000000001000
复制代码 4.4 aarch64架构下串口设备选型及验证
4.4.1 usb-serial
4.4.1.1 修改方案
暂不处置惩罚$MAX_SERIAL_PORTS的最大4个串口限制
- # serial devices
- for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
- my $path = $conf->{"serial$i"} or next;
- if ($path eq 'socket') {
- my $socket = "/var/run/qemu-server/${vmid}.serial$i";
- push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server=on,wait=off";
- # On aarch64, serial0 is the UART device. QEMU only allows
- # connecting UART devices via the '-serial' command line, as
- # the device has a fixed slot on the hardware...
- if ($arch eq 'aarch64') {
- if ($i == 0) {
- push @$devices, '-serial', "chardev:serial$i";
- } else {
- push @$devices, '-device', "usb-serial,id=usbserial$i,chardev=serial$i,always-plugged=true";
- }
- } else {
- push @$devices, '-device', "isa-serial,chardev=serial$i";
- }
- } else {
- die "no such serial device\n" if ! -c $path;
- push @$devices, '-chardev', "serial,id=serial$i,path=$path";
- push @$devices, '-device', "isa-serial,chardev=serial$i";
- }
- }
复制代码 4.4.1.2 测试验证
为了方便测试,验证时chardev使用pty
4.4.1.2.1 PVE默认最大数量测试(1个UART+3个usb-serial)
测试参数:
- -chardev socket,id=serial0,path=/var/run/qemu-server/${vmid}.serial0,server=on,wait=off
- -serial chardev:serial0
- -chardev pty,id=serial1
- -device usb-serial,id=usbserial1,chardev=serial1,always-plugged=true
- -chardev pty,id=serial2
- -device usb-serial,id=usbserial2,chardev=serial2,always-plugged=true
- -chardev pty,id=serial3
- -device usb-serial,id=usbserial3,chardev=serial3,always-plugged=true
复制代码 测试方法:
虚拟机串口发送测试(minicom):
虚拟机内串口设备发送字符,物理机对应pty端口可以接收到字符
虚拟机串口接收测试(minicom):
物理机对应pty端口发送字符,虚拟机内串口设备可以接收到字符
虚拟机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/ttyUSB0
复制代码 物理机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/pts/1
复制代码 盼望结果:
虚拟机串口设备能正常接收或发送字符
测试结果:
体系串口id虚拟机串口发送测试虚拟机串口接收测试Kylin-V10-Desktop(2207)usbserial1通过通过Kylin-V10-Desktop(2207)usbserial2通过通过Kylin-V10-Desktop(2207)usbserial3通过通过Kylin-V10-Server(2204)usbserial1通过通过Kylin-V10-Server(2204)usbserial2通过通过Kylin-V10-Server(2204)usbserial3通过通过Kylin-V4-Desktop(sp4-20200728)usbserial1通过通过Kylin-V4-Desktop(sp4-20200728)usbserial2通过通过Kylin-V4-Desktop(sp4-20200728)usbserial3通过通过Kylin-V4-Server(sp4-20070420)usbserial1通过通过Kylin-V4-Server(sp4-20070420)usbserial2通过通过Kylin-V4-Server(sp4-20070420)usbserial3通过通过 4.4.1.2.2 数量测试(1个UART+9个usb-serial)
使用命令行参数启动虚拟机,手动修改命令行参数以跳出PVE的最大限制
测试参数:
- -chardev socket,id=serial0,path=/var/run/qemu-server/${vmid}.serial0,server=on,wait=off
- -serial chardev:serial0
- -chardev pty,id=serial1
- -device usb-serial,id=usbserial1,chardev=serial1,always-plugged=true
- -chardev pty,id=serial2
- -device usb-serial,id=usbserial2,chardev=serial2,always-plugged=true
- -chardev pty,id=serial3
- -device usb-serial,id=usbserial3,chardev=serial3,always-plugged=true
- -chardev pty,id=serial4-device usb-serial,id=usbserial4,chardev=serial4,always-plugged=true-chardev pty,id=serial5-device usb-serial,id=usbserial5,chardev=serial5,always-plugged=true-chardev pty,id=serial6-device usb-serial,id=usbserial6,chardev=serial6,always-plugged=true-chardev pty,id=serial7-device usb-serial,id=usbserial7,chardev=serial7,always-plugged=true-chardev pty,id=serial8-device usb-serial,id=usbserial8,chardev=serial8,always-plugged=true-chardev pty,id=serial9-device usb-serial,id=usbserial9,chardev=serial9,always-plugged=true
复制代码 测试方法:
虚拟机串口发送测试(minicom):
虚拟机内串口设备发送字符,物理机对应pty端口可以接收到字符
虚拟机串口接收测试(minicom):
物理机对应pty端口发送字符,虚拟机内串口设备可以接收到字符
虚拟机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/ttyUSB0
复制代码 物理机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/pts/1
复制代码 盼望结果:
虚拟机串口设备能正常接收或发送字符
测试结果:
体系串口id虚拟机串口发送测试虚拟机串口接收测试Kylin-V10-Desktop(2207)usbserial1通过通过Kylin-V10-Desktop(2207)usbserial2通过通过Kylin-V10-Desktop(2207)usbserial3通过通过Kylin-V10-Desktop(2207)usbserial4通过通过Kylin-V10-Desktop(2207)usbserial5通过通过Kylin-V10-Desktop(2207)usbserial6通过通过Kylin-V10-Desktop(2207)usbserial7通过通过Kylin-V10-Desktop(2207)usbserial8通过通过Kylin-V10-Desktop(2207)usbserial9通过通过Kylin-V10-Server(2204)usbserial1通过通过Kylin-V10-Server(2204)usbserial2通过通过Kylin-V10-Server(2204)usbserial3通过通过Kylin-V10-Server(2204)usbserial4通过通过Kylin-V10-Server(2204)usbserial5通过通过Kylin-V10-Server(2204)usbserial6通过通过Kylin-V10-Server(2204)usbserial7通过通过Kylin-V10-Server(2204)usbserial8通过通过Kylin-V10-Server(2204)usbserial9通过通过Kylin-V4-Desktop(sp4-20200728)usbserial1通过通过Kylin-V4-Desktop(sp4-20200728)usbserial2通过通过Kylin-V4-Desktop(sp4-20200728)usbserial3通过通过Kylin-V4-Desktop(sp4-20200728)usbserial4通过通过Kylin-V4-Desktop(sp4-20200728)usbserial5通过通过Kylin-V4-Desktop(sp4-20200728)usbserial6通过通过Kylin-V4-Desktop(sp4-20200728)usbserial7通过通过Kylin-V4-Desktop(sp4-20200728)usbserial8通过通过Kylin-V4-Desktop(sp4-20200728)usbserial9通过通过Kylin-V4-Server(sp4-20070420)usbserial1通过通过Kylin-V4-Server(sp4-20070420)usbserial2通过通过Kylin-V4-Server(sp4-20070420)usbserial3通过通过Kylin-V4-Server(sp4-20070420)usbserial4通过通过Kylin-V4-Server(sp4-20070420)usbserial5通过通过Kylin-V4-Server(sp4-20070420)usbserial6通过通过Kylin-V4-Server(sp4-20070420)usbserial7通过通过Kylin-V4-Server(sp4-20070420)usbserial8通过通过Kylin-V4-Server(sp4-20070420)usbserial9通过通过 4.4.1.2.3 热拔插测试
须要使用qemu monitor对USB设备进行热拔插
chardev类型无法进行热拔插,仅能对usb-serial热拔插,故如果须要实现串口灵活热拔插,须要提前添加足额的chardev
测试参数:
- -monitor stdio-chardev socket,id=serial0,path=/var/run/qemu-server/${vmid}.serial0,server=on,wait=off
- -serial chardev:serial0
- -chardev pty,id=serial1
- -device usb-serial,id=usbserial1,chardev=serial1,always-plugged=true
- -chardev pty,id=serial2
- -device usb-serial,id=usbserial2,chardev=serial2,always-plugged=true
- -chardev pty,id=serial3
- -device usb-serial,id=usbserial3,chardev=serial3,always-plugged=true
- -chardev pty,id=serial4
复制代码 测试方法:
热拔插USB设备(qemu monitor):
- # 拔出设备
- device_del usbserial1
- # 插入设备(id1)
- device_add usb-serial,id=usbserial1,chardev=serial1,always-plugged=true
- # 插入设备(id4)
- device_add usb-serial,id=usbserial4,chardev=serial4,always-plugged=true
复制代码 虚拟机串口发送测试(minicom):
虚拟机内串口设备发送字符,物理机对应pty端口可以接收到字符
虚拟机串口接收测试(minicom):
物理机对应pty端口发送字符,虚拟机内串口设备可以接收到字符
虚拟机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/ttyUSB0
复制代码 物理机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/pts/1
复制代码 盼望结果:
热拔插USB设备后,虚拟机串口设备能正常接收或发送字符
测试结果:
体系拔出串口id插入串口id虚拟机串口发送测试虚拟机串口接收测试Kylin-V10-Desktop(2207)usbserial1usbserial1通过通过Kylin-V10-Desktop(2207)/usbserial4通过通过Kylin-V10-Server(2204)usbserial1usbserial1通过通过Kylin-V10-Server(2204)/usbserial4通过通过Kylin-V4-Desktop(sp4-20200728)usbserial1usbserial1通过通过Kylin-V4-Desktop(sp4-20200728)/usbserial4通过通过Kylin-V4-Server(sp4-20070420)usbserial1usbserial1通过通过Kylin-V4-Server(sp4-20070420)/usbserial4通过通过 4.4.2 pci-serial
4.4.2.1 修改方案
暂不处置惩罚$MAX_SERIAL_PORTS的最大4个串口限制
- # serial devices
- for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
- my $path = $conf->{"serial$i"} or next;
- if ($path eq 'socket') {
- my $socket = "/var/run/qemu-server/${vmid}.serial$i";
- push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server=on,wait=off";
- # On aarch64, serial0 is the UART device. QEMU only allows
- # connecting UART devices via the '-serial' command line, as
- # the device has a fixed slot on the hardware...
- if ($arch eq 'aarch64') {
- if ($i == 0) {
- push @$devices, '-serial', "chardev:serial$i";
- } else {
- push @$devices, '-device', "pci-serial,id=pciserial$i,chardev=serial$i";
- }
- } else {
- push @$devices, '-device', "isa-serial,chardev=serial$i";
- }
- } else {
- die "no such serial device\n" if ! -c $path;
- push @$devices, '-chardev', "serial,id=serial$i,path=$path";
- push @$devices, '-device', "isa-serial,chardev=serial$i";
- }
- }
复制代码 4.4.2.2 测试验证
为了方便测试,验证时chardev使用pty
4.4.2.2.1 PVE默认最大数量测试(1个UART+3个pci-serial)
测试参数:
- -chardev socket,id=serial0,path=/var/run/qemu-server/${vmid}.serial0,server=on,wait=off
- -serial chardev:serial0
- -chardev pty,id=serial1
- -device pci-serial,id=pciserial1,chardev=serial1,bus=pcie.0,addr=0x2
- -chardev pty,id=serial2
- -device pci-serial,id=pciserial2,chardev=serial2,bus=pcie.0,addr=0x3
- -chardev pty,id=serial3
- -device pci-serial,id=pciserial3,chardev=serial3,bus=pcie.0,addr=0x4
复制代码 测试方法:
虚拟机串口发送测试(minicom):
虚拟机内串口设备发送字符,物理机对应pty端口可以接收到字符
虚拟机串口接收测试(minicom):
物理机对应pty端口发送字符,虚拟机内串口设备可以接收到字符
虚拟机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/ttyS0
复制代码 物理机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/pts/1
复制代码 盼望结果:
虚拟机串口设备能正常接收或发送字符
测试结果:
体系串口id虚拟机串口发送测试虚拟机串口接收测试Kylin-V10-Desktop(2207)pciserial1通过通过Kylin-V10-Desktop(2207)pciserial2通过通过Kylin-V10-Desktop(2207)pciserial3通过通过Kylin-V10-Server(2204)pciserial1通过通过Kylin-V10-Server(2204)pciserial2通过通过Kylin-V10-Server(2204)pciserial3通过通过Kylin-V4-Desktop(sp4-20200728)pciserial1通过通过Kylin-V4-Desktop(sp4-20200728)pciserial2通过通过Kylin-V4-Desktop(sp4-20200728)pciserial3通过通过Kylin-V4-Server(sp4-20070420)pciserial1通过通过Kylin-V4-Server(sp4-20070420)pciserial2通过通过Kylin-V4-Server(sp4-20070420)pciserial3通过通过 4.4.2.2.2 数量测试(1个UART+9个pci-serial)
使用命令行参数启动虚拟机,手动修改命令行参数以跳出PVE的最大限制
测试参数:
- -chardev socket,id=serial0,path=/var/run/qemu-server/${vmid}.serial0,server=on,wait=off
- -serial chardev:serial0
- -chardev pty,id=serial1
- -device pci-serial,id=pciserial1,chardev=serial1,bus=pcie.0,addr=0x2
- -chardev pty,id=serial2
- -device pci-serial,id=pciserial2,chardev=serial2,bus=pcie.0,addr=0x3
- -chardev pty,id=serial3
- -device pci-serial,id=pciserial3,chardev=serial3,bus=pcie.0,addr=0x4
- -chardev pty,id=serial4-device pci-serial,id=pciserial4,chardev=serial4,bus=pcie.0,addr=0x5-chardev pty,id=serial5-device pci-serial,id=pciserial5,chardev=serial5,bus=pcie.0,addr=0x6-chardev pty,id=serial6-device pci-serial,id=pciserial6,chardev=serial6,bus=pcie.0,addr=0x7-chardev pty,id=serial7-device pci-serial,id=pciserial7,chardev=serial7,bus=pcie.0,addr=0x8-chardev pty,id=serial8-device pci-serial,id=pciserial8,chardev=serial8,bus=pcie.0,addr=0x9-chardev pty,id=serial9-device pci-serial,id=pciserial9,chardev=serial9,bus=pcie.0,addr=0x10
复制代码 测试方法:
虚拟机串口发送测试(minicom):
虚拟机内串口设备发送字符,物理机对应pty端口可以接收到字符
虚拟机串口接收测试(minicom):
物理机对应pty端口发送字符,虚拟机内串口设备可以接收到字符
虚拟机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/ttyS0
复制代码 物理机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/pts/1
复制代码 盼望结果:
虚拟机串口设备能正常接收或发送字符
测试结果:
体系串口id虚拟机串口发送测试虚拟机串口接收测试Kylin-V10-Desktop(2207)pciserial1通过通过Kylin-V10-Desktop(2207)pciserial2通过通过Kylin-V10-Desktop(2207)pciserial3通过通过Kylin-V10-Desktop(2207)pciserial4通过通过Kylin-V10-Desktop(2207)pciserial5通过通过Kylin-V10-Desktop(2207)pciserial6通过通过Kylin-V10-Desktop(2207)pciserial7通过通过Kylin-V10-Desktop(2207)pciserial8通过通过Kylin-V10-Desktop(2207)pciserial9通过通过Kylin-V10-Server(2204)pciserial1通过通过Kylin-V10-Server(2204)pciserial2通过通过Kylin-V10-Server(2204)pciserial3通过通过Kylin-V10-Server(2204)pciserial4通过通过Kylin-V10-Server(2204)pciserial5通过通过Kylin-V10-Server(2204)pciserial6通过通过Kylin-V10-Server(2204)pciserial7通过通过Kylin-V10-Server(2204)pciserial8通过通过Kylin-V10-Server(2204)pciserial9通过通过Kylin-V4-Desktop(sp4-20200728)pciserial1通过通过Kylin-V4-Desktop(sp4-20200728)pciserial2通过通过Kylin-V4-Desktop(sp4-20200728)pciserial3通过通过Kylin-V4-Desktop(sp4-20200728)pciserial4通过通过Kylin-V4-Desktop(sp4-20200728)pciserial5通过通过Kylin-V4-Desktop(sp4-20200728)pciserial6通过通过Kylin-V4-Desktop(sp4-20200728)pciserial7通过通过Kylin-V4-Desktop(sp4-20200728)pciserial8通过通过Kylin-V4-Desktop(sp4-20200728)pciserial9通过通过Kylin-V4-Server(sp4-20070420)pciserial1通过通过Kylin-V4-Server(sp4-20070420)pciserial2通过通过Kylin-V4-Server(sp4-20070420)pciserial3通过通过Kylin-V4-Server(sp4-20070420)pciserial4通过通过Kylin-V4-Server(sp4-20070420)pciserial5通过通过Kylin-V4-Server(sp4-20070420)pciserial6通过通过Kylin-V4-Server(sp4-20070420)pciserial7通过通过Kylin-V4-Server(sp4-20070420)pciserial8通过通过Kylin-V4-Server(sp4-20070420)pciserial9通过通过 4.4.2.2.3 热拔插测试
须要使用qemu monitor对PCI设备进行热拔插
chardev类型无法进行热拔插,仅能对pci-serial热拔插,故如果须要实现串口灵活热拔插,须要提前添加足额的chardev
PCI设备热拔插须要具备以下条件:
- guest体系支持,打开内核参数CONFIG_HOTPLUG_PCI_PCIE
- zcat /proc/config.gz | grep HOTPLUG
- CONFIG_HOTPLUG_PCI_PCIE=y
- CONFIG_HOTPLUG_PCI=y
- CONFIG_HOTPLUG_PCI_ACPI=y
- CONFIG_HOTPLUG_PCI_ACPI_IBM=m
- CONFIG_HOTPLUG_PCI_CPCI=y
- CONFIG_HOTPLUG_PCI_SHPC=y
- # 或者在/boot/config-{uname -r}
- cat /boot/config-5.15.0-122-generic | grep HOTPLUG
- CONFIG_HOTPLUG_PCI_PCIE=y
- CONFIG_HOTPLUG_PCI=y
- CONFIG_HOTPLUG_PCI_ACPI=y
- CONFIG_HOTPLUG_PCI_ACPI_IBM=m
- CONFIG_HOTPLUG_PCI_CPCI=y
- CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
- CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
- CONFIG_HOTPLUG_PCI_SHPC=y
复制代码 - guest体系支持,有pciehp、acpiphp、pci_hotplug驱动并加载
- lsmod | grep pciehp
- lsmod | grep acpiphp
- lsmod | grep pci_hotplug
- # 有些系统这些模块编译到内核里面了,modinfo才能看到
- modinfo pciehp
- name: pciehp
- filename: (builtin)
- parm: pciehp_poll_mode:Using polling mechanism for hot-plug events or not (bool)
- parm: pciehp_poll_time:Polling mechanism frequency, in seconds (int)
- modinfo acpiphp
- name: acpiphp
- filename: (builtin)
- license: GPL
- file: drivers/pci/hotplug/acpiphp
- description: ACPI Hot Plug PCI Controller Driver
- author: Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>, Matthew Wilcox <willy@infradead.org>
- parm: disable:disable acpiphp driver (bool)
- modinfo pci_hotplug
- name: pci_hotplug
- filename: (builtin)
- parm: debug_acpi:Debugging mode for ACPI enabled or not (bool)
- parm: debug:Debugging mode enabled or not (bool)
复制代码 - PCI设备不能挂载在部分总线设备如:Root Bus:pcie.0、pxb-pcie
一般情况aarch64架构下是挂载到pcie-root-port下
由于pcie-root-port本身不支持热拔插,以是须要准备多个pcie-root-port才能支持多设备热拔插
详情参考这份文档:https://github.com/qemu/qemu/blob/master/docs/pcie.txt
- 虚拟机类型须要为virt(aarch64)或者q35(x86)
由于银河麒麟aarch64架构的体系并未支持相关驱动模块,PCIE热拔插功能不支持
4.4.3 virtio-serial
4.4.3.1 修改方案
暂不处置惩罚$MAX_SERIAL_PORTS的最大4个串口限制
- # serial devices
- for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
- my $path = $conf->{"serial$i"} or next;
- if ($path eq 'socket') {
- my $socket = "/var/run/qemu-server/${vmid}.serial$i";
- push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server=on,wait=off";
- # On aarch64, serial0 is the UART device. QEMU only allows
- # connecting UART devices via the '-serial' command line, as
- # the device has a fixed slot on the hardware...
- if ($arch eq 'aarch64') {
- if ($i == 0) {
- push @$devices, '-serial', "chardev:serial$i";
- push @$devices, '-device', "virtio-serial,id=virtioserial";
- } else {
- push @$devices, '-device', "virtserialport,bus=virtioserial.0,chardev=serial$i,id=virtserialport.$i,name=virtserialport.$i";
- }
- } else {
- push @$devices, '-device', "isa-serial,chardev=serial$i";
- }
- } else {
- die "no such serial device\n" if ! -c $path;
- push @$devices, '-chardev', "serial,id=serial$i,path=$path";
- push @$devices, '-device', "isa-serial,chardev=serial$i";
- }
- }
复制代码 4.4.3.2 测试验证
为了方便测试,验证时chardev使用pty
4.4.3.2.1 PVE默认最大数量测试(1个UART+3个virtserialport)
测试参数:
- -chardev socket,id=serial0,path=/var/run/qemu-server/${vmid}.serial0,server=on,wait=off
- -serial chardev:serial0
- -device virtio-serial,id=virtioserial,bus=pcie.0,addr=0x2
- -chardev pty,id=serial1
- -device virtserialport,bus=virtioserial.0,chardev=serial1,id=virtserialport.1,name=virtserialport.1
- -chardev pty,id=serial2
- -device virtserialport,bus=virtioserial.0,chardev=serial2,id=virtserialport.2,name=virtserialport.2
- -chardev pty,id=serial3
- -device virtserialport,bus=virtioserial.0,chardev=serial3,id=virtserialport.3,name=virtserialport.3
复制代码 测试方法:
虚拟机串口发送测试(minicom):
虚拟机内串口设备发送字符,物理机对应pty端口可以接收到字符
虚拟机串口接收测试(minicom):
物理机对应pty端口发送字符,虚拟机内串口设备可以接收到字符
虚拟机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/vport0p10
复制代码 物理机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/pts/1
复制代码 盼望结果:
虚拟机串口设备能正常接收或发送字符
测试结果:
体系串口id虚拟机串口发送测试虚拟机串口接收测试Kylin-V10-Desktop(2207)virtserialport.1通过通过Kylin-V10-Desktop(2207)virtserialport.2通过通过Kylin-V10-Desktop(2207)virtserialport.3通过通过Kylin-V10-Server(2204)virtserialport.1通过通过Kylin-V10-Server(2204)virtserialport.2通过通过Kylin-V10-Server(2204)virtserialport.3通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.1通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.2通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.3通过通过Kylin-V4-Server(sp4-20070420)virtserialport.1通过通过Kylin-V4-Server(sp4-20070420)virtserialport.2通过通过Kylin-V4-Server(sp4-20070420)virtserialport.3通过通过 4.4.3.2.2 数量测试(1个UART+9个virtserialport)
使用命令行参数启动虚拟机,手动修改命令行参数以跳出PVE的最大限制
测试参数:
- -chardev socket,id=serial0,path=/var/run/qemu-server/${vmid}.serial0,server=on,wait=off
- -serial chardev:serial0
- -device virtio-serial,id=virtioserial,bus=pcie.0,addr=0x2
- -chardev pty,id=serial1
- -device virtserialport,bus=virtioserial.0,chardev=serial1,id=virtserialport.1,name=virtserialport.1
- -chardev pty,id=serial2
- -device virtserialport,bus=virtioserial.0,chardev=serial2,id=virtserialport.2,name=virtserialport.2
- -chardev pty,id=serial3
- -device virtserialport,bus=virtioserial.0,chardev=serial3,id=virtserialport.3,name=virtserialport.3
- -chardev pty,id=serial4-device virtserialport,bus=virtioserial.0,chardev=serial4,id=virtserialport.4,name=virtserialport.4-chardev pty,id=serial5-device virtserialport,bus=virtioserial.0,chardev=serial5,id=virtserialport.5,name=virtserialport.5-chardev pty,id=serial6-device virtserialport,bus=virtioserial.0,chardev=serial6,id=virtserialport.6,name=virtserialport.6-chardev pty,id=serial7-device virtserialport,bus=virtioserial.0,chardev=serial7,id=virtserialport.7,name=virtserialport.7-chardev pty,id=serial8-device virtserialport,bus=virtioserial.0,chardev=serial8,id=virtserialport.8,name=virtserialport.8-chardev pty,id=serial9-device virtserialport,bus=virtioserial.0,chardev=serial9,id=virtserialport.9,name=virtserialport.9
复制代码 测试方法:
虚拟机串口发送测试(minicom):
虚拟机内串口设备发送字符,物理机对应pty端口可以接收到字符
虚拟机串口接收测试(minicom):
物理机对应pty端口发送字符,虚拟机内串口设备可以接收到字符
虚拟机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/vport0p10
复制代码 物理机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/pts/1
复制代码 盼望结果:
虚拟机串口设备能正常接收或发送字符
测试结果:
体系串口id虚拟机串口发送测试虚拟机串口接收测试Kylin-V10-Desktop(2207)virtserialport.1通过通过Kylin-V10-Desktop(2207)virtserialport.2通过通过Kylin-V10-Desktop(2207)virtserialport.3通过通过Kylin-V10-Desktop(2207)virtserialport.4通过通过Kylin-V10-Desktop(2207)virtserialport.5通过通过Kylin-V10-Desktop(2207)virtserialport.6通过通过Kylin-V10-Desktop(2207)virtserialport.7通过通过Kylin-V10-Desktop(2207)virtserialport.8通过通过Kylin-V10-Desktop(2207)virtserialport.9通过通过Kylin-V10-Server(2204)virtserialport.1通过通过Kylin-V10-Server(2204)virtserialport.2通过通过Kylin-V10-Server(2204)virtserialport.3通过通过Kylin-V10-Server(2204)virtserialport.4通过通过Kylin-V10-Server(2204)virtserialport.5通过通过Kylin-V10-Server(2204)virtserialport.6通过通过Kylin-V10-Server(2204)virtserialport.7通过通过Kylin-V10-Server(2204)virtserialport.8通过通过Kylin-V10-Server(2204)virtserialport.9通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.1通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.2通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.3通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.4通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.5通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.6通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.7通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.8通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.9通过通过Kylin-V4-Server(sp4-20070420)virtserialport.1通过通过Kylin-V4-Server(sp4-20070420)virtserialport.2通过通过Kylin-V4-Server(sp4-20070420)virtserialport.3通过通过Kylin-V4-Server(sp4-20070420)virtserialport.4通过通过Kylin-V4-Server(sp4-20070420)virtserialport.5通过通过Kylin-V4-Server(sp4-20070420)virtserialport.6通过通过Kylin-V4-Server(sp4-20070420)virtserialport.7通过通过Kylin-V4-Server(sp4-20070420)virtserialport.8通过通过Kylin-V4-Server(sp4-20070420)virtserialport.9通过通过 遗留问题:
虚拟机启动时报错:kvm: virtio-serial-bus: Guest failure in adding port 8 for device virtioserial.0
virtserialport超过7就会报错,但是串口设备能正常创建,不影响使用
4.4.3.2.3 热拔插测试
须要使用qemu monitor对virtserialport设备进行热拔插
chardev类型无法进行热拔插,仅能对virtserialport热拔插,故如果须要实现串口灵活热拔插,须要提前添加足额的chardev
测试参数:
- -monitor stdio-chardev socket,id=serial0,path=/var/run/qemu-server/${vmid}.serial0,server=on,wait=off
- -serial chardev:serial0
- -device virtio-serial,id=virtioserial,bus=pcie.0,addr=0x2
- -chardev pty,id=serial1
- -device virtserialport,bus=virtioserial.0,chardev=serial1,id=virtserialport.1,name=virtserialport.1
- -chardev pty,id=serial2
- -device virtserialport,bus=virtioserial.0,chardev=serial2,id=virtserialport.2,name=virtserialport.2
- -chardev pty,id=serial3
- -device virtserialport,bus=virtioserial.0,chardev=serial3,id=virtserialport.3,name=virtserialport.3
- -chardev pty,id=serial4
复制代码 测试方法:
热拔插USB设备(qemu monitor):
- # 拔出设备
- device_del virtserialport.1
- # 插入设备(id1)
- device_add virtserialport,bus=virtioserial.0,chardev=serial1,id=virtserialport.1,name=virtserialport.1
- # 插入设备(id4)
- device_add virtserialport,bus=virtioserial.0,chardev=serial4,id=virtserialport.4,name=virtserialport.4
复制代码 虚拟机串口发送测试(minicom):
虚拟机内串口设备发送字符,物理机对应pty端口可以接收到字符
虚拟机串口接收测试(minicom):
物理机对应pty端口发送字符,虚拟机内串口设备可以接收到字符
虚拟机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/vport0p10
复制代码 物理机发送/检察字符命令:
- # 打开字符设备
- minicom -D /dev/pts/1
复制代码 盼望结果:
热拔插USB设备后,虚拟机串口设备能正常接收或发送字符
测试结果:
体系拔出串口id插入串口id虚拟机串口发送测试虚拟机串口接收测试Kylin-V10-Desktop(2207)virtserialport.1virtserialport.1通过通过Kylin-V10-Desktop(2207)/virtserialport.4通过通过Kylin-V10-Server(2204)virtserialport.1virtserialport.1通过通过Kylin-V10-Server(2204)/virtserialport.4通过通过Kylin-V4-Desktop(sp4-20200728)virtserialport.1virtserialport.1失败(拔出后再次插入失败)失败(拔出后再次插入失败)Kylin-V4-Desktop(sp4-20200728)/virtserialport.4通过通过Kylin-V4-Server(sp4-20070420)virtserialport.1virtserialport.1失败(拔出后再次插入失败)失败(拔出后再次插入失败)Kylin-V4-Server(sp4-20070420)/virtserialport.4通过通过 4.4.4 最终选型(usb-serial)
测试结果汇总:
串口类型支持最大数量热拔插usb-serial14(PVE默认写死最大值为14,但最大值取决于USB控制器类型,某些USB控制器支持数量可能少于14)支持pci-serial/(取决于pcie的架构计划及控制器类型,pcie.0默认支持32路pcie设备)有限支持(须要guest支持、pcie控制器支持)virtio-serial单个设备最大31个端口,需求更多时可以创建多个设备有限支持(须要guest的对应驱动支持) 个人主观的选择是usb-serial,仅代表个人观点
先说说为什么不选择其他的设备类型
virtio-serial
从设备角度来说已经脱离了串口设备这样的概念,实际是只有一个Communication controller的pci设备,串口只是该设备下的端口
从驱动角度来说,virtio驱动是在内核中的,在测试中暴暴露一些老旧的体系中出现问题
pci-serial
PVE写死了pcie的设备map,增长pci-serial须要削减其他设备的数量
别的测试发现pci-serial挂载在pcie-root-port下时,须要从0地址挂载才能生效,别的地址均初始化失败(其他设备也有该问题)
末了选择了usb-serial,固然PVE写死了最大USB设备数量,串口会抢占一定的数量,总体来说还算能接受
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|