2. Jailhouse 基础概念

Jailhouse 是一个面向嵌入式实时场景的轻量级静态分区 Hypervisor。它不追求通用虚拟化的“万能抽象”,而是把物理硬件按需切成若干互不干扰的分区,让每个分区直接运行原生操作系统或裸机程序。理解 Jailhouse,关键要抓住六个概念:Hypervisor、Cell、Inmate、Root Cell、裸机分区、静态配置与资源隔离。它们共同构成了 Jailhouse 的“世界观”。

一、核心原理:从“虚拟化”到“分区化”

传统 Hypervisor 通过模拟设备、影子页表、调度器让多个 Guest 共享 CPU 与内存,代价是延迟不确定、代码量大。Jailhouse 走的是另一条路:它把系统划分为多个 Cell(单元),每个 Cell 独占一组物理 CPU 核、一段物理内存、一组中断与外设。Cell 之间没有时间片轮转,也没有设备模拟,只有严格的物理资源边界。因此 Jailhouse 更像“硬件分区器”,而不是“虚拟机管理器”。

Jailhouse 自身代码量很小,通常只有几万行,运行在 EL2(ARM)或 VMX root(x86)上。它不提供调度,也不提供设备模型;它只做三件事:初始化分区、分配资源、在 Cell 间传递极少量控制消息。这种极简设计使中断延迟和抖动接近裸机,适合工业控制、汽车电子、机器人等对实时性敏感的场景。

二、Cell、Inmate 与 Root Cell 的关系

Cell 是 Jailhouse 的资源容器,代表一个独立运行环境。每个 Cell 拥有自己的 CPU 集合、内存区域、中断路由和外设权限。Cell 分为两类:Root Cell 和 Inmate Cell。

  • Root Cell:系统启动时由 Linux 首先运行,Jailhouse 被加载后,Linux 被“降级”为 Root Cell。它负责管理非实时任务、加载 Jailhouse 驱动、创建和销毁其他 Cell。Root Cell 拥有剩余资源,但不能再访问已分配给 Inmate 的资源。
  • Inmate:由 Root Cell 创建的非 Root Cell,通常运行裸机程序或轻量 RTOS。Inmate 不依赖 Linux,直接使用分配给它的 CPU、内存和外设,因此启动快、延迟低、行为确定。
  • 裸机分区:Inmate 的典型形态。它没有操作系统抽象层,程序入口即中断向量或主循环,适合硬实时任务。

Root Cell 与 Inmate 之间不是父子进程关系,而是资源划分关系。Root Cell 创建 Inmate 后,Inmate 独立运行,Root Cell 不能随意读写其内存,只能通过 Jailhouse 提供的 ivshmem 或中断注入进行通信。

三、静态配置:一切在启动前决定

Jailhouse 最显著的特征是静态配置。Cell 的 CPU 核、内存区域、PCI 设备、中断号、串口等资源,全部在系统配置文件中预先声明。运行时不能动态添加或迁移资源。这种“先规划、后运行”的方式牺牲了灵活性,换来了可预测性和安全性。

配置通常以 C 结构体形式描述,编译进 Jailhouse 镜像或作为二进制 blob 加载。一个简化的 Cell 配置片段如下:

struct jailhouse_cell_desc {
    .name = "inmate-demo",
    .cpu_set = { 0x2 },          // 使用 CPU2
    .num_memory_regions = 1,
    .memory_regions = {
        { .phys_start = 0x80000000,
          .size = 0x2000000,
          .flags = JAILHOUSE_MEM_READ |
                   JAILHOUSE_MEM_WRITE |
                   JAILHOUSE_MEM_EXECUTE }
    },
    .num_irqchips = 1,
    .irqchips = { { .address = 0x... } }
};

配置一旦加载,Jailhouse 会关闭未分配核的中断,隔离内存控制器,重定向外设访问。任何越界访问都会触发 Hypervisor 异常,而不是被静默忽略。

四、资源隔离:CPU、内存、中断与外设

