Repository navigation
Counters: every CPU answers a read for itself on its kick vector, under the counters and trace rights - #705
Conversation
…er the counters and trace rights `SYS_COUNTERS` answers one record per online CPU: its own counter stamp, its firmware-interrupt count (`MSR_SMI_COUNT`), `APERF` and `MPERF`, and the kicks it took, each read by that CPU itself. A read is a round of `shootdown::Shootdown`'s protocol: the reader issues a generation, kicks every other CPU, answers for its own, and parks on a watch until every CPU has answered or 100 ms after the issue; a CPU silent past that is stale with the last block it published. Rounds within 10 ms of an issue are one. The kick leaves the timer's vector: x86-64 raises it on 0xFC through `device_irq_entry!`, AArch64's SGI 0 counts as a kick, and both kick handlers answer the round. Every IPI is raised after a fence that orders the stores it announces (`mfence; lfence` before the x2APIC ICR write, `dsb ishst` before `ICC_SGI1R_EL1`), which closes `issues/kernel/an-ipi-can-overtake-the-stores-it-announces.md`. Which model-specific counters a CPU has is `toyos_cpuvuln::counters`, Linux `arch/x86/events/msr.c` at the pinned Ubuntu tag, decided by each CPU over its own CPUID at bring-up, whose first sample reads each admitted MSR once. `MSR_SMI_COUNT` is refused under a hypervisor, a departure from Linux. `Rights::COUNTERS` reads the stamp and the SMI count; `Rights::TRACE` beside it the counters that time programs. `inspect` and `test-runner` hold both, and `inspect kernel.*` renders them. The panic console's seqlock becomes `seqlock::Published<N>`; a loom model holds the reader's `served` acquire to the answer it copies, with its negative control. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
|
Mutation patches for this branch, each applied as a checked patch (
|
|
T14 at
Logs: |
Review round 1 — #705 at
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
… answers, and review round 1's records - `demand_syscap` answers every right the handle holds, read under the guard that checked it, so `SYS_COUNTERS` looks its handle up once: a sibling closing it between two lookups can no longer be answered COUNTERS-only, and no error kind is swallowed. - A reader's kick of every other CPU and its answer for its own run under one `IrqGuard`, so the CPU the kick skipped is the CPU answered for, wherever the reader migrates. - `IrqWatch::post_in_place`'s contract names a thread's post, which the reader's answer and an inbox's poll wake already make. - `store_fence` is `wrmsr_fence`: it is `mfence; lfence`, not `sfence`. - The turbostat readings move beside their one reader, `tests/t14-linux/`, and both SOURCE files carry the commands; the Linux-readings issue points at the fixtures instead of repeating them. - The umbrella track no longer says nothing reads APERF, MPERF or MSR_SMI_COUNT. - Filed: the loaded T14 runs below Linux's clock, two CPUs idle busier than Linux's, toyos-cpuvuln's one consumer, and a readback lost to one ssh timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
|
Round 2 mutation m13 at diff --git a/kernel/src/syscall/machine.rs b/kernel/src/syscall/machine.rs
--- a/kernel/src/syscall/machine.rs
+++ b/kernel/src/syscall/machine.rs
@@ -282,3 +282,3 @@ pub(super) fn sys_counters(syscap: RawHandle, out: &mut UserBytesMut) -> u64 {
let rights = match demand_syscap(syscap, Rights::COUNTERS) {
- Ok(rights) => rights,
+ Ok(rights) => rights.union(Rights::TRACE),
Err(e) => return e.refuse(), |
|
T14 run at Images flashed in order, sha256 recorded at flash: Every CPU reports |
Review round 2 — #705 at
|
…roduce on a second boot Both issues filed for the counters row now name the orchestrator, which holds the T14, as the other two filed in the same branch do. The idle-busy finding gains the second boot's reading at a059144 (cpu0 1.35%, cpu7 1.42%), the same two CPUs as at ce1786f. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
Review round 3: #705 at
|
Its two busy CPUs reproduced across two boots (ce1786f, a059144), so it is real and reproducible; issues/README.md promotes such a finding. The exit keeps attribution first, then a fix or a fold to the row doc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
Review round 4: #705 at
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
The one conflict, toyos-explains-itself.md, keeps main's text less the clause "a user symbol is resolved by the kernel", which this branch makes false. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
#705 took syscall 124 for SYS_COUNTERS, so SYS_PORT_MINT becomes 125 and SYS_PORT_BADGE 126. The profile's bound assertion now names the highest number, SYS_PORT_BADGE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
…he branch's first design The owner ruled the perf-state read-back be rebuilt on #705's counters round: one round, one place, and the power envelope another counter behind the strict right. Every file this branch changed is taken as origin/main has it: the perf-state device class, its second shootdown round, its two actuators, the `toyos-perfstate` crate, the `perfstate` program and the metal harness's expected-panic boot go. What is kept, the kernel declaring the HWP request from the one CPU-state declaration, lands again in the next commit on top of what #705 provides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
…ds the power envelope back under TRACE The CPU-state declaration in control_regs gains the performance request: on a CPU toyos_cpuvuln::hwp admits (HWP, EPP, the package request and EPB enumerated, Intel family 6, not hybrid), every CPU clears IA32_HWP_INTERRUPT where it exists, sets IA32_PM_ENABLE, and only then reads IA32_HWP_CAPABILITIES and MSR_PLATFORM_INFO and writes IA32_HWP_REQUEST (intel_pstate's: min the package's maximum-efficiency ratio, max the highest level, EPP 0x80), IA32_HWP_REQUEST_PKG and EPB 6 whole, then logs and asserts each. A refused machine logs the reason once and writes none of them. The read-back rides #705's one round instead of a second: three counters, hwp_request, hwp_request_pkg and energy_perf_bias, each under Rights::TRACE (the owner put power under the strict right), present only where the declaration declared them. CPU identity is toyos-cpuvuln's: its third verdict, `hwp`, beside the vulnerabilities and the counters, and cpu::vendor now decodes CPUID.0 once for both kernel callers. The counters metal row holds every CPU's declaration (pm_enable=1) and its envelope in every read to its boot line, and every CPU's busy clock across the spin to the lowest Linux reached loaded on the same machine, which closes the defect that the T14 ran below it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
PR 1 of the counters + ACPI stage 1 design (lane A1 of the observability strategy): the general counters, their read, and the one cross-CPU request round. Stage 1 of ACPI (PR 2) reads its SMI flatness through this table.
What lands
SYS_COUNTERS = 124answers onetoyos_abi::counters::Recordper online CPU (56 bytes LE: CPU index, hardware id, flags, a word per counter), withSYS_DEVICE_INVENTORY's contract: an empty buffer is the CPU count and asks no CPU anything, a short oneResourceExhausted, one past the kernel's most CPUsInvalidArgument.Counterisstamp,smi,aperf,mperf,kicks; an absent counter has no word, never a zero;staleis a CPU that missed the read's bound, carrying the last block it published and the stamp it published it at. No CPU count is in the ABI.Rights::COUNTERS(bit 13) andRights::TRACE(bit 14),ALL0x7fff, each documented with what it discloses.demand_syscapanswers every right the handle holds, read under the same guard that checked it, soSYS_COUNTERSlooks its handle up once:COUNTERSrefused ends there, and what else the capability holds decides which counters are answered.kernel/src/counters.rs: a read issues a generation ofshootdown::Shootdown's protocol, then, under oneIrqGuard, kicks every other CPU and answers for its own, so the CPU the kick skipped is the CPU answered for; it parks on anIrqWatch(watch::wait_until) until every CPU has answered or 100 ms after the issue. Each CPU answers from its kick handler on both architectures, wherever it was, by publishing its block throughseqlock::Published<N>insideserve's closure. A read within 10 ms of the last issue waits on that round, so a holder makes no CPU take more than one kick per 10 ms. Never unbounded, never a panic.IrqWatch::post_in_place's contract names a thread's post, which the reader's own answer and an inbox's poll wake make.device_irq_entry!(Ring 3exit_to_user, mask-windows hooks),irq_census::Source::Kick; 0x20 is an expiry and nothing else. AArch64: SGI 0 counts asKick, notTimer, and answers the round with the preempt count raised. Every IPI is raised after a fence ordering the stores it announces:cpu::wrmsr_fence(mfence; lfence) before every x2APIC ICR write (Linux'sweak_wrmsr_fence),dsb ishstbeforeICC_SGI1R_EL1withnomemgone from both asm blocks (Linux'sgic_ipi_send_mask). This closesissues/kernel/an-ipi-can-overtake-the-stores-it-announces.md.toyos_cpuvuln::countersoverCounterFacts(vendor, signature,CPUID.1:ECX,CPUID.6:ECX), Linuxarch/x86/events/msr.cat the crate's pinned tag (Ubuntu-6.8.0-142.142, 53e5d07aac02): APERF/MPERF where leaf 6's ECX bit 0 says, any vendor;MSR_SMI_COUNTontest_intel's Intel family 6 models, outside a hypervisor; the list is intable.rsbeside the crate's other four tables. Each CPU decides on its own CPUID at bring-up (counters::bring_up, BSP afterarch::boot::interrupts, each AP inprocess::ap_idle), and that bring-up's first sample reads each admitted MSR once, so a wrong verdict is#GPat boot and never inside a read. It logscounters: cpuN reads smi=… aperf=… mperf=….inspectgains thekernelroot (kernel.cpu.<n>.{stale,hardware_id,<counter>}, rendered bytoyos_inspect::kernel), asked on the sameSysCapasdev.*, taken once.SysCap::countersin the SDK.system.tomlgrantsinspectcountersandtrace; the test estate'stest-runnerholds both intests/testcasesandtests/virtsmpcase; the supervisor's minted capability carries both, since rights only shrink from it (measured: without it the supervisor panicked narrowinginspect's duplicate).drivers/panic_console/published.rsbecomesseqlock.rs,Published<const N>, its loom model andseqlock-writer-fence-offkept.Shootdown::serve_if_owedanswers whether it served, so a kick that owes nothing posts nothing. Linux's turbostat readings of the T14 move beside their one reader,tests/t14-linux/, with aSOURCEcarrying their commands;toyos-cpuvuln/fixtures/t14/SOURCEcarriesperf-msr.txt's;issues/hardware/linuxs-readings-of-the-t14-and-the-tcg-model-lack-reads-owed-before-the-t14s-wipe.mdpoints at the fixtures instead of repeating them. Deleted: the kick on 0x20 (its Ring 0 branch counted kicks as timer expiries and re-armed the one-shot from scratch on every kick), the falsequiesce.rscomment,Intid::Kick's "rides the timer's vector", the IPI-ordering issue, andissues/diagnostics/toyos-explains-itself.md's "nothing reads APERF, MPERF,MSR_SMI_COUNT".issues/kernel/toyos-runs-the-t14-under-load-below-the-clock-linux-reaches.md(defect: 2318 MHz on every CPU against Linux's 3075–3800),issues/kernel/two-t14-cpus-idle-busier-under-toyos-than-any-under-linux.md(defect: cpu0 1.37%, cpu7 1.45% atce1786ff0and 1.35%, 1.42% ata059144e2against Linux's 0.11–0.36%, not yet attributed),issues/design-debt/toyos-cpuvuln-has-one-consumer-and-lives-outside-it.md, andissues/hardware/a-boots-readback-is-lost-to-one-ssh-that-times-out.md(the Drive run'sjobcasereadback, below).Decisions
drain_irqsis not a service point.COUNTERSreads the stamp and the SMI count;TRACE, the strict right, is needed beside it forAPERF,MPERFandkicks. Putting frequency and the kick counts under the strict right is the design and roast's recommendation (APERF/MPERF are the Hertzbleed power channel; per-CPU wake counts time keystrokes), not his words. The two things he named are not in this table: energy (RAPL) is C2's, and per-device interrupt counts stay where they are, in theirq:line.TRACEis the bit the trace track's step 1 will read its ring under; its syscall takes the next number, so nothing renumbers. Two ways round the strict right stand until the umbrella track's exit, for the owner's veto:inspectholdstrace, andissues/isolation/the-launcher-starts-any-row-for-any-holder.mdlets everylauncherholder start any row: the shell, the terminal, the compositor and every sshserver login can runinspect kernel.*and read every CPU's frequency, busy fraction and kick count, at up to 100 Hz (one round per 10 ms join).irq:line gainskick=per CPU, and every process exit prints that line into the log, which any program can read today (no per-program file views). So the per-CPU kick countsTRACEgates in this table are readable without it, asi8042=already is and as the same kicks were insidetimer=before this branch. Moving that line behind the strict right is the umbrella track's exit (issues/diagnostics/toyos-explains-itself.md).toyos-cpuvulnalready decodes vendor, family, model and the hypervisor bit at the same pin. Two named choices:MSR_SMI_COUNTrefused under a hypervisor departs from Linux (a hypervisor answers its own count for the guest, QEMU'senv->msr_smi_count), and APERF/MPERF are admitted under one as Linux admits them, so a hypervisor that enumerates them and faults the read ends the boot that read them first.MSR_SMI_COUNTis masked to 32 bits (SDM: 63:32 reserved;msr.c:254-256sign-extends from bit 31).MSR_SMI_COUNTfromenv->msr_smi_countand every unknown MSR with 0 (target/i386/tcg/system/misc_helper.c, read at the pinned version), so no guest reds on a gate admitting too much. The gate is held on the host instead, and the bring-up read is checked only by reading.roundin the record (roast SHRINK);stalesays it. The hardware id stays, for its reader: nothing else in the ABI maps a CPU index to the core and thread it is, andinspect kernel.cpu.<n>.hardware_idis how a per-CPU reading is matched to what the firmware's MADT, the kernel's ownSMP: AP cpuN lapic=line and Linux's turbostat (Core/CPU, SMT siblings) call that CPU; on a hybrid or SMT part a busy fraction means nothing without it. Thecountersrow checks it against the bring-up's LAPIC ids, which is also what shows each CPU answered for itself.SYS_DEBUG(COUNTERS_DEAF,COUNTERS_HEAR, test kernel only), not by the dump's deaf window as the roast's NOTE proposed. That window opens on the kernel's own clock 3 s into a boot for 400 ms and is judged on metal alone because a guest the host starves misses it; no reader can be placed inside it on purpose. The staged CPU answers no round until heard, which a reader cannot tell from interrupts closed past the bound, and it counts nothing, so the "first three serves" flake the roast named cannot arise. It is a second deaf actuator, beside the dump's, kept to what the reader sees.ring0_timer_firesandTimerFireBurstcounting kicks.Where the size lands
git diff --shortstat origin/main...a059144e2(origin/mainat 3f1db70): 68 files, +1893 −339, the issue reconciliation and the moved fixtures included. Production code (non-blank, non-comment lines inkernel/src,toyos-abi/src,toyos-cpuvuln/src,toyos-inspect/src,toyos/src,userland/inspect/src,toyos-manifest/src, less their unit-test modules and the test-only actuator), counted at round 1: about 440 added, 41 deleted, about 400 net, beside about 230 doc lines; round 2 removed four lines of it (one lookup, not two). The strategy budgeted 250–400 [e]; this is at its top, by what the estimate did not carry: the strict right as a second right with its gating, the kick vector moved with a fence on both architectures, and the reader renderingkernel.*inside the shippedinspect. Cut on the way: the kernel-msr crate, a second round, a second seqlock, theroundfield, Ring 0 expiries, a separate T14 boot, and a one-CPU AArch64 guest case (below: it tested a latency).Gates
At
cba61e819, round 4's one issue edit (the idle-busy reading promoted tokind: defect), no code changed,origin/mainunmoved; log underorch/counters4/:cargo run -- --ci host: EXIT=0,Host: 73 step(s), all green(ci-host.log:7288).At
ee468ce76, the merge oforigin/main(21f06e8: #707, issues only) and round 3's issue edits, no code changed; log underorch/counters3/:cargo run -- --ci host: EXIT=0,Host: 73 step(s), all green(ci-host.log:7289).At
a059144e2, the merge oforigin/main(3f1db70: #700, #702, #704) and round 2's fixes; logs under the orchestrator's scratchpad,orch/counters2/:cargo run -- --build-only: EXIT=0 (build-1.log).cargo run -- --ci host: EXIT=0, 73 steps green, the loom modelcounters_roundand itsshootdown-served-relaxedcontrol among them (ci-host.log).cargo test --test toyos-build(the whole QEMU suite; the kick move touches every wake): EXIT=0, 26 of 26 (guest-suite.log).mut/m13.virt_smp.log,mut/summary.txt).countersrow's boot and the shared boots carryingtest_rs_counters_readandtest_rs_counters_silentwere staged again (metal-stage.log,metal/request.txt) and flashed in order, sha256 recorded at flash:testcases(thecountersrow)97b2dd0feb677507e8718d75f0d2faba61102911cd3bc6c981362c683c2d2136,shared(test_rs_counters_read)327b9b5df9291e3e6de8afea9cfe16520c940661c0e639833416296a4e4160af,shared-debug(test_rs_counters_silent)5bbd06b0649d9fd5f792c3e2fc8d8c155886890620a3b8e3986164153c6f26bf; each boot passed. Judged from the clean head:cargo test --test toyos-build -- --metal --metal-readback orch/counters2/metal counters, EXIT=0,[metal] 3 passed, 0 failed, 3 boot(s),PASS counters. Every CPU reportssmi=true aperf=true mperf=true. Readbacksorch/counters2/metal/{testcases,shared,shared-debug}/, judge logorch/counters2/judge-t14-counters.log.At
ce1786ff0(round 1), logs underorch/counters1/:cargo run -- --ci host: EXIT=0, 73 steps (ci-host-rebased.log).cargo test --test toyos-build: EXIT=0, 26 of 26 (guest-suite-rebased.log).cargo test -p kernel-loom --test counters_round --test panic_console_publish --test tlb_shootdown: EXIT=0 (loom-green.log);--features shootdown-served-relaxed --test counters_round: EXIT=101,a_cpu_read_as_answered_is_read_with_its_answerred, the reader found the round answered and its snapshotNone(loom-served-relaxed.log).test_rs_counters_readandtest_rs_counters_silentexit 0, EXIT=0; each CPU loggedcounters: cpuN reads smi=false aperf=false mperf=false(preflight-final.log).--ci host:toyos-abicounters (6),toyos-cpuvulncounters (5),toyos-inspectkernel (4).cargo test --test toyos-build -- --metalin Drive mode, 26 boots in 2437 s:[metal] 275 passed, 4 failed, 26 boot(s)(drive/counters-full.log, readbacksdrive/counters-full-readback/). The four reds are thejobcaseboot's rows (usb_reset_hands_devices_back,blackbox_done_chain,machine_reboot,machine_soft_off_decoded), eachtoyos-metal exited exit status: 2: reading a log file on the machine exited exit status: 255: Connection timed out during banner exchange: the machine answered ssh 48 s after its reboot and the stick enumerated, then the read's ssh timed out, the readback lost and no row's verdict red. The stagedjobcaseimage (sha25622065d4f3cd282f99e853c3aba80d7a0a6bd0a215d019360d512ee11176a245e, checked in the command that flashed) was booted again (readbackmetal/jobcase/) and judged from the clean head:blackbox_done_chain,machine_reboot,machine_soft_off_decodedeach EXIT=0,1 passed, 0 failed, 1 boot(s);usb_reset_hands_devices_back, which spansjobcaseandmetaldevicecase, over that readback and the Drive run'smetaldevicecase: EXIT=0,1 passed, 0 failed, 2 boot(s)(judge-t14-*.log). 279 of 279 green.test_rs_counters_readandtest_rs_counters_silentpassed insharedandshared-debug(drive/counters-full.log:16573-16615,:23966-23970).High-risk checks (ABI, concurrency, a security boundary)
Negative control. The whole change reverted onto its base cannot build the guest binaries that read it (
SYS_COUNTERSis not in main's ABI), so it is refused at the missing syscall and says nothing; the controls are the mutations and the loom feature. Each mutation was a checked patch (git apply --check), built, run and reversed, the tree clean after each; the patches are posted as comments. Guest mutations of round 1 ran a scratch QEMU preflight (never committed) bootingtests/testcaseswithtest_rs_counters_readon the shipping kernel andtest_rs_counters_silenton the test kernel (x86-64, TCG, 2 CPUs), and the AArch64 onesvirt_smp(8 CPUs):virt_smpcounters_readnever returned (other CPUs never answer); ended by hand after 6 min, green takes 4 scounters_silentnever returned; ended by hand after 16 minvirt_smp/ a one-CPU AArch64 casevirt_smpTRACEnot demandedvirt_smpTRACEit did not read off the handlecargo test --test toyos-build -- virt_smpata059144e2counters_read.rs:116)cargo test -p toyos-cpuvuln countersan_intel_model_off_the_list_counts_no_smis(the T14's family and model on Centaur)a_guest_counts_no_smisThe fences have no control: no QEMU guest reds on them, TCG and HVF not modelling the ordering, as the closed issue said; they are checked by reading against the SDM ("MSR Access in x2APIC Mode") and Linux. The kick and the self-answer under one guard have no control either: the window it closes is a reader migrating between the two, which needs interrupts on inside a syscall ("interrupts on in syscalls" is not landed), so no run reaches it; checked by reading.
Independent oracles. Linux's
msr.cat the pinned commit (the model list,test_aperfmperf, the 32-bit SMI count) andscattered.c(leaf 6's range check); Linux on the T14 itself,perf stat -a -Aover the msr PMU's events, committed astoyos-cpuvuln/fixtures/t14/perf-msr.txtwith its command inSOURCE: the events Linux's probe listed are exactly aperf, mperf, smi and tsc, whichthe_t14_has_what_linux_counted_on_itholds the T14's verdict to; QEMU 11.1.1'starget/i386/cpu.cfor the TCG model's facts (qemu64isAuthenticAMDfamily 0xF model 0x6B, leaf 6's ECX zero on every model), which the TCG guest's owncounters: cpuN reads smi=false aperf=false mperf=falseagreed with; loom for the one ordering edge x86 hides; the T14, with Linux's turbostat on the same machine committed beside the row that reads it.The T14 row
countersrides the sharedtestcasesboot (the roast folded Boot 1 into the full run):test_rs_counters_metalreads every CPU atidle0, after an idle second atidle1, and after a fixed spin on a thread per CPU atspin, printinginspect kernel.*'s own lines. Held: one record per CPU the bring-up started, each naming the LAPIC id the bring-up gave it and carrying the counters itscounters: cpuN readsline names, none stale; fromidle0tospin, refused if under 4.444 s apart, every CPU's SMI count rose alike and by two or more, the firmware's legacy mode as the firmware issue measured it, the positive control ACPI stage 1's flatness is read against (that stage changes this row); across the spin every CPU's MPERF ran 0.9 [e] of its stamp or more (MPERF counts at the TSC's rate in C0, SDM). Read, not held: each CPU's idle busy fraction and its busy frequency under the spin, beside Linux's turbostat (tests/t14-linux/turbostat-*.txt: idle Busy% 0.11–0.36 across its summaries, loaded Bzy_MHz 3075–3800), and what the spin's round cost its reader.What it read at
ce1786ff0(drive/counters-full.log:29934-29943,PASS counters): 8 CPUs,SMI +9 each over 19575 ms, TSC 2419 MHz; MPERF busy across the spin 0.986–0.990 on every CPU; spinning 2318 MHz on every CPU against Linux's 3075–3800; idle busy 1.37% on cpu0 and 1.45% on cpu7 against Linux's 0.11–0.36%, cpu3 0.11%, the other five 0.00–0.01%; a whole round cost its reader 17768 ns. What it read ata059144e2(orch/counters2/judge-t14-counters.log:19-28,PASS counters): 8 CPUs,SMI +9 each over 19875 ms, TSC 2419 MHz; MPERF busy across the spin 0.985–0.990 on every CPU; spinning 2318 MHz on every CPU against Linux's 3075–3800; idle busy 1.35% on cpu0, 1.42% on cpu7 and 0.37% on cpu4 against Linux's 0.11–0.36%, cpu3 0.11%, the other four 0.00–0.03%; a whole round cost its reader 18548 ns. The second boot reads the same two busy CPUs and the same clock. The frequency and the idle busy fraction are filed (above), not fixed here.test_rs_counters_readandtest_rs_counters_silent(the test kernel's shared boot) are shared-boot members on the T14, the tier below a QEMU guest.Guest tests, and why QEMU
virt_smp(and every boot oftests/virtsmpcase) runstest_rs_counters_readon AArch64: SGI 0 answering the round on eight CPUs, the syscall's refusals, a handle nobody holds ending the caller, twice as many readers as CPUs all returning. No type or host test reaches an interrupt handler or the syscall boundary, and the T14 is x86-64, so AArch64's kick is reached only here. x86-64's are metal members, not QEMU tests.What each new check sees that reading cannot
counters_round(loom): theservedacquire that makes a copied block this round's, invisible on x86's TSO;shootdown-served-relaxedis its control insrc/ci.rs. The guest members: that every CPU answers for itself through the kick, that a missed bound is said, that the rights are demanded at the boundary. The host tests: Linux's verdict on fixture facts. The metal row: what the hardware counts.New dependency
The kernel depends on
toyos-cpuvuln, ToyOS's ownno_std,forbid(unsafe)crate; no third-party crate arrives. It now has one consumer and stays at the root, outside this brief:issues/design-debt/toyos-cpuvuln-has-one-consumer-and-lives-outside-it.mdrecords it with its owner and exit.Unsure
Interplay
#590 (parked) takes this round over when picked up. A2 consumes the kick vector and adds Ring 0 expiries to this table; with the kick off 0x20 its "a staged kick leaves Ring 0 expiries unchanged" can hold. The trace track's step 1 reads its ring under
TRACE. PR 2 reads SMI flatness through this table and changes thecountersrow's SMI gate.🤖 Generated with Claude Code
https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8