跳到正文
Hacker News· dorianzheng·· 7 天前AI 评分36

BoxLite 为什么要用自研 VMM 替换 libkrun

Building a VMM from scratch, #0: Why BoxLite is replacing libkrun

AI 导读

BoxLite 正在用自研 VMM 替换现有的 libkrun,以解决进程退出状态缺失、libkrunfw 经 dlopen 加载不稳定以及多目录卷触发 IrqsExhausted 等问题。

正文 · AI 翻译

每个 BoxLite box 都在自己的 micro-VM 中运行,目前由 libkrun 运行该 VM。我们正用自己编写的 VMM 替换它。本系列公开构建,一次一个已合并的 PR。

1. BoxLite 是什么

BoxLite 是 AI agent 的计算基座——轻量到可嵌入你的笔记本电脑,弹性到足以支撑 agentic 云。每个 box 都是一个硬件隔离的 micro-VM,可运行任何 OCI 镜像,并在多轮对话间保持状态。

BoxLite architecture on your machine and in the cloud

图 1. 一个引擎,两处运行:嵌入式 BoxLite 运行时为每个 box 启动一个 micro-VM,在你的机器上或云 runner 上。

运行每个 micro-VM 的部分是 VMM,即虚拟机监视器。这部分正是本系列的主题。

2. 为什么我们从 libkrun 开始

libkrun 自称是“一个动态库,让程序能轻松获得在部分隔离环境中运行进程的能力”,基于 KVM(Linux)和 HVF(Apple 芯片上的 macOS),背后是“一个简单的 C API”。这契合 BoxLite:

  • 是库,不是守护进程:BoxLite 嵌入你的应用,无需 root,无需后台服务。
  • 一套 API 同时支持 Linux 上的 KVM 和 macOS 上的 Hypervisor.framework。
  • 自带 guest 内核(libkrunfw),以及 virtio-fs、virtio-blk 和 vsock。

libkrun 是 BoxLite 目前在 macOS 和 Linux 上运行 box 的方式。

3. 为什么我们要替换它

libkrun 明确说明了自己不是什么:其 README 将“成为通用 VMM”和“兼容所有类型的工作负载”列为非目标。BoxLite 的需求已超出这些目标:

  • VM 的结果。 libkrun 自行结束进程,因此调用方拿不到退出状态,每次启动失败都返回 -EINVAL。
  • 内核作为共享库。 libkrunfw 通过 dlopen 加载,这在某些主机上不断出问题;#1512 列出了六个此类问题。
  • 设备。 每个目录卷都有自己的设备,三个卷就会导致 box 启动失败并报 IrqsExhausted(#935)。
  • 下一步。 热插拔挂载、实时调整大小、用于 AutoPause 的内存快照(#1003)以及 GPU,都需要一个我们可控的 VMM。

我们不做什么

  • 不 fork 或打补丁 libkrun。在新 VMM 成为默认之前,它原样发布;之后保留一个版本作为回退,然后移除。
  • 不构建通用 VMM。它每个进程只运行一个 VM,且仅支持 BoxLite 的设备;机密计算、实时迁移和 Intel Mac 不在范围内。

代价是什么

  • 新 VMM 需要 macOS 15 或更高版本,以使用 Hypervisor.framework 的内核内中断控制器。macOS 12–14 在切换前继续使用 libkrun。
  • 路很长:首次启动(M1),然后是真实 box(M2)、卷(M3)、加固(M4)和切换(M5)。

4. 一屏看懂 VMM 如何工作

Inside one machine: host process, jailed boxlite-shim, micro-VM and state

图 2. 一台机器内部。运行时为每个 box 生成一个受限制的 boxlite-shim,其中的 VMM 运行 micro-VM。PROPOSED 标记的是本系列要替换的部分。

hypervisor(KVM 或 Hypervisor.framework)在 CPU 上运行 guest 指令。VMM 是它周围的普通进程:为 guest 提供内存、创建 vCPU、加载内核并模拟每个设备。其核心是一个循环:

The VMM loop: run a vCPU, handle its exit, run it again

图 3. 运行一个 vCPU 直到它退出,处理退出,然后再次运行它。

我们新的 KVM 后端运行的第一个 guest 只有 7 字节长:

mov dx, 0x3f8   ; COM1 serial port
mov al, 'K'
out dx, al      ; KVM exits to the VMM: port 0x3f8, byte 'K'
hlt

其余都是细节,每个细节在本系列中都有对应篇章:

部分是什么篇章
内存Guest RAM 就是主机内存;未映射的地址就是设备#1
退出为 KVM、Hypervisor.framework 以及后续的 WHP 提供统一的退出契约#2
停止安全地将 vCPU 从 guest 中拉出#3
CPU 状态x86 上的寄存器、CPUID 和 MSR#4
启动VMM 就是引导加载程序#6
设备先串口、RTC 和复位,然后是 virtio#7, #10–12

5. 系列

截至 2026 年 10 月 11 日的状态。每个部分只有在其代码合并后才会发布,因此每项声明都链接到一个已合并的 PR。

Arc部分发布时间
1. 最初的指令#1 你的第一个 VM 只有 7 字节 · #2 先设计退出契约 · #3 停止 vCPU 才是难点 · #4 手动处理 x86 CPU 状态 · #5 我们自己构建的内核代码已合并
2. 首次启动(M1)#6 你就是引导加载程序 · #7 先处理无聊的设备 · #8 在 Apple 芯片上,由你来解码退出 · #9 一个内核,三个宿主随 M1 落地
3. 第一个盒子(M2–M3)#10 从零实现 virtio · #11 磁盘、套接字、网络 · #12 每个卷一个 virtio-fs 设备 · #13 我们的 agent 作为 PID 1M2–M3
4. 发布它(M4–M5)#14 客户机输入绝不能导致宿主机 panic · #15 与 libkrun 对比测量 · #16 删除 libkrunM4–M5
后续内存快照、热插拔挂载、GPU、我们自己的网络栈M5 之后

我们的进展

  • ✅ 为 KVM、Hypervisor.framework 以及后续的 Windows 设计并统一了一份 hypervisor 契约
  • ✅ x86_64 上的 KVM:VM、内存、运行循环、I/O 完成、kick、启动寄存器、CPUID 和 MSR
  • ✅ 为我们锁定的 Linux 6.12 内核在 x86_64 上提供可复现构建
  • ⏳ M1:在 macOS arm64、Linux x86_64 和 Linux arm64 上首次启动,并在 CI 中检查

通过 RSS 订阅 以及 GitHub 上的每个 PR 跟进。

6. 来和我们一起构建它

BoxLite 是开源的,这个 VMM 的每一步也都是开源的。我们很希望得到你的帮助:

  • 挑战设计。 阅读 VMM 设计文档,告诉我们哪里有问题。
  • 认领 M1 工作。 #1698 列出了待办切片及其依赖项:设备、内核加载器、Hypervisor.framework 后端、arm64 KVM 和三宿主 CI。
  • 提问和讨论。 提交一个 GitHub issue,或者在 Discord 上找到我们。

从 CONTRIBUTING.md 开始。你的第一个 PR 会要求你签署我们的贡献者许可协议。

来源:Hacker News · blog.boxlite.ai