• 3.7.1. Jailhouse Hypervisor
• 3.7.1.1. Keystone3 Jailhouse演示
• 3.7.2. Docker Linux容器运行时
• 3.7.2.1. 概述
• 3.7.2.2. 探索处理器SDK中的Docker
• 3.7.2.2.1. 启动Docker文件系统
• 3.7.2.2.2. 配置Docker守护程序
• 3.7.2.2.3. Docker Hello World
• 3.7.2.3. Docker参考
3.7.1. Jailhouse Hypervisor
概述
Jailhouse是一个运行裸机二进制文件的静态分区管理程序。它与Linux紧密合作。Jailhouse不会模仿不存在的资源。它只是将现有的硬件资源分割成单独的“单元”,这些单元完全专用于名为“inmates”的客户软件程序。其中一个单元运行Linux操作系统,被称为“根单元”。其他单元在创建时从根单元借用CPU和设备。
上图显示了系统上的jailhouse a)启用jailhouse之前;b)启用jailhouse之后;c)创建单元格之后。
Jailhouse由三个部分组成:内核模块、虚拟机监控程序固件和工具,用户可以使用它们来启用虚拟机监控程序、创建单元格、加载inmate二进制文件、运行和停止它。Jailhouse是异步多处理(AMP)体系结构的一个例子。当我们在带有ARM CPU集群的设备上引导Linux时,Linux使用所有的内核。在我们启用hypervisor之后,它将Linux移动到根单元。根单元仍然使用所有CPU核。当我们创建一个新单元时,hypervisor会调用cpu_down()让一些cpu内核脱机。新单元将在单元配置文件中使用这些CPU核心和专用于该单元的硬件资源。
Jailhouse是一个开源项目,可以在https://github.com/siemens/jailhouse.
3.7.1.1 Keystone3 Jailhouse演示
这个演示的目标是对CPU内核进行分区,并使用ramfs根文件系统运行Linux内核的第二个实例。内核将使用辅助UART为用户提供一个登录shell。
步骤1:主机设置
因为我们将运行Linux内核的两个实例,所以需要两个终端。将一个终端连接到主UART(例如/dev/ttyUSB0),另一个连接到辅助UART(例如/dev/ttyUSB1)。
步骤2:配置U-Boot
默认的引导配置不为Jailhouse管理程序或inmates保留任何资源。然而,根文件系统包含一个设备树覆盖层,它将挖掘出这些需求。必须配置U-Boot才能应用此设备树覆盖。
对于这一步,我们将使用连接到主UART的终端。
我们需要将jailhouse设备树覆盖添加到覆盖列表中,以应用于u-boot。这由环境变量“overlay_files”控制。处理器SDK Linux J721e附带了现成的uenv.txt,该变量被设置为定义用于运行jailhouse演示的DTBO文件列表。请参阅如何更改dtb文件一节,以获得有关这方面的更多细节。
步骤3:启动Linux并登录
现在引导内核并登录到shell:
=> boot
...
_____ _____ _ _
| _ |___ ___ ___ ___ | _ |___ ___ |_|___ ___| |_
| | _| .'| . | . | | __| _| . | | | -_| _| _|
|__|__|_| |__,|_ |___| |__| |_| |___|_| |___|___|_|
|___| |___|
Arago Project http://arago-project.org am65xx-evm ttyS2
Arago 2019.07 am65xx-evm ttyS2
am65xx-evm login: root
root@am65xx-evm:~#
步骤4:运行Jailhouse linux-demo
jailhouse包包含一个脚本,用于运行Linux inmate演示。这个脚本结合了典型的jailhouse命令,以简化第一次运行演示的过程。该脚本执行以下步骤。
root@am65xx-evm:~# /usr/share/jailhouse/linux-demo.sh
Initializing Jailhouse hypervisor v0.10 (152-g6dce20f) on CPU 2
Code location: 0x0000ffffc0200800
Page pool usage after early setup: mem 39/991, remap 0/131072
Initializing processors:
CPU 2... OK
CPU 3... OK
CPU 1... OK
CPU 0... OK
Initializing unit: irqchip
Initializing unit: PVU IOMMU
Initializing unit: ARM SMMU v3
Initializing unit: PCI
Adding virtual PCI device 00:00.0 to cell "k3-am654-idk"
Initializing unit: regmap
Page pool usage after late setup: mem 71/991, remap 144/131072
Activating hypervisor
[ 63.162406] jailhouse: CONFIG_OF_OVERLAY disabled
[ 63.167261] jailhouse: failed to add virtual host controller
[ 63.172978] The Jailhouse is opening.
[ 63.251354] CPU2: shutdown
[ 63.254071] psci: CPU2 killed.
[ 63.303312] CPU3: shutdown
[ 63.306033] psci: CPU3 killed.
Adding virtual PCI device 00:00.0 to cell "k3-am654-idk-linux-demo"
Shared memory connection established: "k3-am654-idk-linux-demo" <--> "k3-am654-idk"
Created cell "k3-am654-idk-linux-demo"
Page pool usage after cell creation: mem 93/991, remap 144/131072
[ 63.355266] Created Jailhouse cell "k3-am654-idk-linux-demo"
Cell "k3-am654-idk-linux-demo" can be loaded
Started cell "k3-am654-idk-linux-demo"
root@am65xx-evm:~#
现在,在辅助终端上,验证inmate内核是否使用ramfs引导。还要注意,根单元格和inmaite使用的/dev/ttySX编号可能匹配,也可能不匹配。
_____ _____ _ _
| _ |___ ___ ___ ___ | _ |___ ___ |_|___ ___| |_
| | _| .'| . | . | | __| _| . | | | -_| _| _|
|__|__|_| |__,|_ |___| |__| |_| |___|_| |___|___|_|
|___| |___|
Arago Project http://arago-project.org am65xx-evm /dev/ttyS1
Arago 2019.07 am65xx-evm /dev/ttyS1
am65xx-evm login: root
root@am65xx-evm:~# mount
rootfs on / type rootfs (rw,size=230400k,nr_inodes=3600)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
configfs on /sys/kernel/config type configfs (rw,relatime)
devtmpfs on /dev type devtmpfs (rw,relatime,size=230400k,nr_inodes=3600,mode=755
)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /var/volatile type tmpfs (rw,relatime,size=51200k)
devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620,ptmxmode=000)
Jailhouse内部
本节给出了一些Jailhouse的细节和所需的内核修改。
Linux内核修改
为了运行hypervisor本身和inmates,jailhouse需要内核dtb中的额外节点。有关所需节点或修改的详细信息,请参阅特定于平台的监狱设备树或DT覆盖。
内存保留
Linux内核必须为jailhouse管理程序和inmate保留一些内存。这个内存必须静态保留。下面的示例显示为hypervisor保留16MB物理内存,为inmate保留16MB物理内存。
/ {
reserved-memory {
jailhouse: jailhouse@ef000000 {
reg = <0x0 0xef000000 0x0 0x1000000>;
no-map;
status = "okay";
};
jh_inmate: jh_inmate@ee000000 {
reg = <0x0 0xee000000 0x0 0x1000000>;
no-map;
status = "okay";
};
};
};
硬件模块预留
Jailhouse是一个分区管理程序。这意味着硬件外围设备独占控制其中一个单元。Jailhouse cell config文件定义了这个所有权,以确保对外围设备的所有访问在不同的单元之间是隔离的。进入jailhouse外的任何外围设备都将被视为违规行为,jailhouse将把这个cell停在那里。为了确保Linux只使用指定的外设,我们可以禁用其他单元所拥有的外设。
以下节点描述如何在根单元设备树中禁用设备的示例。
/*禁用inamte单元使用的uart*/
&main_uart1 {
status = "disabled";
};
/*禁用inamte cell使用的emmc实例*/
&main_sdhci0 {
status = "disabled";
};
根单元配置
当hypervisor被启用时,它为Linux创建一个单元并将其移动到该单元。这个细胞被称为“root-cell”。单元配置为“.c”文件,该文件被编译为特殊的二进制格式“.cell”文件。hypervisor使用“cell”文件创建一个单元格。单元配置描述单元将使用的内存区域及其属性
:
.mem_regions = {
/* OCMCRAM */ {
.phys_start = 0x40300000,
.virt_start = 0x40300000,
.size = 0x80000,
.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
JAILHOUSE_MEM_IO,
},
/* 0x40380000 - 0x48020000 */ {
.phys_start = 0x40380000,
.virt_start = 0x40380000,
.size = 0x7ca0000,
.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
JAILHOUSE_MEM_IO,
},
/* UART... */ {
.phys_start = 0x48020000,
.virt_start = 0x48020000,
.size = 0xe0000,//0x00001000,
.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
JAILHOUSE_MEM_IO,
},
...
/* RAM */ {
.phys_start = 0x80000000,
.virt_start = 0x80000000,
.size = 0x6F000000,
.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
JAILHOUSE_MEM_EXECUTE,
},
/* Leave hole for hypervisor */
/* RAM */ {
.phys_start = 0xF0000000,
.virt_start = 0xF0000000,
.size = 0x10000000,
.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
JAILHOUSE_MEM_EXECUTE,
},
下面的代码段显示了专用于单元的CPU内核的位图:
.cpus = {
0x3,
},
以下代码段显示中断控制器SPI中断的位图:
.irqchips = {
/* GIC */ {
.address = 0x48211000,
.pin_base = 32,
.pin_bitmap = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
},
},
/* GIC */ {
.address = 0x48211000,
.pin_base = 160,
.pin_bitmap = {
0xffffffff, 0, 0, 0
},
},
},
这些设置适用于所有单元格。
此外,根单元还为hypervisor分配物理内存.
.hypervisor_memory = {
.phys_start = 0xef000000,
.size = 0x1000000,
},
hypervisor使用“内存区域”部分创建第二阶段MMU转换表。通常对于root-cell,使用相同的映射-“VA=PA”。
Bare Metal Inmate示例
Jailhouse在incomates/demos目录中提供了inmate演示。当前版本(v0.6)有两个演示inmate:gic-demo and uart-demo。这些是非常简单的裸机应用程序,演示了uart和arm定时器中断。这些演示在所有jailhouse平台上都很常见。
Jailhouse comes with inmate demos located at the inmates/demos directory. Current (v0.6) version has two demo inmates: gic-demo and uart-demo. Those are very simple bare-metal applications that demonstrate a uart and arm-timer interrupt. Those demos are common for all jailhouse platforms.
3.7.2 Docker Linux容器运行时
3.7.2.1 概述
Docker用一个高级API来补充内核命名空间,该API在进程级别上运行。它运行unix进程,能够强有力地保证跨服务器的隔离性和可重复性。
Docker是自动化分布式系统的一个伟大的构件:大规模web部署,数据库集群,连续部署系统,私有PaaS,面向服务的架构,等等。
3.7.2.2 在处理器SDK中探索Docker
3.7.2.2.1 引导Docker文件系统
建议从SD卡挂载到根文件系统,因为docker运行时可能不在NFS挂载中。虽然可以在NFS根目录上使用Docker,但需要额外的配置来修改默认的rocker运行时目录。
3.7.2.2.2 配置Docker守护进程
默认的docker配置适用于大多数设置。在某些情况下,可能需要自定义配置来正确设置docker,例如,在防火墙后工作。以后,这里将提供可能需要的选择配置。Docker是一个得到广泛支持的开源项目。通常,在线搜索会提供针对不同环境的配置信息。
3.7.2.2.3 Docker Hello World
通过EVM,登录Linux shell。下面的命令将运行“Hello World”演示并确认docker是否正确配置。
$ docker run hello-world
Hello from Docker!
此消息显示您的安装似乎工作正常。
为了生成此消息,Docker采取了以下步骤:
1.Docker客户端已联系Docker守护程序。
2.Docker守护进程从Docker Hub中提取“hello world”图像。(amd64)
3. Docker守护进程从该映像创建了一个新的容器,该容器运行可执行文件,生成您当前读取的输出。
4.Docker守护进程将输出流到Docker客户端,由客户端发送你的终端。
要尝试更具野心的东西,您可以运行一个Ubuntu容器:
$ docker run -it ubuntu bash
共享图像,自动化的工作流程,和更多的免费Docker ID:
https://hub.docker.com/
更多的例子和想法,请访问:
https://docs.docker.com/get-started/
3.7.2.3. Docker参考
• https://docker.com/
• https://hub.docker.com/