Zephyr 在 ACRN Hypervisor 下运行 Pre-Launched 客户机的完整构建与启动指南
Zephyr 在 ACRN Hypervisor 下运行 Pre-Launched 客户机的完整构建与启动指南【免费下载链接】zephyrPrimary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.项目地址: https://gitcode.com/GitHub_Trending/ze/zephyrZephyr 可以以预启动pre-launched客户机的身份运行在 x86 平台的 ACRN hypervisor 之上绕过 SOS VM 直接访问 hypervisor从而让 Zephyr 的实时性与安全性不受其他虚拟机干扰。本文以仓库中的 ACRN 板级教程 为主线完整覆盖从构建 Zephyr 镜像、配置 ACRN 的 hybrid.xml、编译 ACRN到制作 EFI 启动介质并在真实硬件Intel Elkhart Lake CRB上启动验证的全过程并结合 Zephyr 源码说明kern_load_addr取值、SMP CPU 分配等关键配置背后的实现原理。读完本文你将掌握在无 SOS VM 参与的情况下让 Zephyr 作为 SAFETY_VM 跑起来的可复制方案。1. 为什么选择 ACRN 的 Hybrid混合场景ACRN 支持一种混合部署场景Zephyr 以pre-launched模式运行即 Zephyr 直接访问 ACRN hypervisor而不需要经过 SOS VMSupervisor OS 虚拟机的中介。这是现实中最实用的用户场景原因是Zephyr 的实时能力与安全性承诺不会被同机的其他 VM 影响启动路径短hypervisor 直接拉起 Zephyr 客户机控制台即可见 Zephyr 输出。在该场景下Zephyr 在 ACRN 配置中的vm_type固定为SAFETY_VM。ACRN 的启动链为EFI 固件 → GRUBmultiboot2→ ACRNacrn.bin→ 客户机zephyr.bin作为 GRUB 模块加载。ACRN 本身没有自己的运行时文件系统它把客户机镜像作为 GRUB 的 multiboot 模块接收因此启动介质上的文件系统组织方式第 6 节是整套方案能否工作的前提。本教程只演示 Zephyr ACRN 的最小可运行组合SOS VM、其他客户机等 ACRN 进阶功能不在本文范围内。2. 构建 Zephyr 应用2.1 选择板级并构建首先像平时一样构建要在 ACRN 中运行的 Zephyr 应用教程选用 Intel Elkhart Lake Reference BoardEHL CRB作为目标平台west build -b acrn_ehl_crb samples/hello_world仓库中与 ACRN 相关的板级目标定义在 board.yml 中共有三个条目板级名含义acrn通用 ACRN hypervisor 板级acrn_ehl_crbACRN on EHL hypervisor本文使用acrn_adl_crbACRN Hypervisor on ADL三者的 SoC 均指定为atom对应 Kconfig 中的SOC_ATOM见 Kconfig.acrn。2.2 板级配置的关键内容构建时 Kconfig 输出会落到build/zephyr/.config其中几个值在后续配置 ACRN 时必须引用尤其是CONFIG_MP_MAX_NUM_CPUS见第 4.3 节。acrn_defconfig 的内容值得逐条理解它们共同决定了 Zephyr 在 hypervisor 环境下的行为CONFIG_PIC_DISABLEy CONFIG_LOAPICy CONFIG_APIC_TSC_DEADLINE_TIMERy CONFIG_X2APICy CONFIG_CONSOLEy CONFIG_SERIALy CONFIG_UART_CONSOLEy CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC25000000 CONFIG_BUILD_OUTPUT_BINy CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVENn CONFIG_KERNEL_VM_SIZE0x1000000几个要点CONFIG_BUILD_OUTPUT_BINy显式要求产出原始二进制镜像zephyr.bin。这正是 ACRN 加载方式的要求——ACRN 只会把一段连续的内存区域搬进客户机物理内存并跳转到指定地址它无法解析 ELF。因此不同于其他 x86 目标这里必须用zephyr.bin而不是zephyr.elfzephyr.elf只是用来查询入口地址。CONFIG_LOAPICy、CONFIG_X2APICy、CONFIG_APIC_TSC_DEADLINE_TIMERyACRN 向客户机呈现的中断控制器与定时器环境基于 LAPIC/TSC Deadline中断投递由 hypervisor 完成。CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC25000000与 ACRN 呈现给客户的时钟配置匹配。2.3 设备树8MB 内存与串口控制台基础设备树 acrn.dts 声明了客户机看到的硬件抽象内存DT_DRAM_BASE 0、DT_DRAM_SIZE为 8192 KB即客户机拥有 8MB 线性内存控制台与 shell 都绑定到uart0zephyr,console与zephyr,shell-uart波特率 115200CPU在通用cpu之外额外声明了cpu1compatible intel,x86_64reg 1这正是 Zephyr 默认以 SMP 模式构建、拥有多核可用的依据板级文件 acrn_ehl_crb.dts 仅一行#include acrn.dts硬件差异由 ACRN 侧的 platform 配置ehl-crb-b承担而不是 Zephyr 设备树。构建完成后两个关键产物build/zephyr/zephyr.bin——ACRN 实际加载的原始内存镜像build/zephyr/zephyr.elf——用于提取入口地址。3. 获取并配置 ACRN3.1 版本要求ACRN hypervisor 源码从 ACRN 项目的acrn-hypervisor官方仓库克隆git clone该仓库即可。教程建议使用 v2.5.1 或更新版本因为更新版本对 Zephyr 的 SMP 有更好的支持。3.2 XML 大配置文件ACRN 与 Zephyr 一样偏好构建期配置但组织方式不同Zephyr 使用可叠加合并的 kconfig defconfig 与 devicetree include而 ACRN 使用单个大型 XML 文件。你需要选择与硬件匹配的 host config本例为ehl-crb-b然后编辑misc/config_tools/data/platform/hybrid.xml使其与 Zephyr 的构建配置一致。3.3 让 Zephyr 成为 vm id 0在hybrid.xml中找到所有vm声明每个带id属性。为测试 Zephyr必须保证 Zephyr 镜像的 ID 为零这样启动 ACRN 时只需一个 VM 镜像也避免无谓地把大型 Linux blob 拷进启动文件系统。在已测试的配置下Zephyr 的vm_type标签始终是SAFETY_VM。4. 配置 Zephyr 的内存布局4.1 定位加载地址与入口地址ACRN 无法像传统加载器那样从 ELF 中自动提取加载地址与入口点它只会把一段连续数据载入内存并跳转到指定地址因此这两个地址必须在 ACRN 中手工配置。找到vm id0下的os_config标签形如os_config nameZephyr/name kern_typeKERNEL_ZEPHYR/kern_type kern_modZephyr_RawImage/kern_mod ramdisk_mod/ bootargs/bootargs kern_load_addr0x1000/kern_load_addr kern_entry_addr0x1000/kern_entry_addr /os_config其中kern_mod取值Zephyr_RawImage与第 6 节 GRUB 配置中module2 ... Zephyr_RawImage的模块名相互对应——GRUB 加载模块时携带的这个名字就是 ACRN 用来认领该客户机镜像的标识。4.2 kern_load_addr 与 LOCORE_BASE 的对应关系kern_load_addr必须与 Zephyr 的LOCORE_BASE符号一致。这个符号定义在 memory.ld 中#ifdef CONFIG_X86_64 /* Locore must be addressable by real mode and so cannot extend past 64K. * Skip reserved stuff in first page */ #define LOCORE_BASE 0x1000 #define LOCORE_SIZE (0x10000 - LOCORE_BASE)从注释与 MEMORY 段定义 可以看出LOCORE 是 64 位 x86 上一个特殊的低内存区LOCORE (wx) : ORIGIN LOCORE_BASE, LENGTH LOCORE_SIZE用途是从实模式引导其他 CPU——也就是 SMP 下 APapplication processor启动跳板。因为实模式只能寻址到 64KB 以内且要跳过首页的保留区域BIOS IVT/中断向量表占 0x0–0xFFF所以LOCORE_BASE固定为0x1000。这解释了为什么 Zephyr 64 位镜像的物理加载点必须选在 0x1000ACRN 把zephyr.bin放到该地址后BS 端初始化与后续 AP 实模式跳板代码才落在合法的低地址窗口内。4.3 kern_entry_addr 的获取方法kern_entry_addr必须与构建出的zephyr.elf的入口点一致可用 binutils 查询$ objdump -f build/zephyr/zephyr.elf build/zephyr/zephyr.elf: file format elf64-x86-64 architecture: i386:x86-64, flags 0x00000012: EXEC_P, HAS_SYMS start address 0x0000000000001000默认配置下入口地址同样是0x1000与 ACRN 的默认配置一致。但教程特别提醒这并非在所有配置下恒为真且未来可能变化——更换板级或内核配置后应重新执行objdump -f核对而不是直接照抄。5. 配置 Zephyr 的 CPU 与构建 ACRN5.1 SMP 下的 CPU 亲和性配置Zephyr 默认以 SMP 模式构建对应 acrn.dts 中声明的cpu1而 ACRN 默认只给客户机一个 CPU。需要查 Zephyr.config中CONFIG_MP_MAX_NUM_CPUS的值并在cpu_affinity标签中给该 VM 分配相应数量的物理 CPUvm id0 vm_typeSAFETY_VM/vm_type nameACRN PRE-LAUNCHED VM0/name guest_flags guest_flag0/guest_flag /guest_flags cpu_affinity pcpu_id0/pcpu_id pcpu_id1/pcpu_id /cpu_affinity ... clos vcpu_clos0/vcpu_clos vcpu_clos0/vcpu_clos /clos ... /vm教程明确指出使用 SMP 时必须把 VM0 的pcpu_id改成 0 和 1让 Zephyr 跑在 CPU0/CPU1否则 ACRN 与 Zephyr 都无法成功启动若只打算用单 CPU 运行 Zephyr则可以跳过此步。由于 Zephyr 占用了 CPU0/CPU1VM1SOS VM必须改到 CPU2/CPU3其余客户机同理避免物理 CPU 分配重叠vm id1 vm_typeSOS_VM/vm_type nameACRN SOS VM/name guest_flags guest_flag0/guest_flag /guest_flags cpu_affinity pcpu_id2/pcpu_id pcpu_id3/pcpu_id /cpu_affinity clos vcpu_clos0/vcpu_clos vcpu_clos0/vcpu_clos /clos ... /vm注意pcpu_id索引指的是宿主机上的物理 CPU。仅测试 Zephyr 时用 CPU 0、1 即可ehl-crb-b共有 4 个物理 CPU把 0–3 全部分配给客户机也能工作但会没有剩余空间给其他客户机预留独占 CPU。5.2 编译 ACRN配置完成后编译$ make -j BOARDehl-crb-b SCENARIOhybrid唯一的构建产物需求是 ACRN multiboot 镜像build/hypervisor/acrn.bin。6. 制作 EFI 启动介质ACRN 通过 GNU GRUB 在硬件上启动GRUB 本身又由 EFI 固件拉起两者都需要正确配置。6.1 准备 GRUB EFI 二进制你需要一个与硬件匹配的 GRUB EFI 二进制。多数情况下上游源码构建或从常见 Linux 发行版拷贝即可部分硬件则可能需要特殊补丁的 GRUB。教程的实用建议是直接向硬件支持团队或最近一次测试成功的同事要一个可用的二进制。6.2 创建 EFI 启动分区与 FAT 文件系统把启动介质例如 USB 键在 Linux 上为/dev/sdb视硬件而定接入 Linux 系统创建一个足够容纳启动文件的 EFI 分区类型代码 0xEF。以下命令直接喂给 fdisk# for i in n p 1 t ef w; do echo $i; done | fdisk /dev/sdb ... lots of fdisk output然后在新分区上创建 FAT 文件系统并挂载# mkfs.vfat -n ACRN_ZEPHYR /dev/sdb1 # mkdir -p /mnt/acrn # mount /dev/sdb1 /mnt/acrn6.3 拷贝镜像并配置 GRUB三个文件GRUB、ACRN、Zephyr都要拷入启动介质的/efi/boot目录。注意 GRUB 必须命名为bootx64.efi否则固件不会把它识别为启动加载器# mkdir -p /mnt/acrn/efi/boot # cp $PATH_TO_GRUB_BINARY /mnt/acrn/efi/boot/bootx64.efi # cp $ZEPHYR_BASE/build/zephyr/zephyr.bin /mnt/acrn/efi/boot/ # cp $PATH_TO_ACRN/build/hypervisor/acrn.bin /mnt/acrn/efi/boot/GRUB 启动时会加载efi/boot/grub.cfg作为运行时配置。该配置需要把acrn.bin作为启动目标并把zephyr.bin作为第一个模块传入因为第 4 节中 Zephyr 被配置为vm id0。这份最小配置对绝大多数硬件都够用hd0 几乎总是 GRUB 所在的启动文件系统无需折腾 GRUB 插件、菜单或超时# cat /mnt/acrn/efi/boot/grub.cfgEOF set roothd0,msdos1 multiboot2 /efi/boot/acrn.bin module2 /efi/boot/zephyr.bin Zephyr_RawImage boot EOF最后卸载并同步# umount /dev/sdb1 # sync文件系统即告完成。7. 启动并验证一切顺利的话在硬件上启动该 EFI 介质后会看到运行中的 ACRN、运行中的 Zephyr默认 Zephyr 以 pre-launched VM 启动以及控制台上的 ACRN 命令行。用vm_console命令查看 Zephyrvm 0的控制台输出ACRN:vm_console 0 ----- Entering VM 0 Shell ----- *** Booting Zephyr OS build v2.6.0-rc1-324-g1a03783861ad *** Hello World! acrnHello World! acrn 中的acrn正是BOARD_TARGET说明 hello_world 示例已在 ACRN 客户机身份下成功运行。8. 适用前提与常见注意事项平台限定本教程以 x86 64 位 ACRN hybrid 场景为前提参考平台为 Intel Elkhart Lake CRBACRN host configehl-crb-b4 个物理 CPU仓库同时提供acrn_adl_crb板级见 board.yml流程类似但需换成对应平台的 hybrid.xml。镜像格式ACRN 只加载原始连续镜像务必使用zephyr.binzephyr.elf仅用于objdump -f查询入口。地址核对kern_load_addr必须等于 memory.ld 中的LOCORE_BASE当前为0x1000kern_entry_addr必须等于实际构建的 ELF 入口二者都可能随配置变化换配置后要重新核对。SMP 依赖ACRN 版本需 v2.5.1 及以上以获得良好的 Zephyr SMP 支持cpu_affinity与clos的 vCPU 数量要和CONFIG_MP_MAX_NUM_CPUS对齐且各客户机物理 CPU 分配不要互相重叠。模块命名GRUB 的module2 /efi/boot/zephyr.bin Zephyr_RawImage中第二个参数是 ACRN 识别客户机镜像的模块名必须与 hybrid.xml 中kern_mod一致。调试入口启动后一切从 ACRN 命令行ACRN:开始vm_console id是查看各客户机控制台的主要手段。【免费下载链接】zephyrPrimary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.项目地址: https://gitcode.com/GitHub_Trending/ze/zephyr创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考