fix(x86_64): reduce Starry userspace switch overhead - #1252
Closed
ZR233 wants to merge 2 commits into
Closed
Conversation
ZR233
marked this pull request as ready for review
June 12, 2026 15:39
Contributor
There was a problem hiding this comment.
PR #1252 Review:fix(x86_64): reduce Starry userspace switch overhead
修改概述
本 PR 优化 x86_64 用户态切换路径的两个开销来源:
- FSGSBASE 指令替代 MSR 读写:在 someboot per-CPU 初始化时启用
CR4.FSGSBASE,ax-cpu 中优先使用RDFSBASE/WRFSBASE/RDGSBASE/WRGSBASE读写 FS_BASE 和 inactive GS_BASE,保留 MSR fallback。 - 避免冗余 TLB flush:x86_64 写 CR3 已隐式 flush 非全局 TLB 条目,新增
write_user_page_table_flushes_tlb()让 ax-task 跳过重复 flush;其他架构保持显式 flush。
实现逻辑分析
- FSGSBASE 检测:
detect_fsgsbase_enabled()同时检查 CPUID 硬件支持和 CR4 已启用标志,两者满足才走快速路径,逻辑正确。 read_inactive_gs_base/write_inactive_gs_base:使用swapgs+rdgsbase/wrgsbase+swapgs模式临时切换 GS 基址读写。内联汇编的nostack、preserves_flags选项正确(swapgs和 FSGSBASE 指令均不影响 RFLAGS)。调用方UserContext::run()中已有disable_irqs(),满足 safety 要求。write_user_page_table_flushes_tlb():x86_64 返回true符合 Intel SDM Vol 3 §4.10.4(CR3 写入 flush 非全局 TLB);aarch64/loongarch64/riscv 返回false,保持原有显式 flush 行为。- someboot
enable_fsgsbase():per-CPU 初始化中调用,先检查 CPUID 再设置 CR4,顺序正确。 FSGSBASE_STATE全局 static +Ordering::Relaxed:启动顺序保证所有 CPU 在用户态调度前完成init_local(),单 CPU 上首次检测结果缓存后后续 CPU 直接命中,实际安全。x86 的 Relaxed load/store 本身就是普通内存操作,缓存一致性由硬件保证。
CI 状态
- CI workflow 结论:success(run #6201, #6200)
- 各检查项因 path filter 被 skip(如 aarch64/riscv64 QEMU 测试、board 测试等),属于预期行为,因为 PR 仅修改 x86_64 特定代码。
- clippy/run_container 等也因 path filter 跳过,但本地已验证。
本地验证
cargo fmt --check:✅ 通过cargo clippy --package ax-cpu:✅ 28 checks passedcargo clippy --package ax-task:✅ 18 checks passedcargo clippy --package someboot:✅ 通过git diff --check:✅ 无问题- PR 作者已验证
cargo xtask starry test qemu --arch x86_64 -c qemu-smp1/syscall-test-uid-gid-re-setters:PASS(74.81s)
重复/重叠分析
- 基线:dev 分支无等效 FSGSBASE 优化。
- PR #1254(同作者 ZR233):互补 PR,从 KVM CI 加速和
copy_from_kernel()冗余 TLB flush 角度优化 x86_64 性能。两个 PR 改动区域无重叠(#1252 改 axcpu/someboot/axtask,#1254 改 CI workflow/page_table_multiarch/starry loader),可独立合并。
建议(非阻塞)
FSGSBASE_STATE 作为全局 static 在 SMP 场景下如果未来出现 CPU 特性差异(如大小核),可考虑改为 per-CPU 存储。当前启动顺序下无实际风险。
结论
实现正确,优化逻辑清晰,fallback 保底,CI 通过,无阻塞问题。APPROVE。
Powered by mimo-v2.5-pro
Contributor
There was a problem hiding this comment.
PR #1252 Review:fix(x86_64): reduce Starry userspace switch overhead
修改概述
本 PR 优化 x86_64 用户态切换路径的两个开销来源:
- FSGSBASE 指令替代 MSR 读写:在 someboot per-CPU 初始化时启用
CR4.FSGSBASE,ax-cpu 中优先使用RDFSBASE/WRFSBASE/RDGSBASE/WRGSBASE读写 FS_BASE 和 inactive GS_BASE,保留 MSR fallback。 - 避免冗余 TLB flush:x86_64 写 CR3 已隐式 flush 非全局 TLB 条目,新增
write_user_page_table_flushes_tlb()让 ax-task 跳过重复 flush;其他架构保持显式 flush。
实现逻辑分析
- FSGSBASE 检测:
detect_fsgsbase_enabled()同时检查 CPUID 硬件支持和 CR4 已启用标志,两者满足才走快速路径,逻辑正确。 read_inactive_gs_base/write_inactive_gs_base:使用swapgs+rdgsbase/wrgsbase+swapgs模式临时切换 GS 基址读写。内联汇编的nostack、preserves_flags选项正确(swapgs和 FSGSBASE 指令均不影响 RFLAGS)。调用方UserContext::run()中已有disable_irqs(),满足 safety 要求。write_user_page_table_flushes_tlb():x86_64 返回true符合 Intel SDM Vol 3 §4.10.4(CR3 写入 flush 非全局 TLB);aarch64/loongarch64/riscv 返回false,保持原有显式 flush 行为。- someboot
enable_fsgsbase():per-CPU 初始化中调用,先检查 CPUID 再设置 CR4,顺序正确。 FSGSBASE_STATE全局 static +Ordering::Relaxed:启动顺序保证所有 CPU 在用户态调度前完成init_local(),单 CPU 上首次检测结果缓存后后续 CPU 直接命中,实际安全。
CI 状态
- 大部分检查因 path filter 被 skip(如 aarch64/riscv64 QEMU 测试、board 测试等),属于预期行为,因为 PR 仅修改 x86_64 特定代码。
- 部分检查(formatting/sync-lint)仍在进行中。
本地验证
cargo fmt --check:✅ 通过cargo clippy --package ax-cpu:✅ 通过cargo clippy --package ax-task:✅ 通过cargo clippy --package someboot:✅ 通过git diff --check:✅ 无问题
建议(非阻塞)
FSGSBASE_STATE 作为全局 static 在 SMP 场景下如果未来出现 CPU 特性差异(如大小核),可考虑改为 per-CPU 存储。当前启动顺序下无实际风险。
结论
实现正确,优化逻辑清晰,fallback 保底,本地验证通过,无阻塞问题。APPROVE。
Powered by mimo-v2.5-pro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
starry qemu-smp1/system在 x86_64 CI 上明显慢于其他架构。对 CI 日志和本地运行结果做对比后,主要慢点不在单个用户程序本身,也不是测试脚本应当被规避的问题,而是大量短用户态程序之间的 fork/exec/wait/date 路径把 x86_64 内核态切换成本放大了。对比其他架构后,x86_64 的热路径额外包含两类高成本操作:
FS_BASE和 inactiveGS_BASE。在 QEMU TCG 下 MSR 访问非常贵,Linux 也会在 CPU 支持时启用CR4.FSGSBASE并用RDFSBASE/WRFSBASE/RDGSBASE/WRGSBASE避开这条慢路径。CR3本身已经 flush 当前 CPU TLB,但任务切换页表后又额外做了一次全 TLB flush,短进程密集场景下会反复付出重复成本。这不是通过修改 test-suit 绕过的问题;测试只是暴露了内核 x86_64 用户态切换路径比其他架构更贵。
修改
CR4.FSGSBASE。FS_BASE和 inactiveGS_BASE,保留 MSR fallback 以兼容旧 CPU。write_user_page_table()是否已经 flush TLB:x86_64 写 CR3 后不再重复全 TLB flush,其他架构保持显式 flush。--device /dev/kvm,并在日志中打印/dev/kvm状态,用于确认 GitHub-hosted container 是否能启用 KVM 加速。验证
cargo fmtcargo xtask clippy --package ax-cpu:28 checks passedcargo xtask clippy --package ax-task:18 checks passedcargo xtask clippy --package someboot:7 checks passedgit diff --checkcargo xtask starry test qemu --arch x86_64 -c qemu-smp1/syscall-test-uid-gid-re-setters:PASS,qemu run: 74.81sgit diff --check -- .github/workflows/ci.yml .github/workflows/reusable-command.yml补充观察:本地 TCG 对比中,同一重 syscall 单用例在启用/关闭 FSGSBASE 时 wall time 约为 16s vs 18s,说明 MSR 路径确实是 x86_64 特有开销来源之一;剩余差距还可能包含 x86_64 UEFI 启动、FPU save/restore、以及 CI 容器是否能使用 KVM 等成本,需要完整 CI 继续量化。