Jailhouse 的资源隔离是“硬隔离”,不依赖软件调度。下表总结了四类资源的隔离方式:

资源类型 隔离机制 典型配置项
CPU 按物理核分配,关闭未分配核的中断与时钟 cpu_set
内存 第二阶段页表映射,仅允许 Cell 访问自身区域 memory_regions
中断 中断控制器重映射,仅路由到所属 Cell irqchips
外设 PCI 设备直通,禁止 Root Cell 访问已分配设备 pci_devices

这种隔离方式意味着:Inmate 的实时任务不会被 Linux 调度器打断,也不会因其他 Cell 的内存访问而缓存污染。代价是资源不能超卖,必须提前规划。

五、案例场景:工业机器人的双核分区

假设一台工业机器人控制器使用四核 ARM SoC。设计目标:CPU0-1 运行 Linux 做视觉与人机界面,CPU2-3 运行裸机 Inmate 做运动控制,周期 100μs。

配置步骤:

  1. 在 Root Cell 配置中保留 CPU0-1、DDR 低 512MB、以太网和显示控制器。
  2. 创建 Inmate Cell,分配 CPU2-3、DDR 高 256MB、一个定时器和一路 CAN 控制器。
  3. 将运动控制固件编译为裸机镜像,通过 Jailhouse 加载到 Inmate 内存。
  4. 启动 Inmate,验证 CAN 收发与定时器中断延迟。

运行后,Linux 侧负载波动不会影响 Inmate 的 100μs 周期;Inmate 的 CAN 中断也不会被 Linux 网络栈延迟。两者通过共享内存交换目标位置与状态反馈。

调试建议:先用 jailhouse cell list 确认 Cell 状态,再用 jailhouse cell stats 查看 CPU 与中断计数。若 Inmate 无法启动,优先检查内存区域是否与 Root Cell 重叠。

六、常见误区与复盘

  • 误区一:把 Jailhouse 当 KVM 用。 Jailhouse 不支持动态迁移、设备模拟和超卖,不能运行未修改的通用 Guest。
  • 误区二:认为 Root Cell 可以随意访问 Inmate 内存。 一旦资源分配完成,Root Cell 的访问会被第二阶段页表拦截。
  • 误区三:忽略静态配置的编译期约束。 修改 Cell 配置后必须重新生成配置二进制并重启 Jailhouse,不能热更新。
  • 误区四:只关注 CPU 隔离,忽略中断路由。 中断未正确重映射会导致 Inmate 收不到定时器或外设事件。

复盘时可用一张“资源归属表”核对每个 CPU、内存段、中断号和外设的归属,确保没有重叠或遗漏。Jailhouse 的可靠性来自“配置即契约”,配置错误往往在启动阶段就暴露,而不是运行中随机崩溃。

Jailhouse 静态分区资源视图 Jailhouse Hypervisor(EL2 / VMX root)— 仅做分区、资源分配与控制消息 Root Cell(Linux) 管理非实时任务、加载 Jailhouse 驱动 CPU0-1 · DDR 低 512MB 以太网 · 显示控制器 · 文件系统 jailhouse 工具 · cell 管理 不可访问 Inmate 已分配资源 Inmate Cell(裸机分区) 硬实时任务、无 OS 抽象、启动即运行 CPU2-3 · DDR 高 256MB 定时器 · CAN 控制器 · 中断直通 100μs 运动控制循环 与 Root Cell 通过 ivshmem 通信 硬隔离边界:CPU / 内存 / 中断 / 外设 不可越界 静态配置:所有资源在启动前声明,运行时不可动态迁移或超卖

掌握这六个概念后,后续移植与故障诊断就有了共同语言:看到“Cell 启动失败”,先查配置中的资源是否冲突;看到“Inmate 中断丢失”,先查中断路由是否归属正确;看到“Root Cell 访问越界”,先查第二阶段页表映射。Jailhouse 的调试,本质上是核对“配置契约”与“实际资源”是否一致。