QNX800 virtual machine
简介
本文通过了在ubuntu使用了多种方式创建和运行qnx800 vm(Virtual Machine, 虚拟机) ,并比较了这几种方式的差异点。
方式1:通过mkqnximage
快速创建并使用qemu-system_x84_64
运行该qnx800 vm
方式2:通过Generic x86_64
BSP编译出image,并使用qemu-system_x84_64
运行该qnx800 vm
方式3:通过BSP_aarch64_qemu_virt
BSP编译出image,并使用qemu-system-aarch64
运行qnx800 vm
方式 | 工具 | 优势 | 劣势 |
---|---|---|---|
1 | mkqnximage | 不用配置,快速编译出相关功能的qnx800 vm,可以进行快速验证 | buildfile文件不方便自定义 |
2 | Generic x86_64 BSP | 可以根据自己的需求配置buildfile文件和启动程序 | 有一定的门槛,需要对BISO启动,QNX启动和buildfile机制熟悉 |
3 | BSP_aarch64_qemu_virt | 同上 | 同上 |
试验环境
Host
: Ubuntu 22.04.3 LTSQNX Version
: SDP800, 8.0 Build141 - November 27.2023BSP for Generic x86_64
: 8.0 Build 50 - November 20, 2023,BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50.zipBSP for Raspberry Pi BCM2711 R-PI4
: 8.0 Build 198 - June 18, 2024,BSP_raspberrypi-bcm2711-rpi4_br-hw-rel_be-800_SVN999745_JBN198.zipqemu-system-x86_64
:qemu-system-aarch64
:
mkqnximage创建并运行qnx800 vm
QNX提供了一个mkqnximage
的工具用于创建运行与X86平台的qnx vm image,该image支持在Vmware
, VirtualBox
, qemu
等虚拟机工具上运行。
1.创建qnx800 vm image
使用以下方式在ubuntu下快速生成一个可用qemu运行的qnx800 vm image。
mkdir qnx800_qemu_base_x86
cd qnx800_qemu_base_x86
source ~/qnx800/qnxsdp-env.sh
mkqnximage --type=qemu --arch=x86_64 --build
2.运行qnx800 vm
之后可以使用mkqnximage --run
运行qnx800 vm。
mkqnximage --run
这个命令相当于启动了qemu-system-x86_64
程序,并指定相关的一些配置,这些配置来源于mkqnximage
创建QNX VM image时候传入的options
参数,实际运行的命令如下:
qemu-system-x86_64 -smp 2 --cpu max -m 1G -drive file=output/disk-qemu.vmdk,if=ide,id=drv0 -netdev bridge,br=br0,id=net0 -device virtio-net-pci,netdev=net0,mac=52:54:00:50:16:3c -pidfile output/qemu.pid -nographic -kernel output/ifs.bin -serial mon:stdio -object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-pci,rng=rng0 -nographic
各个参数的定义如下:(注意,在启动qnx800 VM需要加上--cpu max
的参数,但是启动qnx710 VM就不需要)
○ -smp 2 --cpu max
§ Specifies 2 CPU cores for the guest.
§ The --cpu max enables the most feature-rich virtual CPU supported by QEMU on the host.
○ -m 1G
§ Allocates 1 GB of memory for the guest.
○ -drive file=output/disk-qemu.vmdk,if=ide,id=drv0
§ Attaches a disk image (output/disk-qemu.vmdk) using the IDE interface.
§ id=drv0 assigns an identifier to the drive.
○ -netdev bridge,br=br0,id=net0
§ Connects the guest’s networking through the host bridge br0.
§ id=net0 assigns an identifier to this network device.
○ -device virtio-net-pci,netdev=net0,mac=52:54:00:50:16:3c
§ Adds a VirtIO network device connected to net0.
§ Assigns the specified MAC address to the guest’s network interface.
○ -pidfile output/qemu.pid
§ Stores the QEMU process ID in output/qemu.pid.
○ -nographic
§ Disables graphical output. The guest runs entirely in the terminal.
○ -kernel output/ifs.bin
§ Specifies the kernel image (output/ifs.bin) to boot the guest.
○ -serial mon:stdio
§ Configures the serial port to be accessible via the terminal for debugging.
○ -object rng-random,filename=/dev/urandom,id=rng0
§ Adds an entropy source (/dev/urandom) for the guest.
§ id=rng0 assigns an identifier to the RNG object.
○ -device virtio-rng-pci,rng=rng0
§ Adds a VirtIO RNG device, linked to the rng0 entropy source.
qnx800 VM启动的过程如下:
3.修改配置
上述创建的vm image使用的默认配置,可以通过修改local/options
的文件来修改配置,然后执行重新生成vm image就可以了。
mkqnximage --clean
vi local/options
mkqnximage --options
mkqnximage --build
4.Host通过ssh访问qnx800 vm
在启动qnx800 vm的时候,qemu-system-x86_64
会在host端创建一个br0
的网卡给qnx800 vm,只要保证这两个网卡在同一个网段即可。
Host端br0网卡:
qnx800 vm网卡:
5.单独编译ifs.bin
当使用创建好的qnx800 vm image后,如果有需要对其中的某些配置做一个简单的修改而不想要重新创建整个vm image,那么可以单独修改output/build/
目录中的.build
或者启动相关的脚本。
之后重新执行mkifs -o output output/build/ifs.build output/ifs.bin
编译出ifs.bin
即可。
6.单独编译disk-qemu
目前是做不到的,生成的disk-qemu
是包含一个只读的system
分区,一个可读写的data
分区。
mkqnximage 原理
mkqnximage
是一个放在~/qnx800/host/common/bin/
的脚本,比如执行mkqnximage --build
创建一个新的qnx800 VM,那么就会执行以下的脚本片段:
# Turn the assorted partitions into the final disk image and then invoke any post build scripts
function build_disk()
{
echo Building disk
if ${TOOL_DIR}/builddisk; then
for script in "${POST_BUILD_SCRIPTS[@]}"; do
$script postbuild
done
else
do_run=(0)
do_getip=(0)
failed=1
fi
}
function build_image()
{
create_defines
opt_script_configure
copy_snippets
generate_shadow_file
read_extra_options
generate_input_files
build_disk
# OPT_REPOS has been expanded for the benefit of option scripts so return to its former value
OPT_REPOS="$SAVED_OPT_REPOS"
show_options brief
echo -e '\nFor full list of options, run "mkqnximage --options"'
}
当使用mkqnximage
相关的操作时,实际上会根据传入的参数来执行一系列预设好的动作。
这些预设好的动作已都在~/qnx800/host/common/mkqnximage/
目录各种配置文件和脚本中定义好了,不同的参数选择执行不同的配置或者脚本。
通过Generic x86_64 BSP编译出x86_64 vm image
1.下载Generic x86_64
BSP
从QNX软件中心下载Generic x86_64
的源码
2.添加串口支持
修改使用8250 debug port做为shell,这样子能保证我们能进行串口的调试,patch如下:
index 6d8a06aa..44c1b411 100644
--- a/bsp/BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50/images/generic-bios/x86_64-generic-bios.build
+++ b/bsp/BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50/images/generic-bios/x86_64-generic-bios.build
@@ -8,7 +8,8 @@
[+keeplinked]
[image=0x2000000]
[virtual=x86_64,bios +compress] boot = {
- startup-x86
+ # (Default) If you want to use the 8250 debug port, uncomment the following line:
+ startup-x86 -D8250..115200 -zz
PATH=/proc/boot:/sbin:/bin:/usr/bin:/usr/sbin:/usr/libexec LD_LIBRARY_PATH=/proc/boot:/lib:/usr/lib:/lib/dll:/lib/dll/pci procnto-smp-ins
}
@@ -60,6 +61,7 @@
waitfor /dev/ser1
+
############################################################################################
## Block driver
############################################################################################
@@ -173,6 +175,9 @@
############################################################################################
reopen /dev/con1
display_msg "Starting shell ..."
+ # Note: If you want to use the 8250 serial debug port, uncomment the following line
+ # and change the device name to the actual port name:
+ TERM=qansi on -t /dev/ser1 /bin/sh
[+session] ksh &
}
3.添加EIDE磁盘
通过在qnx虚拟机执行pci-tool
查看当前识别到的设备,发现识别到的IDE
磁盘为vid/did: 8086/7010
,与x86_64-generic.build
的文件指定的不一致,因此需要为其添加一个EIDE_8086_7010=8086/7010
的设备。
这个磁盘加载上后,就可以看到disk.img
对应的分区,然后将其挂载出来即可。
--- a/bsp/BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50/images/generic-bios/x86_64-generic-bios.build
+++ b/bsp/BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50/images/generic-bios/x86_64-generic-bios.build
@@ -862,6 +862,7 @@ STD_NULL=/dev/null
## supported list for the EIDE block devices
EIDE_8086_7111=8086/7111
+EIDE_8086_7010=8086/7010
## supported list for the SDMMC block devices
SDMMC_8086_5acc=8086/5acc
@@ -891,11 +892,15 @@ then
fi
# check if there is the EIDE device in the list
-if grep $EIDE_8086_7111 $PCI_DEVICE_LIST > $STD_NULL
+if grep $EIDE_8086_7111 $PCI_DEVICE_LIST > $STD_NULL || \
+ grep $EIDE_8086_7010 $PCI_DEVICE_LIST > $STD_NULL
then
echo "Starting EIDE block driver ..."
devb-eide cam pnp disk name=eide
waitfor /dev/eide0 3
+ echo "Starting mount qnx6 partition to /bios_boot and /qnx_data ..."
+ mount -t qnx6 /dev/eide0t177 /bios_boot
+ mount -t qnx6 /dev/eide0t179 /qnx_data
fi
# check if there is the SDMMC device in the list
4.添加网卡设备:
可以通过io-sock -d vtnet_pci
创建一个VirtIO PCI 网卡,然后启动qemu的时候添加与之对用的网卡名为br0
,那么QNX VM就会有一个与之对应的vtnet0
网卡。
-netdev bridge,br=br0,id=net0 \
-device virtio-net-pci,netdev=net0,mac=52:54:00:40:e4:25
diff --git a/bsp/BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50/images/generic-bios/x86_64-generic-bios.build b/bsp/BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50/images/generic-bios/x86_64-generic-bios.build
index e4a6a246..cd4f6aa6 100644
--- a/bsp/BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50/images/generic-bios/x86_64-generic-bios.build
+++ b/bsp/BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50/images/generic-bios/x86_64-generic-bios.build
@@ -89,7 +89,7 @@
## Network driver
############################################################################################
display_msg "Starting networking ..."
- io-sock -m phy -d vmx -m pci -d em -d ix -d re -m usb -d axe -d axge -d cdce -d smsc
+ io-sock -m phy -d vmx -m pci -d em -d ix -d re -m usb -d vtnet_pci
############################################################################################
@@ -379,6 +379,7 @@ fi
/etc/netconfig=${QNX_TARGET}/etc/netconfig
/etc/protocols=${QNX_TARGET}/etc/protocols
/etc/services=${QNX_TARGET}/etc/services
+/lib/dll/devs-vtnet_pci.so=devs-vtnet_pci.so
################################################################################################
## Remote_debug
启动qnx800 vm后,能看到qnx800 vm中的vtnet0
网卡:
vtnet0: flags=8863<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=4c07bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,VLAN_HWTSO,LINKSTATE,TXCSUM_IPV6>
ether 52:54:00:40:e4:25
inet6 fe80::ae3e:2bbc:2918:d231%vtnet0 prefixlen 64 scopeid 0x5
inet 169.254.28.54 netmask 0xffff0000 broadcast 169.254.255.255
media: Ethernet autoselect (10Gbase-T <full-duplex>)
status: active
nd6 options=1<PERFORMNUD>
host端能看到一个br0
网卡
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.31.1.1 netmask 255.255.255.0 broadcast 172.31.1.255
inet6 fe80::68:dfff:fe7b:de98 prefixlen 64 scopeid 0x20<link>
ether 66:79:62:9a:f8:29 txqueuelen 1000 (Ethernet)
RX packets 90 bytes 22824 (22.8 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 35 bytes 4853 (4.8 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
5.编译BSP
source ~/qnx800/qnxsdp-env.sh
make -C bsp/BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50/
make -C bsp/BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50/images/generic-bios/ disk_image
之后在BSP_x86_64_br-hw-rel_be-800_SVN989189_JBN50/images/generic-bios/
目录下会生成运行于x86_64架构上bios启动所需的disk.img
镜像,这个镜像的布局如下,具体的布局是由disk.cfg
配置文件决定的。
各个image和disk.cfg
配置信息的关系如下:
6.启动qemu: 这个命令与mkqnximage
启动qemu的命令一致
qemu-system-x86_64 -smp 2 --cpu max -m 1G \
-drive file=./disk.img,if=ide,id=drv0 \
-netdev bridge,br=br0,id=net0 \
-device virtio-net-pci,netdev=net0,mac=52:54:00:40:e4:25 \
-serial mon:stdio -object rng-random,filename=/dev/urandom,id=rng0 \
-device virtio-rng-pci,rng=rng0 \
-nographic
通过BSP_aarch64_qemu_virt BSP编译出aarch64 vm image
# QEMU Virtual Machine BSP for QNX
This is a QNX minimal BSP for AARCH64 QEMU VIRT machine.
## How to use
Checkout the source code under QNX SDP BSP directory (tested under SDP 8.0.0) then execute:
cd qemu-virt
source ${QNX_SDP_DIR}/qnxsdp-env.sh
make
make run
The "make run" will start the QEMU and run QNX on an AARCH64 machine called VIRT.
You need to install qemu-system-aarch64 before run it. Tested under qemu-system-aarch64 8.2 but should work for other versions.
## Networking
When you execute "make run", it uses QEMU user networking mode, which can access from QNX(guest OS) to outside, but cannot access from outside to QNX by default (you can do it by using port forwarding) .
Ping 10.0.2.2(represents your host) is working but cannot ping outside world, if you need to do ping test, then execute "make sudo-run".
If you need more flexible networking, please execute "make run-tap", it will use QEMU tap networking mode, need sudo permision although.
More information about QEMU networking mode: https://wiki.qemu.org/Documentation/Networking
## TODO
The PCI is not available yet causes massive devices/drivers cannot be used.