周报(2026-03-09 至 2026-03-15)
开发分支
- axvisor: https://github.com/Iscreamx/axvisor/tree/feature/ebpf
- axebpf: https://github.com/Iscreamx/axebpf/tree/feature/deferred-guest-kprobe-enable
总结
本周核心进展:在上周 Stage-2 / BrkInject 双路径和 deferred attach 机制基本落地的基础上,完成了 guest kretprobe 返回探针机制的实现——包括 per-vCPU return stack、动态 BRK 注入/回收的引用计数管理、以及 handler 侧的 entry/return 分流处理;同时完成了上周遗留的 deferred attach 收口提交和 VMM 依赖解耦。
一、已完成工作
1. deferred attach 收口
- axvisor 侧(
d379ab7):shell 的trace kprobe命令支持 pending attach 提示,当TTBR1_EL1尚未就绪时显式输出 "registered pending enable" 而非报错退出。 - VMM 依赖解耦(
ac1068a):将 VM-exit 通知收回到kernel/src/vmm/mod.rs,去掉对axvm新接口的直接依赖,使 guest-kprobe 功能可在不修改 axvm crate 的前提下工作。
2. guest kretprobe 返回探针实现(axebpf)
本周最主要的新功能是 guest kretprobe(a77d6ec),变更量为 +1126/-145 行,涉及 10 个文件。核心设计包括:
2.1 per-vCPU return stack(return_stack.rs,新增文件)
- 每个 vCPU 维护一个 LIFO 栈(最大深度 16),记录待返回的 probe 信息
- 支持
push、pop_matching(按 vm_id + return_gva 匹配弹出)、retain(批量清理) - 提供
clear_for_vm和clear_for_vm_probe用于 VM 销毁或 probe detach 时的资源回收
2.2 动态 return BRK 引用计数(manager.rs)
- 新增
RETURN_BRK_REFCOUNT全局注册表,管理 return 地址处的动态 BRK 注入 acquire_return_brk:首次调用时注入 BRK 并保存原指令,后续调用仅增加引用计数release_return_brk:引用计数归零时恢复原指令- 解决了多个 entry probe 共享同一 return 地址时的 BRK 生命周期问题
2.3 handler 侧 entry/return 分流(handler.rs)
handle_guest_brk增加is_ret分支:- entry hit:直接执行 eBPF 程序(与此前行为一致)
- return hit(
is_ret=true):从x30读取返回地址 → 翻译为 HVA → 调用acquire_return_brk注入 BRK → 压入 return stack
- 新增
ReturnProbeHitSingleStep返回值,指示 caller 需进入 single-step 流程 - 寄存器接口从
[u64; 8]扩展为[u64; 31],覆盖 AArch64 全部通用寄存器
3. trace stream 修复
修复了 trace stream -n <count> 模式下的一个交互问题:当指定了事件数量上限时,不再轮询键盘输入,避免在非交互场景下误触退出。
4. VMM 配置 cmdline 透传
在 kernel/src/vmm/config.rs 中将 guest 的 cmdline 配置项透传到 AxVMConfig,为后续 guest 启动参数定制提供基础。
二、遇到的问题与解决方案
2.1 多个 entry probe 共享 return 地址
问题:当多个不同入口函数恰好返回到同一地址时,简单的 "注入 BRK / 恢复原指令" 会导致提前恢复,遗漏后续 return hit。 解决方案:引入引用计数(ReturnBrkState.refcount),仅在最后一个引用释放时才恢复原指令。
2.2 寄存器宽度不足
问题:kretprobe 需要读取 x30(LR 寄存器)获取返回地址,但此前 handler 只接收 x0-x7(8 个寄存器)。 解决方案:将接口统一扩展为 [u64; 31],覆盖 AArch64 全部通用寄存器,同时在 build_guest_ctx 中仍只取 x0-x7 作为 eBPF 上下文参数,保持兼容。
2.3 热点地址不是合法 kretprobe 入口
问题:最早用 keepalive_hotspot 做验证时,能反复触发 entry hit,但始终看不到 return hit,return stack 最终被顶满。 根因:keepalive_hotspot 是函数内部热点指令,不是函数入口;此时 x30 只是内部 bl 的返回地址,不是真正的函数返回点。 解决方案:改用真实函数入口做验证,并构建专用 keepalive guest,避免把验证点错误与实现问题混淆。
2.4 return stack 溢出风险
问题:递归或高频函数可能导致 return stack 无限增长。 解决方案:设置固定上限 MAX_RETURN_DEPTH = 16,超出时 push 返回错误并自动释放已 acquire 的 return BRK,不会泄漏。
三、提交摘要
axvisor(已提交)
| 提交 | 说明 |
|---|---|
d379ab7 |
shell 侧支持 deferred attach pending 提示 |
ac1068a |
将 VM-exit 通知收回 root,去掉对 axvm 新接口的依赖 |
axebpf(已提交)
| 提交 | 说明 |
|---|---|
54740f1 |
deferred attach:允许先注册、首次条件满足后 enable |
a77d6ec |
guest kretprobe return handling:return stack + 引用计数 + handler 分流 |
工作区(未提交)
| 文件 | 说明 |
|---|---|
kernel/src/shell/commands/trace.rs |
修复 trace stream -n 模式下误触退出 |
kernel/src/vmm/config.rs |
透传 guest cmdline 到 AxVMConfig |
.cargo/config.toml |
启用 git-fetch-with-cli 解决网络拉取问题 |
四、工作量统计
| 仓库 | 提交数 | 新增 | 删除 |
|---|---|---|---|
| axvisor | 2 | +46 | -26 |
| axebpf | 2 | +1680 | -183 |
五、下两周计划(03-16 至 03-29)
第一周(03-16 至 03-22):StarryOS / Linux guest 全功能验证
| 优先级 | 任务 | 验收标准 |
|---|---|---|
| P0 | StarryOS guest 上跑通 hprobe 全流程 | tracepoint、hprobe attach/detach/stream 均可稳定工作 |
| P0 | StarryOS / Linux guest 上跑通 guest-kprobe(BrkInject + Stage-2) | attach → hit → detach 可复现,日志可观测 |
| P0 | StarryOS / Linux guest 上跑通 kretprobe | entry hit → return hit → detach 全流程通过 |
| P1 | 提交本周工作区变更并清理 | trace stream 修复和 cmdline 透传正式提交 |
| P1 | 固化回归脚本 | 一键复现各路径 attach → hit → detach,适配 StarryOS / Linux 两种 guest |
第二周(03-23 至 03-29):uprobe 设计与原型
| 优先级 | 任务 | 验收标准 |
|---|---|---|
| P0 | uprobe 方案设计文档 | 输出设计文档,覆盖 guest 用户态地址翻译、ELF 符号解析、BRK 注入策略、与 kprobe 的复用/差异分析 |
| P0 | uprobe 核心数据结构与 manager 原型 | axebpf 中新增 probe/uprobe 模块骨架,定义 attach/detach 接口 |
| P1 | 评估 uprobe 地址翻译路径 | 明确 guest 用户态 VA → PA 翻译需要哪些新 hook(TTBR0_EL1、用户页表遍历) |
| P1 | 评估 vCPU 迁移对 return stack 的影响 | 明确 kretprobe 是否需要改为 per-vcpu 索引 |
七、个人复盘
这周的重心从"让基础路径跑通"转到"在已验证的基础设施上扩展能力"。kretprobe 是 guest-kprobe 功能链中第一个需要在 handler 中动态修改 guest 内存的特性(return 地址处的 BRK 注入),和 entry probe 的静态 BRK 注入不同,它的生命周期完全由运行时事件驱动,引入了引用计数和 per-CPU 栈两个新的状态管理维度。
好的一面是:上周建立的 deferred attach 机制和 single-step 基础设施直接被 kretprobe 复用了,没有出现"为新功能重新搭基础"的情况。这说明之前的分层设计(manager 管注册/启用、handler 管命中/分发、single_step 管恢复)是合理的。
需要注意的风险是:return stack 按物理 CPU 索引,如果 vCPU 在两次 VM-exit 之间被调度到不同物理核,return hit 会找不到对应记录。这个问题在单核 guest 上不会暴露,需要在多核验证阶段重点关注。