Summary
The stage 1 runtimes configuration builds libunwind with -mno-sse -mno-sse2 for
i686-unknown-nanvix. That guard predates SSE support in nanvix/nanvix and appears to be
obsolete: Nanvix has provided full userland SSE/SSE2 support since 2025-08-28. The flags
should be dropped after verifying a stage 1 build and the smoke tests.
Current state
configure_stage1() in z:
local libunwind_options=(
-DLIBUNWIND_ENABLE_STATIC=ON
-DLIBUNWIND_ENABLE_SHARED=ON
-DLIBUNWIND_USE_COMPILER_RT=ON
-DLIBUNWIND_IS_BAREMETAL=ON
)
if [[ "${NANVIX_ARCH}" == "x86" ]]; then
libunwind_options+=(
-DLIBUNWIND_ADDITIONAL_COMPILE_FLAGS='-mno-sse;-mno-sse2'
)
fi
The flag was unconditional when only i686 was supported (added in [Nanvix] Add build orchestrator, 2026-07-02). [Nanvix] Add x86_64 toolchain support made it conditional
rather than removing it, because -mno-sse is invalid on x86-64 — SSE2 is part of the
System V AMD64 psABI (xmm0-xmm7 carry float/double arguments and return values), so
Clang rejects such code with error: SSE register return with SSE disabled.
Why the i686 guard looks obsolete
Evidence from nanvix/nanvix:
src/kernel/src/hal/arch/x86/cpu/mod.rs and .../x86_64/cpu/mod.rs abort boot unless
(sse || sse2) && fxsr, then call fpu::init().
src/kernel/src/hal/arch/shared/cpu/fpu.rs clears CR0.EM, sets CR0.MP, sets
CR4.OSFXSR and CR4.OSXMMEXCPT, masks all MXCSR exceptions, and snapshots an initial
FXSAVE image used to seed new threads.
src/kernel/src/pm/process/manager/mod.rs implements lazy FPU context switching:
CR0.TS is set on context switch, #NM routes to handle_fpu_exception(), which clears
TS, fxsaves the previous FPU_OWNER_TID's area and fxrstors the current thread's.
src/kernel/src/pm/process/manager/signal.rs saves/restores the 512-byte FXSAVE image
as part of the signal frame.
src/uservm/src/vmm/microvm/kvm/vcpu/mod.rs advertises Sse, Sse2 and Fxsr in guest
CPUID.
src/libs/nvx-crt0/src/lib.rs (_do_start) aligns the stack to 16 bytes on both
architectures, which is the precondition for movaps stack spills.
- Userland SSE/SSE2 integration tests exist:
src/tests/integration/test-rust-arch/src/{sse,sse2}.rs.
Relevant history: [kernel] E: Add Initial SIMD Instruction Support (2025-08-28),
[kernel] E: FPU save/restore and [kernel] F: Lazy FPU Context Switching (2025-09-05) —
all predating the toolchain flag.
Note that only the kernel Rust targets disable SIMD (build/targets/x86-kernel.json and
x86_64-kernel.json carry -sse,-sse2,...,+soft-float). The user targets do not.
Proposed change
Remove the NANVIX_ARCH == "x86" branch and the LIBUNWIND_ADDITIONAL_COMPILE_FLAGS
setting from configure_stage1() in z.
Acceptance criteria
If the i686 build or unwinding regresses, keep the guard and replace it with a comment
recording the actual reason, so this does not get re-investigated.
Summary
The stage 1 runtimes configuration builds libunwind with
-mno-sse -mno-sse2fori686-unknown-nanvix. That guard predates SSE support innanvix/nanvixand appears to beobsolete: Nanvix has provided full userland SSE/SSE2 support since 2025-08-28. The flags
should be dropped after verifying a stage 1 build and the smoke tests.
Current state
configure_stage1()inz:The flag was unconditional when only i686 was supported (added in
[Nanvix] Add build orchestrator, 2026-07-02).[Nanvix] Add x86_64 toolchain supportmade it conditionalrather than removing it, because
-mno-sseis invalid on x86-64 — SSE2 is part of theSystem V AMD64 psABI (
xmm0-xmm7carry float/double arguments and return values), soClang rejects such code with
error: SSE register return with SSE disabled.Why the i686 guard looks obsolete
Evidence from
nanvix/nanvix:src/kernel/src/hal/arch/x86/cpu/mod.rsand.../x86_64/cpu/mod.rsabort boot unless(sse || sse2) && fxsr, then callfpu::init().src/kernel/src/hal/arch/shared/cpu/fpu.rsclearsCR0.EM, setsCR0.MP, setsCR4.OSFXSRandCR4.OSXMMEXCPT, masks all MXCSR exceptions, and snapshots an initialFXSAVEimage used to seed new threads.src/kernel/src/pm/process/manager/mod.rsimplements lazy FPU context switching:CR0.TSis set on context switch,#NMroutes tohandle_fpu_exception(), which clearsTS,
fxsaves the previousFPU_OWNER_TID's area andfxrstors the current thread's.src/kernel/src/pm/process/manager/signal.rssaves/restores the 512-byteFXSAVEimageas part of the signal frame.
src/uservm/src/vmm/microvm/kvm/vcpu/mod.rsadvertisesSse,Sse2andFxsrin guestCPUID.
src/libs/nvx-crt0/src/lib.rs(_do_start) aligns the stack to 16 bytes on botharchitectures, which is the precondition for
movapsstack spills.src/tests/integration/test-rust-arch/src/{sse,sse2}.rs.Relevant history:
[kernel] E: Add Initial SIMD Instruction Support(2025-08-28),[kernel] E: FPU save/restoreand[kernel] F: Lazy FPU Context Switching(2025-09-05) —all predating the toolchain flag.
Note that only the kernel Rust targets disable SIMD (
build/targets/x86-kernel.jsonandx86_64-kernel.jsoncarry-sse,-sse2,...,+soft-float). The user targets do not.Proposed change
Remove the
NANVIX_ARCH == "x86"branch and theLIBUNWIND_ADDITIONAL_COMPILE_FLAGSsetting from
configure_stage1()inz.Acceptance criteria
i686-nanvixwithout the flags../z verifyand./z testpass fori686-nanvix.unwinds correctly on i686 (runtime check, not just a build check).
x86_64-nanvix.If the i686 build or unwinding regresses, keep the guard and replace it with a comment
recording the actual reason, so this does not get re-investigated.