Skip to content

fix(x86_64): reduce Starry userspace switch overhead - #1252

Closed
ZR233 wants to merge 2 commits into
devfrom
fix/x86-starry-qemu-overhead
Closed

fix(x86_64): reduce Starry userspace switch overhead#1252
ZR233 wants to merge 2 commits into
devfrom
fix/x86-starry-qemu-overhead

Conversation

@ZR233

@ZR233 ZR233 commented Jun 12, 2026

Copy link
Copy Markdown
Member

问题

starry qemu-smp1/system 在 x86_64 CI 上明显慢于其他架构。对 CI 日志和本地运行结果做对比后,主要慢点不在单个用户程序本身,也不是测试脚本应当被规避的问题,而是大量短用户态程序之间的 fork/exec/wait/date 路径把 x86_64 内核态切换成本放大了。

对比其他架构后,x86_64 的热路径额外包含两类高成本操作:

  1. 用户态进入/返回时通过 MSR 读写 FS_BASE 和 inactive GS_BASE。在 QEMU TCG 下 MSR 访问非常贵,Linux 也会在 CPU 支持时启用 CR4.FSGSBASE 并用 RDFSBASE/WRFSBASE/RDGSBASE/WRGSBASE 避开这条慢路径。
  2. x86_64 写 CR3 本身已经 flush 当前 CPU TLB,但任务切换页表后又额外做了一次全 TLB flush,短进程密集场景下会反复付出重复成本。

这不是通过修改 test-suit 绕过的问题;测试只是暴露了内核 x86_64 用户态切换路径比其他架构更贵。

修改

  • 在 someboot x86_64 per-CPU 初始化中,当 CPUID 报告 FSGSBASE 时启用 CR4.FSGSBASE
  • 在 ax-cpu x86_64 中优先用 FSGSBASE 指令读写 FS_BASE 和 inactive GS_BASE,保留 MSR fallback 以兼容旧 CPU。
  • 在 ax-task 页表切换路径中区分 write_user_page_table() 是否已经 flush TLB:x86_64 写 CR3 后不再重复全 TLB flush,其他架构保持显式 flush。
  • 给 Starry x86_64 QEMU 的 GitHub Actions 容器传入 --device /dev/kvm,并在日志中打印 /dev/kvm 状态,用于确认 GitHub-hosted container 是否能启用 KVM 加速。
  • 更新 arch platform porting 说明,记录 x86_64 FSGSBASE per-CPU 初始化要求。

验证

  • cargo fmt
  • cargo xtask clippy --package ax-cpu:28 checks passed
  • cargo xtask clippy --package ax-task:18 checks passed
  • cargo xtask clippy --package someboot:7 checks passed
  • git diff --check
  • cargo xtask starry test qemu --arch x86_64 -c qemu-smp1/syscall-test-uid-gid-re-setters:PASS,qemu run: 74.81s
  • workflow 变更本地验证:git 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 继续量化。

@ZR233
ZR233 marked this pull request as ready for review June 12, 2026 15:39

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #1252 Review:fix(x86_64): reduce Starry userspace switch overhead

修改概述

本 PR 优化 x86_64 用户态切换路径的两个开销来源:

  1. FSGSBASE 指令替代 MSR 读写:在 someboot per-CPU 初始化时启用 CR4.FSGSBASE,ax-cpu 中优先使用 RDFSBASE/WRFSBASE/RDGSBASE/WRGSBASE 读写 FS_BASE 和 inactive GS_BASE,保留 MSR fallback。
  2. 避免冗余 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 基址读写。内联汇编的 nostackpreserves_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 passed
  • cargo clippy --package ax-task:✅ 18 checks passed
  • cargo 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

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #1252 Review:fix(x86_64): reduce Starry userspace switch overhead

修改概述

本 PR 优化 x86_64 用户态切换路径的两个开销来源:

  1. FSGSBASE 指令替代 MSR 读写:在 someboot per-CPU 初始化时启用 CR4.FSGSBASE,ax-cpu 中优先使用 RDFSBASE/WRFSBASE/RDGSBASE/WRGSBASE 读写 FS_BASE 和 inactive GS_BASE,保留 MSR fallback。
  2. 避免冗余 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 基址读写。内联汇编的 nostackpreserves_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

@ZR233 ZR233 closed this Jun 15, 2026
@ZR233
ZR233 deleted the fix/x86-starry-qemu-overhead branch June 29, 2026 03:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant