Repository navigation
Conversation
…en per idle period acpiserver reads each processor's _CST and _CSD and hands the kernel, through a new op on the acpi claim, only the states it may enter as they are: Intel FFH MWAIT states, and off Intel the SystemIO states the core traps. The kernel checks each against the CPU that will enter it (toyos-userbound::idle) and chooses, per idle period, the deepest state whose exit fits the held wake bound, whose residency fits before the next timer, and that the CPU's recent unforeseen wakes admit. A timer deadline is met by waking early by the state's exit. A wake forward prefers the shallowest sleeper. The processor _OSC commits ToyOS's claim (Intel bits 4 and 9) with no query: Table 1's bits say what OSPM is capable of (302223-007 section 2.1), and the T14's query answers 0x1 whatever is asked. A WakeLatency object, made through the new WAKE_LATENCY right, holds every idle CPU to waking within a bound; soundserver holds half a period while a stream plays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cords The AMD bench's type-3 state, withheld for want of a family 17h statement that its I/O C-states keep caches coherent, and AArch64's wfi-only idle each get a record with an exit. The AML track, the doorbell track and the scheduler/clocks track say what changed for them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s three blocks Under ToyOS's committed processor claim the T14's first processor loads three blocks, its _CST's among them (916, 459 and 1162 bytes, as the check outside the tree read them on its dump), and every processor's _CST hands over MWAIT 0x31 and 0x60; the AMD bench hands over port 0x414 and withholds its type-3 0x415. The row now holds each bench to that, and to no declaration refused by the kernel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The history is eight bytes, so it is one word its CPU alone reads and writes, with no hand-written Sync and no unsafe cell. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…iers are two bindings Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… stopping machine The hold is a value kept for its drop, which an assignment never read denies in the guest build. A _CST or _CSD evaluation refused because the machine is stopping ends the declarations, as the server's other walks do, rather than counting the processor unread. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Design round, as approved (orchestrator, 2026-10-27, under the owner's direction for this work that day). The rulings on it:
One addition since the design: a CPU that only its history holds shallow revisits after the deeper state's residency. Without it, an idle CPU could stay in C1 indefinitely and hold the T14's bin down. The design as written: Deep idle: design (stage 5), for architecture check before implementationWorktree 0. Facts this rests on (M1, read tonight)Each fact is taken from the vendor document or the spec, or measured with our own interpreter on the benches' dumps. That measurement used #875's out-of-tree harness, rebuilt against this worktree (
What the documents say:
1. Ownership
Without a declaration, or with one refused, every CPU stays in C1. That is logged once; it is expected absence, not an error. No kernel thread is added, and all work stays in the idle loop and is bounded. 2. The kernel/acpiserver interface
3. The wake-latency limit
4. The selection rule (pure,
|
Review r1: deep idle (head 59dcd1f)Architecture. The ownership is right. acpiserver owns ACPI semantics: it evaluates What I verified by reading the code.
Blockers
Suggestions
Evidence
SEND BACK |
Review r1: - A port state's fence is the holder's own port policy (firmware::port), as every AML port read meets: no CStateBaseAddr read and no family gate, so every AMD family gets its declared states and no CPU can #GP on an MSR it lacks. - The cst header says why an Intel FFH state of type 3 is handed over: its only OSPM duty is bus-master avoidance (302223-007 Table 4), and the processor flushes what a C-state powers off as it enters it (SDM Vol. 3B section 20.19.6.4). - The boundary refuses a residency shorter than the exit, zero among them, which the early wake before a deadline needs. - A hold holds from when it is made: the idle CPU publishes its exit, fences and reads the bound again; the hold stores the bound, fences and wakes every CPU whose exit exceeds it. - The AArch64 header and the track's "built on branch" line say what is true. - The timer plan, the foreseen test and the declaration's words are pure and host-tested; the foreseen test has a tick's slack. The metal readings: - The T14's cpu.clock stayed at 3789 in 16 of 17 group starts where the always-deepest control reached 4189 in 10: a CPU the history held in C1 needed five quiet revisits at C3's residency, about 10 ms, longer than cpu.clock's 5 ms window. A CPU now revisits after the next deeper state's residency, and a revisit nothing interrupted clears the history of each state it covered: it climbs a state per residency. - The AMD's IPC round trips were 1.28-1.32 times A's: every shallow idle armed its revisit with arm_within, an uncached read and a write of its xAPIC timer. The pass has just armed the timer for the token's instant, and the revisit and the early wake are never later, so one write arms them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mer write The orchestrator's ruling of 2026-10-28: an idle cycle costs one timer write, as on main. Machine::idle_plan chooses the state in the pass, with the timer the CPU would sleep under; the plan's own wake, the early wake before a deadline or the revisit, joins the pass's timer plan through TimerPlan::no_later_than, and the SleepToken carries the plan to the wait, which touches no timer. The simulator plans C1 by default. The port fence's trust argument is stated at the boundary, with what a declared port that is no trapped C-state request costs: a read that returns at once, never a hang. osbench reads, around each crunch and malloc_churn row, each CPU's busy fraction, the clock it ran at (APERF/MPERF), its core's C6 and C7 residency (MSR_CORE_C6/C7_RESIDENCY, SDM Vol. 4 Table 2-20, now counters), the kernel's deep idles, and the CPUs the row's threads ran on. A host test holds that a spawn's placement reads no idle exit. The idle track records the deep states' exit cost with main's and Linux's figures, as ruled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g's sleep pokes it A core enters a core C-state only when every thread of it asks for one, so a thread waiting deep beside a running sibling saves nothing and pays the deeper exit; on the AMD bench it also cost the running sibling. Round 2's instruments read it: the one slow deflate (66.77 ms against 63.0) ran beside a sibling 99 % in port 0x414, every fast one beside a sibling in C1, at the same clock. On the T14 two runs beside deep siblings were as fast as without. A CPU whose plan is deeper than C1 marks itself held, fences and reads its siblings; a running one keeps it in C1. The sibling that sleeps publishes SLEEPING, fences and pokes each held sibling, which chooses again: an event, so a held CPU is not left in C1 when its core could go deep. Nothing is held where nothing deeper than C1 is declared. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ster A clock held below the one-core bin at a group's start means three or more cores ran then; the roster, read on the measuring CPU before and after the clock's few milliseconds, names the processes that did, and wakes no other CPU. The counters, whose read kicks every CPU, stay around rows of seconds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… boots Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r2: deep idle (head f6510de)Architecture. The fold is the right shape. The pass asks r1 blockers.
Verified by reading.
Blockers
Suggestions
Evidence
SEND BACK |
…s control Round 2 put a CPU beside a running SMT sibling in C1 because one AMD deflate row ran 6 % slow beside a sibling in port 0x414. The third boots read the same slow deflate with the deep states off, every idle CPU in C1: both slow boots placed deflate on CPU 4, the six fast ones elsewhere, at the same clock. The rule answered nothing, and review r2 found three defects in it (a stale held flag, the history learning the kernel's own poke, and two idle siblings holding each other), so it is removed whole. The spread is recorded as a property of the bench. - The hold's kick, `CpuHandles::wake_slower_than`, moves into the pure scheduler beside the tiebreak that reads the same word, with a host test: it kicks each other CPU above the bound once, not the holder and not one at or below it. - `idle_exit`'s contract says what it now is: published before the wait and fenced against the bound, 0 while awake, the hold's input and the wake forward's tiebreak. - The history's update is the plan's own (`Plan::learn`), and a revisit clears the residency it was armed for even when its timer fired up to `FORESEEN_SLACK` early. - `History::forget` is gone: a new declaration already starts from a fresh history. `Choice` and `Plan` lose their unused `Default`, and the helpers only `Plan` calls are private. - The core C6/C7 residency models are cited section by section to SDM Vol. 4 325462-093: each §2.11-§2.16 opening and §2.17's name the model as supporting Table 2-20, which defines 3FDH and 3FEH, and of the tables that supersede it only Table 2-57 (06_AFH) names either, defining both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r3: deep idle (head d286ddd)Architecture. The round removes code. d286ddd is +124/−150, and the branch now stands at +2664/−193 against origin/main. The SMT-sibling mechanism is gone: the held flag, the poke, the hold-shallow wrapper, its TestHw r2 blockers
Suggestions taken
Evidence
FindingsNo blockers. SUGGESTIONS
LAND The landing waits on the B4 boots the PR has already staged, and that decision is the orchestrator's. |
…t 0 again The group-start roster instrument (6a0fa3f) opened the counters' Diag before each group's first row, and Diag took the process's one SysCap endowment. `osbench identity` and `osbench fair` each take it again for a row of their own, found nothing and refused, so both groups exited 1 on every bench in every boot since. The metal judge says so when it is run over the readbacks; it was not run. The endowment is now taken once, by `sys::syscap()`, and every user borrows it: the counters' Diag, identity's inventory read and fair's job builder. `osbench_capability_groups_exit_0` boots benchcase.toml under QEMU with those two groups alone and holds each to exit 0, so a capability taken twice fails a PR's own QEMU run rather than a nightly bench. Review r3's suggestions: - A wait the bound or a new declaration sends to C1 publishes exit 0, so `idle_exit` is what the CPU waits in. - `Plan::learn`'s Unforeseen and Deadline arms have a test. - The AMD deflate finding records only what was measured. B4 ran the slow mode on CPU 10, which earlier read fast, so the record is renamed: the mode varies per boot at the same clock and with no running neighbour. - The track names #1066's exit as unmet, 8 to 10 of 17 group starts against Linux's 13, with acpiserver's start-up a measured busy core at four. - A stray blank line goes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The T14's group starts at ratio 42 across six boots with the deep states read 8, 8, 8, 10, 10 and 5: only sched, files, ipc and work in all six, so a spread from boot to boot. The A* testcases control puts soundserver's worst IRQ lateness where the deep states put it on both benches, the AMD's 2661 µs window included, so the deep states move neither. The AMD deflate finding counts B5's fast run, three slow of ten. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r4: deep-idle at d60d727 (focused: d286ddd..d60d727, plus the uncommitted records edit in the worktree)Architectural assessmentThe defect fix has the right shape. The process takes its one The C1-fallback publish in Size: about +20 lines of production code, and the net change in osbench is close to zero. Tests: +13 unit lines and +34 lines for the QEMU check. Metal at d60d727 (run5), which I checked against the readbacks:
FindingsBLOCKER 1. Records at the head don't state the final measured state.
BLOCKER 2.
BLOCKER 3 (PR body; the orchestrator owns the correction). The body describes a pre-B5 state.
SUGGESTION. No other issues in the changed code. SEND BACK |
…ames its machine The track states soundserver's worst IRQ lateness over every window line of each testcases boot: T14 181 to 572 µs with every idle CPU in C1, 0 to 564 with the deep states; the AMD 0 to 2661 both ways. The registration of `osbench_capability_groups_exit_0` names QEMU x86-64's q35 and drops its history, which 49a98e3's message carries. An assertion says the deadline is the scheduler's own, pulled in by the exit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One conflict, `sdk/abi/src/syscall.rs`: main's #1070 took 146 for `SYS_VM_REMAP`, which this branch had given `SYS_WAKE_LATENCY_HOLD`. Main keeps 146; the wake-latency hold is 147 and the profile has 149 bins, its last the bin for numbers the ABI does not issue. Every caller names the constant, not the number. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The merge resolution at 145e659 was checked by the orchestrator: syscall renumbering only (VM_REMAP 146, WAKE_LATENCY_HOLD 147, 149 profile bins), with host CI, the osbench QEMU check and the image build all exit 0. Metal at d60d727 (B5 plus A* testcases, both benches) passed the harness judge; the merge touches neither the idle path, the scheduler nor osbench's instruments. Review r3 and r4 LAND. Landing. |
… CPU whose readings are not the row's is refused The instrument around crunch, churn and tail divided by the row's wall time what the counters measured over theirs. The two differ: a counters read within 10 ms of another is served that read's values, so a reading can predate its row or be the same reading twice. Deep idle was also credited per period at its end, so a period begun before the row counted whole. The shipped rows printed deep fractions up to 2278 permille. Each CPU's window is now the difference of the counter stamps its two readings carry, converted by the clock page, and `osbench_rules::window` refuses it by name when the readings are one or span more than 10 % off the row. Busy and C6/C7 fractions and the clock are of that window, and both `window_us` and `row_us` are printed. Deep idle is printed as the periods that ended in the window and their microseconds, which is what the kernel counts. The rule is host-tested: a shared reading, a reading taken before a short row and a missing stamp are refused, and the fractions and the clock are of the readings' window. The kernel serving an old reading as new is recorded with an owner and an exit, for the track's follow-up. The track's C7 and clock claims are re-derived from rows whose readings matched them: the deflate thread busy 989 permille across its row, at 4.23 GHz against 3.83, every other core 99.5 to 99.9 % in C7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No conflict. Main holds syscalls to 146 (SYS_VM_REMAP), so the wake-latency hold keeps 147 and the profile its 149 bins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…time The kernel credits a deep period's nanoseconds when it ends, so the time of the periods that ended in a window includes what they spent before it. B6 printed it above `window_us` on 13 T14 and 31 AMD lines. A count of ended periods is true of the window; their time is no figure of it, so it goes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r5: deep-idle at 55269e9 (focused: b1ae80c, and the merge of main 23f34b5)Architectural assessmentThe fix has the right shape. It takes each CPU's window from the stamps its own two readings carry, and every fraction is computed over that window. I checked the cases you asked about against the code:
What remains wrong is not the window but the rate the instrument assumes for MPERF. FindingsBLOCKER 1.
BLOCKER 2.
BLOCKER 3. SUGGESTION 1.
SUGGESTION 2.
SEND BACK |
…unded by the join and the reads' cost Neither SDM Vol. 3B §17.2 nor AMD's APM Vol. 2 §17.3 defines the rate MPERF counts at: only the APERF/MPERF ratio is architectural. The instrument divided MPERF by the TSC for a busy fraction and multiplied the ratio by the TSC's rate for a clock, so a fully busy T14 CPU read 989 permille and its clock 1 % above `cpu.clock`'s, 4230 against 4189. The ratio is now printed as `aperf_mperf_permille` and neither figure is derived from it; the clock stays `cpu.clock`'s. Core C6/C7 residency counts at the TSC's rate (SDM Vol. 4 Table 2-20) and stays a fraction of the window. The kernel leaves Sierra Forest (06_AFH) out of the residency counters, as Table 2-57 counts its residency at the P1 clock, not the TSC's rate that `Counter::CoreC6` promises. A CPU's window now stands only between the row less its two reads' cost and the row plus the kernel's 10 ms join, the two ways a reading can differ from the row, and a CPU the kernel read stale is refused by name. The row is the span from the first read's call to the second's return, and `reads_us` is printed beside it. The track takes the clock step from each row's `mhz`, `cpu.clock`'s reading beside it: 4187 to 4189 MHz in the seven boots with the deep states against 3788 to 3789 in the four without. It links the stale-reading issue and says what the three diagnostic boots read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…te finding names B6 and no MPERF-rate clock `Instant` is used only by the ToyOS half of the instrument now, so the Linux build's clippy refused the import. The AMD deflate finding counts B6, 65.7 ms on CPU 0, and compares the boots by the APERF/MPERF ratio rather than a clock that assumed MPERF's rate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…step Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r6: deep-idle at 5c812f1 (focused on 1d46a3c, 862f68c and 18fe4e1, plus the records-only efe09aa and 5c812f1)Architectural assessmentr5's points are resolved, and the instrument now prints only figures that have a documented rate.
B7 readbacks (
Records. I checked the records at 5c812f1 against the readbacks:
Findingsr5 B1-B3 and S1-S2 are resolved. No new blocker. SUGGESTION 1.
SUGGESTION 2.
SUGGESTION 3.
LAND |
|
Focused r6 LAND at 5c812f1, which adds only records after 18fe4e1, the code B7 booted. B7: the harness judge exits 0 on both benches, and every instrument figure is in range. r6's suggestions S1-S3 (naming JOIN_NS in the stale-reading issue's exit, the unread DeepIdleNanos counter, the AMD record's MPERF comparison) go to the counters follow-up on this track, which rewrites that contract. Landing. |
CpuHandles::place ranked a spawn's candidates by queue, sleep and busy SMT siblings, and broke every remaining tie by the rotation alone, so a spawn woke a CPU in its deepest declared state as readily as one in C1. The key now ends in the exit each idle CPU publishes, the cost idle_near already weighs for a wake forward: among free cores' sleepers with equal queues the shallowest is woken, the rotation decides only between equal exits, and a free core still comes before a shallow sibling of a running one. This reverses #1073's choice that a spawn reads no idle exit, under the accepted scheduling model that placement accounts for wake cost; its test is replaced by one that states the new order. The simulator plans C1, where every exit is 0, so its scenarios place as before. It was shelved because osbench's statistical staging could not reach a parked thread's CPU once that CPU idled deep; the benches now pin their threads, so a placement rule no longer decides whether a row can run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CpuHandles::place ranked a spawn's candidates by queue, sleep and busy SMT siblings, and broke every remaining tie by the rotation alone, so a spawn woke a CPU in its deepest declared state as readily as one in C1. The key now ends in the exit each idle CPU publishes, the cost idle_near already weighs for a wake forward: among free cores' sleepers with equal queues the shallowest is woken, the rotation decides only between equal exits, and a free core still comes before a shallow sibling of a running one. This reverses #1073's choice that a spawn reads no idle exit, under the accepted scheduling model that placement accounts for wake cost; its test is replaced by one that states the new order. The simulator plans C1, where every exit is 0, so its scenarios place as before. It was shelved because osbench's statistical staging could not reach a parked thread's CPU once that CPU idled deep; the benches now pin their threads, so a placement rule no longer decides whether a row can run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CpuHandles::place ranked a spawn's candidates by queue, sleep and busy SMT siblings, and broke every remaining tie by the rotation alone, so a spawn woke a CPU in its deepest declared state as readily as one in C1. The key now ends in the exit each idle CPU publishes, the cost idle_near already weighs for a wake forward: among free cores' sleepers with equal queues the shallowest is woken, the rotation decides only between equal exits, and a free core still comes before a shallow sibling of a running one. This reverses #1073's choice that a spawn reads no idle exit, under the accepted scheduling model that placement accounts for wake cost; its test is replaced by one that states the new order. The simulator plans C1, where every exit is 0, so its scenarios place as before. It was shelved because osbench's statistical staging could not reach a parked thread's CPU once that CPU idled deep; the benches now pin their threads, so a placement rule no longer decides whether a row can run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CpuHandles::place ranked a spawn's candidates by queue, sleep and busy SMT siblings, and broke every remaining tie by the rotation alone, so a spawn woke a CPU in its deepest declared state as readily as one in C1. The key now ends in the exit each idle CPU publishes, the cost idle_near already weighs for a wake forward: among free cores' sleepers with equal queues the shallowest is woken, the rotation decides only between equal exits, and a free core still comes before a shallow sibling of a running one. This reverses #1073's choice that a spawn reads no idle exit, under the accepted scheduling model that placement accounts for wake cost; its test is replaced by one that states the new order. The simulator plans C1, where every exit is 0, so its scenarios place as before. It was shelved because osbench's statistical staging could not reach a parked thread's CPU once that CPU idled deep; the benches now pin their threads, so a placement rule no longer decides whether a row can run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CpuHandles::place ranked a spawn's candidates by queue, sleep and busy SMT siblings, and broke every remaining tie by the rotation alone, so a spawn woke a CPU in its deepest declared state as readily as one in C1. The key now ends in the exit each idle CPU publishes, the cost idle_near already weighs for a wake forward: among free cores' sleepers with equal queues the shallowest is woken, the rotation decides only between equal exits, and a free core still comes before a shallow sibling of a running one. This reverses #1073's choice that a spawn reads no idle exit, under the accepted scheduling model that placement accounts for wake cost; its test is replaced by one that states the new order. The simulator plans C1, where every exit is 0, so its scenarios place as before. It was shelved because osbench's statistical staging could not reach a parked thread's CPU once that CPU idled deep; the benches now pin their threads, so a placement rule no longer decides whether a row can run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Idle CPUs now wait in the deep states their firmware's
_CSTdeclares, chosen per idle period by the pass that puts them to sleep. The wake-latency bound has explicit authority (Rights::WAKE_LATENCY,SYS_WAKE_LATENCY_HOLD= 147). This is stage 5 of the scheduler/audio/idle plan. It takes the T14's one-thread clock from ratio 38 to 42 at 5–10 of 17 osbench group starts (Linux: 13) and runscrunch.single1.10 times faster.issues/idle-cpus-enter-the-c-states-cst-names.mdstays open, because #1066's exit is unmet.Problem
ToyOS idled in
sti; hlt(C1). On the T14 (i5-1135G7), turbo counts a C1 core as active, soMSR_TURBO_RATIO_LIMITheld a one-thread load to ratio 38 (3789 MHz) instead of 42 (#1066).What changes
The states come from the firmware, interpreted in userland.
_CSTand_CSD(system/acpiserver/src/cst.rs), and again on that processor'sNotify(…, 0x81).op::IDLEon theacpiclaim, only the states that need nothing done around their entry.hlt;_CSDcoordinates in software._CSTdeclares none).The processor
_OSCcommits ToyOS's claim (Intel bits 4 and 9) with no query. This is the orchestrator's ruling of 2026-10-27, under the owner's direction.The kernel's boundary (
lib/userbound/src/idle.rs) refuses:acpiholder could not read itself (kernel-kept, protected or lent).The port comes from the firmware's AML, which is trusted platform code, so that fence needs no list of parts (ruled 2026-10-28). A declared port that is not a trapped C-state request returns at once: a short wake, never a hang.
The pass chooses the idle state, and its timer plan arms the choice's wake: one timer write per idle cycle, as on main (ruled 2026-10-28).
Machine::idle_planis asked in the pass, against the timer the CPU would sleep under.TimerPlan::no_later_than. It is either the early wake before a deadline (by the state's exit) or the revisit.SleepTokencarries the plan to the wait, which touches no timer.The selection rule (
kernel/pure/sched/idle.rs) picks the deepest state that satisfies all three:When the history alone holds a CPU shallow, the CPU revisits after the next deeper state's residency. A revisit that nothing interrupted clears the history it covered, so a CPU left idle climbs one state per residency.
Waking: a wake forward prefers, among equally near free cores, the one whose state is quickest to leave. Spawn placement is unaffected; a host test holds it.
The wake-latency bound has explicit authority.
SysCap::hold_wake_latencytakes theWAKE_LATENCYright.CpuHandles::wake_slower_than, host-tested).Instruments:
countersrow gains the deep-idle count and nanoseconds. It also gains core C6/C7 residency on each model whose SDM Vol. 4 (325462-093) section names Table 2-20, the table that defines 3FDH and 3FEH. Of the tables that supersede it, only Table 2-57 names either address, and it defines both (quotes).crunchandmalloc_churnrow, and acrosstail, osbench notes the CPUs the row's threads ran on. For each CPU, over the readings' own window, it also notes:cpu.clock's;osbench_rules::window, host-tested). The window comes from the counter stamps the two readings carry. It stands only between the row less its two reads' cost and the row plus the kernel's 10 ms join; outside that, or where a CPU was read stale, the CPU is refused by name.window_us,row_usandreads_usare printed. The kernel's join is recorded inissues/a-counters-read-within-10-ms-of-another-returns-the-older-reading-as-new.md.Counter::CoreC6promises.cpu.clock, osbench names the processes that ran beside it, from the roster. A counters read kicks every CPU, which would disturb a 5 ms reading.Diag, which took the process's oneSysCapendowment first.osbench identityandosbench fairthen found none and exited 1 in every B3 and B4 boot. The metal judge reports it (r4judge4-*), but it was never run over those readbacks.sys::syscap()is now the one owner of the endowment.osbench_capability_groups_exit_0(QEMU, x86-64) boots benchcase.toml with those two groups and holds each to exit 0. The image's endowments are not host-buildable, and the benches run osbench only nightly.AArch64 keeps
wfi(issues/aarch64-cpus-idle-only-in-wfi.md).Measured
f6510defd, alternating A*, B3, A*, B3 on each bench. A* has the deep states off, all else equal.d286dddf3,d60d727aa,55269e97fand18fe4e150.crunch.single.deflatemalloc_churn.1048576.t1cpu.clockat 4189, of 17 group startsipc.reqrep.8(ns)malloc_churn.1048576.t1(each row'smhz,cpu.clock's reading) is 4187–4189 MHz in all eight boots with the deep states, against 3788–3789 in the four A* boots. Across deflate, every core but the thread's is 99.5–99.9 % of the row in core C7. Linux reaches 4190 at 13 group starts.t14-2-B3-boot-groups-timed.txt). acpiserver ran for each whole clock window: a measured busy core.issues/the-amd-benchs-deflate-runs-6-percent-slow-in-some-boots-at-the-same-clock.md).time.sleep_late: 1 µs 1.5×, 10 µs 1.4×, 10 ms 1.6×; 1 ms 1.25× and 0.82×.wake.storm.drain: w4 3.3–3.4×, w16 1.9–2.2×, w64 1.5–1.6×.time.sleep_late: 10 µs 1.4×, 100 µs 1.1×. The AMD's 1 ms row improves 5.8×.pingpong.pipe.same_cpu(7605 against 5.6k ns) andwake.storm.call.w64(15100 against 9.6–10.1k). Their other B3 runs read at A*.hda_tonepasses with no underruns, andacpi_tables_loadedpasses with every CPU's declaration kept.test_rs_wake_onto_busyfails on every revision; it is a standing defect.test_rs_pci_reclaimasks the AMD for an Intel NIC it lacks.Checks
cargo run -- --ci hostosbench_capability_groups_exit_0cargo run -- --build-onlydeep_permilleabove 1000; the reason for the fix (r6)deep_ended_usexceeded its window on 44 lines and was removed (r7)aperf_mperf_permille188–1749 (T14) and 776–2358 (AMD); C7 0–999 ‰ (r8)PASS osbenchon both benches;hda_tone,hda_tone_resampledandacpi_tables_loadedpass on both A* boots (r5 logs)osbench_capability_groups_exit_0osbench_identityexited 1, the defect fixed here.hda_tone,hda_tone_resampledandacpi_tables_loadedpassPlan::learn's arms swappedhda_plays_to_the_controller_that_reaches_an_output,acpi_press_is_one_sciRisks
sti; inentry relies on the Family 16h BKDG for wake on interrupt.After d60d727 the branch changes only
issues/, a test registration comment and an assertion message, then merges main twice:SYS_VM_REMAP(#1070) keeps 146 and the wake-latency hold takes 147, which #1077 also claims, so whichever lands second renumbers. Then it fixes the counters instrument.🤖 Generated with Claude Code