目录
jailhouse none-root cell中挂载nfs作为根目录启动linux
简介
jailhouse是一个嵌入式系统的虚拟化工具,它非常强调partition。实时性比较好,隔离的安全性也比较好。由德国西门子开发。始于2013年11月。
据说西门子有采用jailhouse技术的商业产品,但是jailhouse本身目前应用的案例看起来并不太多。https://www.youtube.com/watch?v=skIcAkXfNWQ 用jailhouse驱动马达的示例。
Jailhouse, a Linux-based partitioning hypervisor
版权:GPLv2
代码地址:
https://github.com/siemens/jailhouse
https://github.com/siemens/jailhouse-images
相关论文
Look Mum, no VM Exits! (Almost) https://arxiv.org/pdf/1705.06932.pdf 被引用25次
Deterministic memory hierarchy and virtualization for modern multi-core embedded systems http://cs-people.bu.edu/rmancuso/files/papers/virt_IDA_rtas19.pdf 被引用21次
架构
图片来源:Login | InCareer
jailhouse的应用示例
https://www.youtube.com/watch?v=skIcAkXfNWQ&ab_channel=PaoloGai
用一套系统既实现HMI,又能保证实时性。
jailhouse 官方demo
jaihouse提供了一个demo ,https://github.com/siemens/jailhouse-images 可以用于编译一整套可用的demo。
适用于多个平台。 编译过程主要参考【jailhouse】如何安装 jailhouse-images?_铭のブロゲ-CSDN博客_jailhouse
此demo可以生成多个平台所用的操作系统image。具体如下图所示:
比较通用的是qemu版本,既支持x86也支持arm64。
如果没有树莓派4B等硬件,可以先尝试运行qemu版的demo。我在x86的ubuntu 20.04系统上运行qemu。
ubuntu 18.04下默认的qemu版本是2.11,启动时会报错: 不支持-kvm-pv-ipi特性,需要修改https://github.com/siemens/jailhouse-images 项目里start-qemu.sh , 把kvm-pv-ipi删掉
我修改后x86平台用于直接运行镜像的脚本是这样的:(生成的.img镜像、内核、initrd在当前目录下)
qemu-system-x86_64 \
-drive file=./demo-image-jailhouse-demo-qemu-amd64.ext4.img,discard=unmap,if=none,id=disk,format=raw -m 1G \
-serial mon:stdio -netdev user,id=net \
-kernel ./demo-image-jailhouse-demo-qemu-amd64-vmlinuz -append 'root=/dev/sda intel_iommu=off memmap=82M$0x3a000000 vga=0x305' \
-initrd ./demo-image-jailhouse-demo-qemu-amd64-initrd.img \
-cpu host,-kvm-pv-eoi,-kvm-asyncpf,-kvm-steal-time,-kvmclock \
-smp 4 \
-enable-kvm \
-machine q35,kernel_irqchip=split \
-serial vc \
-device ide-hd,drive=disk \
-device intel-iommu,intremap=on,x-buggy-eim=on \
-device intel-hda,addr=1b.0 \
-device hda-duplex \
-device e1000e,addr=2.0,netdev=net
ARM版的命令有所不同: (此处.img名称与上面的不一样)
qemu-system-aarch64 \
-drive file=./demo-image-jailhouse-demo-qemu-arm64.ext4.img,discard=unmap,if=none,id=disk,format=raw -m 1G \
-serial mon:stdio -netdev user,id=net \
-kernel ./demo-image-jailhouse-demo-qemu-arm64-vmlinuz -append 'root=/dev/vda mem=768M' \
-initrd ./demo-image-jailhouse-demo-qemu-arm64-initrd.img \
-cpu cortex-a57 \
-smp 4 \
-machine virt,gic-version=3,virtualization=on \
-device virtio-serial-device \
-device virtconsole,chardev=con \
-chardev vc,id=con \
-device virtio-blk-device,drive=disk \
-device virtio-net-device,netdev=net
ubuntu 18.04下运行qemu可能会报 缺少“efi-e1000e.rom”,解决方法参考:x86下KVM启动Jailhouse_alex_mist的博客-CSDN博客
sudo apt install qemu-efi
cd /usr/lib/ipxe/qemu
sudo wget https://github.com/qemu/qemu/raw/master/pc-bios/efi-e1000e.rom
jailhouse的运行
raspberry 4B 版jailhouse编译后,运行起来,首先是linux操作系统启动。启动后可以执行下列命令,这些命令都保存在.bash_history中,可以通过上下键调出来。
jailhouse enable /etc/jailhouse/rpi4.cell
jailhouse console
jailhouse cell create /etc/jailhouse/rpi4-inmate-demo.cell
jailhouse cell load inmate-demo /usr/libexec/jailhouse/demos/gic-demo.bin
jailhouse cell start inmate-demo
jailhouse cell stats inmate-demo
jailhouse cell destroy inmate-demo
jailhouse cell linux /etc/jailhouse/rpi4-linux-demo.cell \
/boot/vmlinuz* \
-d /etc/jailhouse/dts/inmate-rpi4.dtb \
-i /usr/libexec/jailhouse/demos/rootfs.cpio \
-c "console=ttyS0,115200 ip=192.168.19.2"
ssh 192.168.19.2
jailhouse disable
运行linux-demo.cell, CPU被分走2个,现在只能看到2个CPU。rpi4本身有4个CPU
root@demo:~# jailhouse cell linux /etc/jailhouse/rpi4-linux-demo.cell \
> /boot/vmlinuz* \
> -d /etc/jailhouse/dts/inmate-rpi4.dtb \
> -i /usr/libexec/jailhouse/demos/rootfs.cpio \
> -c "console=ttyS0,115200 ip=192.168.19.2"
root@demo:~# cat /proc/cpuinfo
processor : 0
BogoMIPS : 108.00
Features : fp asimd evtstrm crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd08
CPU revision : 3
processor : 1
BogoMIPS : 108.00
Features : fp asimd evtstrm crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd08
CPU revision : 3
Hardware : BCM2835
Revision : b03114
Serial : 10000000c51d861b
Model : Raspberry Pi 4 Model B Rev 1.4
jailhouse的日志输出
root@demo:~# jailhouse console
Initializing Jailhouse hypervisor v0.12 (0-g92db71f2-dirty) on CPU 0
Code location: 0x0000ffffc0200800
Page pool usage after early setup: mem 39/994, remap 0/131072
Initializing processors:
CPU 0... OK
CPU 2... OK
CPU 1... OK
CPU 3... OK
Initializing unit: irqchip
Initializing unit: ARM SMMU v3
Initializing unit: PVU IOMMU
Initializing unit: PCI
Adding virtual PCI device 00:00.0 to cell "Raspberry-Pi4"
Adding virtual PCI device 00:01.0 to cell "Raspberry-Pi4"
Page pool usage after late setup: mem 61/994, remap 5/131072
Activating hypervisor
Adding virtual PCI device 00:00.0 to cell "rpi4-linux-demo"
Shared memory connection established, peer cells:
"Raspberry-Pi4"
Adding virtual PCI device 00:01.0 to cell "rpi4-linux-demo"
Shared memory connection established, peer cells:
"Raspberry-Pi4"
Created cell "rpi4-linux-demo"
Page pool usage after cell creation: mem 76/994, remap 5/131072
Cell "rpi4-linux-demo" can be loaded
Started cell "rpi4-linux-demo"
jailhouse none-root cell中挂载nfs作为根目录启动linux
jailhouse 中的虚拟机guest os运行在cell中,默认是无法访问磁盘的,要想将某个文件夹作为根目录启动虚拟机,可以使用nfs技术。
在宿主机中安装nfs server,将根目录下的文件放在nfs对外提供服务的目录中,启动guest os时,把nfs的参数传递给内核。
nfs的相关服务安装和配置可以参照 Debian Linux安装NFS_起一个好听的名字的博客-CSDN博客_debian nfs
jailhouse启动 inmate 的命令如下: 假设已有nfs目录位于/srv/nfs/rootfs1
jailhouse cell linux /etc/jailhouse/rpi4-linux-demo.cell /boot/vmlinuz* \
-d /etc/jailhouse/dts/inmate-rpi4.dtb \
-i /srv/nfs/initrd.img \
-c " root=/dev/nfs nfsroot=192.168.19.1:/srv/nfs/rootfs1 ip=192.168.19.2:192.168.19.1:192.168.19.1:255.255.255.0::eth0:off init=/linuxrc console=ttyS0,115200"
上面的命令如果写成 console=jailhouse,则虚拟机启动的日志,像linux启动时候的打印信息会输出到jailhouse的虚拟控制台上,可以通过 jailhouse console 查看。
注意事项
不要使用vmware 虚拟出的ubuntu来跑jailhouse,因为vmware虚拟出来的CPU对VMX的支持不全面,参见
https://groups.google.com/g/jailhouse-dev/c/qMWgyfuWjVg/m/6pJYHxJtAAAJ
看不了这个网页的,我截个图
主要是 vmware虚拟化的时候VMX功能存在缺陷,不符合jailhouse的要求。导致运行jailhouse enable的时候报错
JAILHOUSE_ENABLE: Input/output error
jailhouse的配置
树莓派运行2个linux inmates的配置文件 可以从这下载 jailhouse-two-inmates.zip-Linux文档类资源-CSDN下载
1.cell配置文件简介
jailhouse enable /etc/jailhouse/rpi4.cell
jailhouse cell create /etc/jailhouse/rpi4-inmate-demo.cell
jailhouse的配置文件分2类,
首先是root cell的配置文件,用于配置主机的相应环境。
另一类是none root cell的配置文件,描述这个cell所拥有的CPU,内存等资源情况。
jailhouse的代码比较简单,核心代码只有2万行,对于配置文件依赖特别重,配置不正确会导致虚拟机无法正常运行或系统直接死机。
但是jailhouse的文档中最关键的关于cell配置文件的说明文档中的内容是“ to be written.” 已经从2016年 to be written到现在了。给理解jailhouse的人带来了巨大的困难和障碍,“鸡儿耗死”绝非浪得虚名。
目前只能上作者的开发社区提问获取一些技术支持https://groups.google.com/g/jailhouse-dev (需要科学上网)。
2. cell文件的生成过程
jailhouse运行时用到许多的.cell文件,.cell文件是用.c文件生成的。
e1000-demo.c文件为例,里面定义了一个名为config的变量,并赋值。在Makefile中,这些.c文件被gcc编译生成.o,之后再用objcopy命令把ELF的相关格式去掉,变成RAW的二进制内容。供jailhouse加载。
objcopy --remove-section=.note.gnu.property -O binary *.o *.cell
这样的命令把ELF格式的obj文件直接转换成 raw的二进制文件,即.cell文件。
2. .c配置文件内容解析
.cpu用的是二进制位的表示法,可以写成16进制,也可以写成2进制, 比如: 0x4, 也可以写成0b100, 意思是用第3个CPU核,编号为2(编号从右往左依次是 0, 1 ,2 )。
还有.mem_regions .irqchips .pci_devices 非常复杂,此处不展开讲,想了解更多可以参考 https://github.com/CJTSAJ/jailhouse-learning
#include <jailhouse/types.h>
#include <jailhouse/cell-config.h>
struct {
struct jailhouse_cell_desc cell;
__u64 cpus[1];
struct jailhouse_memory mem_regions[3];
struct jailhouse_pio pio_regions[4];
struct jailhouse_pci_device pci_devices[1];
struct jailhouse_pci_capability pci_caps[1];
} __attribute__((packed)) config = {
.cell = {
.signature = JAILHOUSE_CELL_DESC_SIGNATURE,
.revision = JAILHOUSE_CONFIG_REVISION,
.name = "e1000-demo",
.flags = JAILHOUSE_CELL_PASSIVE_COMMREG |
JAILHOUSE_CELL_VIRTUAL_CONSOLE_PERMITTED,
.cpu_set_size = sizeof(config.cpus),
.num_memory_regions = ARRAY_SIZE(config.mem_regions),
.num_irqchips = 0,
.num_pio_regions = ARRAY_SIZE(config.pio_regions),
.num_pci_devices = ARRAY_SIZE(config.pci_devices),
.num_pci_caps = ARRAY_SIZE(config.pci_caps),
.console = {
.type = JAILHOUSE_CON_TYPE_8250,
.flags = JAILHOUSE_CON_ACCESS_PIO,
.address = 0x3f8,
},
},
.cpus = {
0x4,
},
作者提供了一个教程,可以了解一些jailhouse进行PCI隔离的方法。(文档2016年的,有一点旧,arm部分不太新) https://events.static.linuxfound.org/sites/events/files/slides/ELCE2016-Jailhouse-Tutorial.pdf
QEMU中实现jailhouse的PCI设备隔离(x86)
jailhouse号称可以实现硬件partition,不光是CPU和内存的隔离,还包括PCI设备的隔离。
可惜jailhouse的相关文档太少。在jailhouse-images的qemu DEMO中,可以进行PCI设备隔离DEMO,将qemu虚拟出的e1000网卡隔离到jailhouse的inmate中运行。
需要进行:
1.修改configs/x86/目录下qemu-x86.c和 linux-x86-demo.c两个配置文件。
qemu-x86.c中注意e1000网卡的设备号要与系统对应,不能写错
linux-x86-demo.c中添加这个宏定义,因为后面用到了。
#define CONFIG_QEMU_E1000E_ASSIGNMENT 1
2. 可能需要版本高一点的QEMU,我用的是qemu-6.0.0,估计qemu-4.2.1以上都可以
更多相关的配置文件可参考下列链接: https://groups.google.com/g/jailhouse-dev/c/lSwAquo3obM
后续有机会可以更新更多内容。
参考论文
Jailhouse的内部实现
http://hercules2020.eu/wp-content/uploads/2016/04/D4.5_MultiOS_Integration_Final.pdf
jailhouse特性说明
https://groups.google.com/g/jailhouse-dev/c/hFYjp7Wx1e0/m/86-9XPcyCQAJ
提出将开源的Hypervisor嵌入式虚拟化实时系统管理程序Jailhouse应用到工业机器人控制系统的研究方案,用来提高工业机器人控制系统的实时响应性能。对比RTOS Only、Linux RT和嵌入式虚拟化实时系统实时性能,实验结果表明,虚拟化实时系统在重负载条件下实时性能相对于Linux RT有了很大程度的提高。