嵌入式虚拟化平台jailhouse踩坑笔记

目录

简介

相关论文

架构

jailhouse的应用示例

jailhouse 官方demo

jailhouse的运行

jailhouse  none-root cell中挂载nfs作为根目录启动linux

注意事项

jailhouse的配置

1.cell配置文件简介

2.  cell文件的生成过程

2.  .c配置文件内容解析

QEMU中实现jailhouse的PCI设备隔离(x86)

参考论文


简介

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次

架构

嵌入式虚拟化平台jailhouse踩坑笔记_第1张图片

图片来源:Login | InCareer

jailhouse的应用示例

https://www.youtube.com/watch?v=skIcAkXfNWQ&ab_channel=PaoloGai

用一套系统既实现HMI,又能保证实时性。

嵌入式虚拟化平台jailhouse踩坑笔记_第2张图片

jailhouse 官方demo

jaihouse提供了一个demo ,https://github.com/siemens/jailhouse-images 可以用于编译一整套可用的demo。

适用于多个平台。 编译过程主要参考【jailhouse】如何安装 jailhouse-images?_铭のブロゲ-CSDN博客_jailhouse

此demo可以生成多个平台所用的操作系统image。具体如下图所示:

嵌入式虚拟化平台jailhouse踩坑笔记_第3张图片

比较通用的是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删掉

嵌入式虚拟化平台jailhouse踩坑笔记_第4张图片

我修改后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

看不了这个网页的,我截个图

嵌入式虚拟化平台jailhouse踩坑笔记_第5张图片

主要是 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 (需要科学上网)。

嵌入式虚拟化平台jailhouse踩坑笔记_第6张图片

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 
#include 

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有了很大程度的提高。

你可能感兴趣的:(linux,jailhouse,jailhouse,嵌入式,hypervisor,嵌入式虚拟化)