Skip to content

feat(cpu): start every processor from a known x87, SSE and AVX state, with XSAVE enabled - #805

Merged
MasterLaplace merged 7 commits into
mainfrom
feat/85-known-extended-state
Nov 9, 2026
Merged

MasterLaplace merged 7 commits into
mainfrom
feat/85-known-extended-state

Conversation

@MasterLaplace

@MasterLaplace MasterLaplace commented Nov 8, 2026 •

Copy link
Copy Markdown
Owner

What

Every processor starts from a known x87, SSE and AVX state. extended_state_initialize_on_this_processor runs on the bootstrap processor before any constructor, and on each application processor at its C entry:

  • CR0.NE and CR0.MP set, CR0.EM and CR0.TS clear: x87 errors raise #MF instead of going through FERR#;
  • CR4.OSFXSR and CR4.OSXMMEXCPT, plus CR4.OSXSAVE when CPUID offers XSAVE;
  • XCR0 from extended_state_components_to_enable: x87, SSE, AVX and the three AVX-512 components, each only with those XSETBV requires; never MPX, PKRU or AMX;
  • FNINIT and LDMXCSR give the x87 control word 0x037F and the MXCSR 0x1F80.

This replaces boot.S's inline CR0 and CR4 block.

Verify

./build.sh --server, then qemu-system-i386 -machine q35 -m 1G -smp 2 -kernel kernel/lpl.kernel -display none -serial file:serial.log, with -cpu max or -accel kvm -cpu host:

  • red on main: CR0 0x80010013, XCR0 0 instead of 7;
  • q35 863/0, -cpu max with 4 processors 865/0, KVM 865/0, pc 857/0;
  • the XCR0 rule against 12 sets worked out by hand from SDM vol. 1 §13.3;
  • 9 mutants, each failing under -cpu max: no NE, no mask, no AVX-512 rule, no SSE rule, no FNINIT, no LDMXCSR, a flag in the MXCSR loaded, no call on the APs, no OSXSAVE (the boot faults).

Not in it

  • The interrupt stubs keep FXSAVE: a handler uses SSE at most.
  • XCR0's first caller is the context switch stacked on this PR.

Refs #85

@MasterLaplace MasterLaplace added the type:feature A new capability label Nov 8, 2026
@MasterLaplace MasterLaplace self-assigned this Nov 8, 2026
@github-project-automation github-project-automation Bot moved this to To review in Laplace Nov 8, 2026
@MasterLaplace
MasterLaplace added this pull request to stack #807 November 8, 2026 19:50
@MasterLaplace
MasterLaplace merged commit c6791e0 into main Nov 9, 2026
16 checks passed
@MasterLaplace
MasterLaplace deleted the feat/85-known-extended-state branch November 9, 2026 00:58
@github-project-automation github-project-automation Bot moved this from To review to Done in Laplace Nov 9, 2026
MasterLaplace added a commit that referenced this pull request Nov 9, 2026
…e with the strongest XSAVE the processor offers (#806)

## What

`cpu_context_switch(from, to)` switches between two ring-0 contexts on
one processor. It saves EBP, EBX, ESI, EDI, the stack pointer and the
extended state.

- **The policy for SIMD in ring 0**, written on `cpu_context_switch`:
every switch saves eagerly, never lazily through CR0.TS (LazyFP). A
context that never touched its vector registers costs only the header.
- Each context names its save. `extended_state_preferred_save` takes the
SDM's order: XSAVES, then XSAVEOPT, then XSAVE. FXSAVE is offered only
while XCR0 enables nothing past SSE.
- `cpu_context_prepare` starts a context at its entry, from the initial
state, on a 16-byte-aligned stack. An entry that returns is reported on
COM1, then its processor halts.
- `cpu_context_adopt` makes the running code a context. It ends with an
XRSTOR of empty mask, so any area may be adopted, even the one the
processor last restored from.
- `tools/instructions.sh --cpu` names QEMU's processor model, so a
budget can count the XSAVE path.
- First caller outside the tests: the tasks of #259.

## Specification: said, says, because

#85's criterion said "a test preempts a task". It now says a context
finds its registers after another context ran, because no task exists
yet; preemption moves to #259.

## Verify

`./build.sh --server`, then `qemu-system-i386 -machine q35 -m 1G -smp 2
-kernel kernel/lpl.kernel -append lpl.test=context_switch.*`, with `-cpu
max` or `-accel kvm -cpu host`:

- Red before: registers lost and inherited, and under KVM the area
adopted again kept its initial state.
- Server: q35 868/0, `-cpu max` 871/0 with 2 and 4 processors, KVM
871/0, pc 862/0, KVM pc with 4 processors 864/0. Satellite: `-cpu max`
721/0, KVM pc 714/0.
- Under KVM, integer contexts write no SSE or AVX byte with XSAVEOPT or
XSAVES.
- 8 mutants, each failing under TCG or KVM: XSAVE for XSAVEOPT, no
XRSTOR, FXSAVE only, no XCOMP_BV, no MXCSR, a misaligned frame, FXSAVE
offered with AVX, no empty restore.
- `context-switch.debug.budget`: 58,852 instructions for 1,000 switches.
Server tick unchanged.

## Not in it

- ZMM and opmask registers are not probed: no machine at hand has
AVX-512. #85 stays open for that, and for its runs on real hardware.

Stacked on #805. Refs #85
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:feature A new capability

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant