Skip to content

Port the time tools to Rust - #550

Merged
Pedro Henrique Penna (ppenna) merged 4 commits into
devfrom
agents/fix-issue-358-time-tools
Oct 16, 2026
Merged

Pedro Henrique Penna (ppenna) merged 4 commits into
devfrom
agents/fix-issue-358-time-tools

Conversation

@ppenna

@ppenna Pedro Henrique Penna (ppenna) commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • port nvx-time, the guest side of NVX time ABI v1, to safe Rust;
  • port nvx-time-probe latency, warp, and clock diagnostics to safe Rust;
  • preserve command lines, bytes, markers, state, exit and power-off statuses,
    port transactions, deferred work, and timing boundaries;
  • build and test both static-musl programs through nvx.py;
  • rewrite both tools in idiomatic Rust: types, Result, and the standard
    library in place of the C translation's byte strings, sentinels, and buffers.

Part of #358 (PR 4 of 5). Rebased onto dev (11c7a0f42), which merged #533,
so the four commits on top are this PR's.

Guest conventions

The tools are reworked onto the nvx::guest conventions that #531 and #533
established:

  • Every system call goes through nix, or through the standard library, which
    reads and writes whole files and the MSR devices. libc is reached through
    nix::libc only for calls that nix does not wrap (ioperm, adjtimex,
    klogctl, getauxval, sigqueue, and _exit), for sched_setscheduler,
    which musl does not implement for one thread, for the probe's raw
    clock_gettime and getpid system calls, and for child waits that keep
    real-time signals. guest::sys documents each.

  • Errors are nix's Errno with its descriptions. Both programs fail with the
    shared CommandError and exit with the shared ExitStatus.

  • System-specific values are named once. sys::kernel holds the kernel paths,
    sys::Port OpenVMM's ports, sys::x86 the CPUID leaves, bits, and MSRs, and
    sys::ClockAdjustment the adjtimex modes and status bits. The programs
    name their own limits, file modes, and time constants.

  • Owners release or restore every resource and temporary change when dropped:

    • port permissions;
    • MSR files and flock locks;
    • created files, which are unlinked unless kept or renamed;
    • scratch directories and tmpfs mounts;
    • blocked signal masks;
    • CPU affinity;
    • the idle scheduling policy, which only the thread that entered it leaves;
    • the forced rcu_normal setting;
    • the idle-thread promoter, which is joined.
  • sys::fork refuses a process that has other threads, and every fork point is
    single-threaded. test promote and test deferred-restore-cpu drive the
    production promoter and deferred-restore fork.

  • CPUID and the TSC reads use core::arch intrinsics. Only sys::port uses
    inline assembly, for its scalar inb, inl, and outb. The probe formats
    with Rust's exact fixed-precision formatting and C's NaN spellings, rather
    than libc snprintf.

  • Input is strict:

    • integers are plain decimal, or 0x hexadecimal where C read base 0, with a
      - sign where a test hook's number may be negative;
    • rates are finite decimals;
    • the probe's CPU lists reject duplicates;
    • the kernel's numbers and text, the tools' own records, and the test hooks'
      names, codes, and sources are read only in the form in which they are
      written.

    The tools do not reproduce what only C's buffers and lenient parsers did to
    oversized or malformed input, such as the 127-byte limit on --new-cpus.
    guest/mod.rs documents the rule, and C's parity fixtures pass unchanged.

  • The port follows dev's rename of restore step 13 to the deferred restore
    (repair step 7), including the deferred-restore-cpu test hook.

Idiomatic Rust

The ports first translated the C programs nearly line by line. The fourth
commit rewrites them in Rust's terms, keeping the output, exit statuses, state
file, and port transactions byte-exact for valid input:

  • guest::kernel_text parses the kernel's text formats for both tools:
    /dev/kmsg and syslog(2) records, CPU lists, and /proc/timer_list. This
    fixes the probe's timer-list summary, which printed
    handler=none hres_active=-1 nohz=-1 on real kernels.
  • Check IDs, violation codes, event sources, state tokens, CPU sets, restore
    packets, time samples, and their errors are types with Display, and
    Option replaces the zero and -1 sentinels.
  • The checks return their failures as values that ? propagates.
  • TimeSpec, Instant, Duration, std::fs, channels, black_box,
    split_first_chunk, and div_euclid replace hand-written versions.
  • The latency probe's timing loop is specialized per method, which keeps the
    method's dispatch out of the measured loop, as in C.

Follow-ups

The latest review found two places where nvx-time-probe clock prints zero as
0x0 where C's %#x printed 0, as the port has since its first revision:

Validation

This revision (2ac2ce1a2)

In WSL Linux, on the rebased head:

  • PASS: every Linux check-nvx-rs step:
    • format;
    • both Clippy modes;
    • tests with all and with default features;
    • artifact bundling;
    • rustdoc with warnings denied;
    • the Rust 1.89 MSRV check;
    • the macOS cross-check;
    • musl check-guest-binaries, with 254 library and 33 guest-tool tests,
      including a two-CPU warp run;
    • build-guest-binaries and test-guest-binaries. nvx-time is 623,184
      bytes (df4fca77...), and nvx-time-probe is 561,808 bytes
      (4f0d22e5...).
  • PASS: every Linux check-aci-edge-sandboxes step, including
    test-agent-bundling.
  • PASS: test_guest_time.py's C fixtures against the musl debug and
    guest-profile nvx-time, and its new two-unusable-CPU parallel case
    against the C program.
  • PASS: Ruff check and format, Linux and Windows Pyright on the changed test,
    and dev's Markdown link check.
  • NOT RUN: nvx.py verify, which needs an OpenVMM checkout, the Windows
    checks, and every in-VM run. The results below predate the rewrite.

Previous revision (98a35f1d5, before the rewrite)

Windows and WSL

  • PASS: every check-nvx-rs command on Windows and WSL Linux:
    • format;
    • every Clippy mode;
    • tests;
    • rustdoc with warnings denied;
    • the Rust 1.89 MSRV check;
    • the macOS cross-check;
    • musl check-guest-binaries, with 234 library and 32 guest-tool tests.
  • PASS: every check-aci-edge-sandboxes command on Windows, including
    test-agent-bundling.
  • PASS: nvx.py verify, the Windows validate-nvx list (1,080 unit tests),
    Ruff check and format, compileall, Linux and Windows Pyright, WSL
    test_guest_binaries.py and test_guest_time.py, and dev's markdown link
    check on the merge with dev.
  • PASS: each commit passes format and both GNU Clippy modes. The two nvx-rs
    commits also passed the full WSL check (Clippy, musl, tests, and rustdoc)
    before the rebase onto Port nvx-ingress to Rust #533's final head, which changed only
    ingress/table.rs.
  • Two fresh build-guest-binaries runs were byte-identical and passed all 32
    prebuilt tests. nvx-time is 610,896 bytes (2344e4b3...), and
    nvx-time-probe is 541,328 bytes (2d6bbed9...).

In-VM on WHP

The runs used a local Windows/WHP host with an Intel Core i9-12900H, and
OpenVMM c6d97c529 with guest images from v0.1.0-dev.f429da852efa. Both Rust
time tools were overlaid in copies of the guest images.

  • Alpine: every default test-microvm scenario, plus managed-exec-config
    and sandbox-lifecycle. This covers:
    • SMP on 1, 2, 4, and 8 vCPUs;
    • console, SMP, core, tier, and scratch snapshots;
    • restore of processors and memory, and long-downtime restore;
    • exhaustive time-ABI conformance on 8 vCPUs: exhaustive=ok/8/0, 29 warp
      runs with a maximum offset of 23 ns and no backward steps, and every boot
      and restore within its CPU budget.
  • Ubuntu: the CI smoke set, plus snapshot core and exhaustive conformance.
  • Azure Linux: the CI smoke set.
  • In-guest: nvx-time status, probe latency on two CPUs, a two-CPU warp
    (PASS), the clock report, and the optional MSR dump.

Not repeated for that revision

The bare-metal KVM and MSHV in-VM runs, the generated C/old/new differential
comparisons, and the boot, capture, and restore timing table were not repeated.

Copilot AI balanced review requested due to automatic review settings October 14, 2026 12:37

Copilot AI 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.

🔵 Needs a closer look

The large stacked change includes privileged, concurrency-sensitive timekeeping code and still lacks the deferred KVM, MSHV, and WHP host validation.

0 open findings

What changed in this PR

Ports nvx-time and nvx-time-probe to Rust while preserving the existing C ABI and behavior; the stacked PR also contains earlier guest-tool ports.

Changes:

  • Implements time repair, monitoring, diagnostics, latency, and warp tooling in Rust.
  • Adds extensive parity and guest-binary tests.
  • Builds, lints, and validates static musl executables in CI.
File Description
.github/​actions/​check-nvx-rs/​action.yml Adds musl guest validation.
doc/​ci.md Documents guest CI checks.
doc/​contribute.md Updates contributor guidance.
doc/​project-structure.md Documents Rust guest modules.
doc/​usage.md Updates guest-tool usage.
nvx-rs/​Cargo.toml Registers guest binaries and profile.
nvx-rs/​README.md Documents guest tooling.
nvx-rs/​src/​bin/​nvx-console-pending.rs Adds binary entry point.
nvx-rs/​src/​bin/​nvx-device-io.rs Adds binary entry point.
nvx-rs/​src/​bin/​nvx-exit.rs Adds binary entry point.
nvx-rs/​src/​bin/​nvx-ingress.rs Adds binary entry point.
nvx-rs/​src/​bin/​nvx-managed-agent.rs Adds agent entry point.
nvx-rs/​src/​bin/​nvx-mmio-write.rs Adds binary entry point.
nvx-rs/​src/​bin/​nvx-port-io.rs Adds binary entry point.
nvx-rs/​src/​bin/​nvx-reseed.rs Adds binary entry point.
nvx-rs/​src/​bin/​nvx-time-probe.rs Adds probe entry point.
nvx-rs/​src/​bin/​nvx-time.rs Adds time-tool entry point.
nvx-rs/​src/​guest/​agent/​cgroup.rs Implements cgroup containment.
nvx-rs/​src/​guest/​agent/​diagnostics.rs Implements agent diagnostics.
nvx-rs/​src/​guest/​agent/​dispatch.rs Implements request dispatch.
nvx-rs/​src/​guest/​agent/​exec.rs Implements workload execution.
nvx-rs/​src/​guest/​agent/​exec_config.rs Handles execution configuration.
nvx-rs/​src/​guest/​agent/​helper.rs Implements launch helper.
nvx-rs/​src/​guest/​agent/​launch.rs Implements process launching.
nvx-rs/​src/​guest/​agent/​loopback.rs Adds loopback integration coverage.
nvx-rs/​src/​guest/​agent/​mappings.rs Implements host mappings.
nvx-rs/​src/​guest/​agent/​mod.rs Wires agent modules.
nvx-rs/​src/​guest/​agent/​seam.rs Adds privileged-operation seam.
nvx-rs/​src/​guest/​agent/​session.rs Implements control sessions.
nvx-rs/​src/​guest/​agent/​tty.rs Implements control TTY handling.
nvx-rs/​src/​guest/​console_pending.rs Ports console query tool.
nvx-rs/​src/​guest/​freestanding/​args.rs Parses freestanding arguments.
nvx-rs/​src/​guest/​freestanding/​device_io.rs Ports device benchmark.
nvx-rs/​src/​guest/​freestanding/​exit.rs Implements guest exit.
nvx-rs/​src/​guest/​freestanding/​hosted.rs Supports hosted testing.
nvx-rs/​src/​guest/​freestanding/​mem.rs Provides memory primitives.
nvx-rs/​src/​guest/​freestanding/​mod.rs Wires freestanding modules.
nvx-rs/​src/​guest/​freestanding/​start.rs Implements process startup.
nvx-rs/​src/​guest/​freestanding/​syscall.rs Provides raw syscalls.
nvx-rs/​src/​guest/​ingress/​address.rs Parses ingress addresses.
nvx-rs/​src/​guest/​ingress/​collect.rs Collects listening sockets.
nvx-rs/​src/​guest/​ingress/​diag.rs Parses socket diagnostics.
nvx-rs/​src/​guest/​ingress/​encode.rs Encodes announcements.
nvx-rs/​src/​guest/​ingress/​mod.rs Wires ingress behavior.
nvx-rs/​src/​guest/​ingress/​sender.rs Implements live announcements.
nvx-rs/​src/​guest/​ingress/​table.rs Parses socket tables.
nvx-rs/​src/​guest/​ingress/​test_mode.rs Adds ingress test mode.
nvx-rs/​src/​guest/​mmio_write.rs Ports MMIO writer.
nvx-rs/​src/​guest/​mod.rs Exposes guest modules.
nvx-rs/​src/​guest/​parse.rs Adds byte-oriented parsing.
nvx-rs/​src/​guest/​port_io.rs Ports port-I/O tool.
nvx-rs/​src/​guest/​reseed.rs Ports reseeding tool.
nvx-rs/​src/​guest/​sys.rs Provides guest system wrappers.
nvx-rs/​src/​guest/​time/​checks.rs Implements time checks.
nvx-rs/​src/​guest/​time/​commands.rs Implements time commands.
nvx-rs/​src/​guest/​time/​daemon.rs Implements time daemon behavior.
nvx-rs/​src/​guest/​time/​decoders.rs Decodes ABI records.
nvx-rs/​src/​guest/​time/​events.rs Formats violation events.
nvx-rs/​src/​guest/​time/​mod.rs Wires the time tool.
nvx-rs/​src/​guest/​time/​state.rs Persists time state.
nvx-rs/​src/​guest/​time/​system.rs Implements privileged operations.
nvx-rs/​src/​guest/​time/​test_mode.rs Adds parity test hooks.
nvx-rs/​src/​guest/​time_probe/​clock.rs Implements clock diagnostics.
nvx-rs/​src/​guest/​time_probe/​format.rs Preserves C-style formatting.
nvx-rs/​src/​guest/​time_probe/​latency.rs Implements latency probing.
nvx-rs/​src/​guest/​time_probe/​mod.rs Dispatches probe commands.
nvx-rs/​src/​guest/​time_probe/​support.rs Provides probe utilities.
nvx-rs/​src/​guest/​time_probe/​warp.rs Implements warp detection.
nvx-rs/​src/​guest/​x86.rs Adds x86 guest primitives.
nvx-rs/​src/​lib.rs Exposes guest functionality.
nvx-rs/​src/​protocol/​boot.rs Extends boot parsing.
nvx-rs/​src/​protocol/​exec.rs Adds guest EXEC decoding.
nvx-rs/​src/​protocol/​features.rs Adds guest feature masks.
nvx-rs/​src/​protocol/​maps.rs Adds mapping protocol support.
nvx-rs/​src/​protocol/​mod.rs Exposes protocol additions.
nvx-rs/​src/​protocol/​outer.rs Extends outer records.
nvx-rs/​src/​protocol/​tests.rs Adds protocol coverage.
nvx-rs/​tests/​guest_tools.rs Exercises real guest binaries.
scripts/​nvx.py Exposes ELF validation command.
scripts/​nvx_tools/​elf.py Validates static ELF binaries.
scripts/​test_nvx_tools.py Tests CLI and ELF validation.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot AI balanced review requested due to automatic review settings October 14, 2026 23:23

Copilot AI 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.

🟡 Changes recommended

Accepted large TSC-frequency values are silently truncated, breaking the required output compatibility.

1 open finding

🧠 Review effort: Balanced

Comment thread nvx-rs/src/guest/sys/stdio.rs Outdated
Copilot AI balanced review requested due to automatic review settings October 14, 2026 23:37

Copilot AI 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.

🔵 Needs a closer look

Privileged runtime operations and timing-sensitive ABI compatibility require final human review despite the extensive reported validation.

0 open findings

1 resolved since last review

🧠 Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 15, 2026 02:30

Copilot AI 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.

🔵 Needs a closer look

Privileged I/O, fork boundaries, and timing-sensitive compatibility across backends require final human review.

0 open findings

🧠 Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 15, 2026 05:41

Copilot AI 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.

🔵 Needs a closer look

Privileged operations, fork boundaries, and snapshot timing compatibility require final human review.

1 open finding

🧠 Review effort: Balanced

Comment thread nvx-rs/src/guest/time/commands.rs Outdated
Copilot AI balanced review requested due to automatic review settings October 15, 2026 05:53

Copilot AI 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.

🔵 Needs a closer look

Privileged clock repair, fork behavior, and instruction-ordering and timing compatibility require final human review.

0 open findings

1 resolved since last review

🧠 Review effort: Balanced

Copilot AI 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.

🟡 Changes recommended

Compatibility hooks change output and failure accounting, and daemon polling introduces recurring heap allocation.

4 open findings

🧠 Review effort: Balanced

Comment thread nvx-rs/src/guest/sys/poll.rs Outdated
Comment thread nvx-rs/src/guest/time/test_mode.rs Outdated
Comment thread nvx-rs/src/guest/time/test_mode.rs Outdated
Comment thread nvx-rs/src/guest/time/test_mode.rs Outdated
Comment thread nvx-rs/src/guest/sys/clock.rs
Comment thread nvx-rs/src/guest/sys/clock.rs Outdated
Port nvx-time, the guest side of NVX time ABI v1, as a static Rust guest
binary that keeps the C program's command lines, exit statuses 0, 1, and
2, power-off statuses 193, 194, and 195, markers, output, state and run
files, scalar port transactions, deferred work, and timing boundaries.
Split the program by concern: pure decoders of the restore packet,
samples, the kernel log, timer list, CPU lists, command line, clock
corrections, and frequencies; event records; the time state; the
conformance checks; the commands; the background daemon; the system
boundary; and the C program's test hooks. Follow the C program's rename
of restore step 13 to the deferred restore, repair step 7, in names and
in the deferred-restore-cpu test hook.

Follow the guest programs' conventions. The program fails with the
shared CommandError and exits with the shared statuses, and its
diagnostics describe errno values with nix's text. The capture request
is plain decimal and the exhaustive-leaf hook's CPUID values plain
decimal or 0x-prefixed hexadecimal, while the other test hooks keep the
C program's strtoll and strtoull reading, which their compatibility
tests compare. Every port, path, file mode, limit, time constant, status
bit, CPUID leaf and bit, MSR, and Hyper-V identity is named once.

Extend nvx::guest::sys with the safe operations that the program needs,
through nix wherever it provides them: timerfd and signalfd owners,
flock, absolute monotonic sleeps, renameat and unlinkat, polling, CPU
affinity, fork, setsid and dup2 for detaching, private mount namespaces,
and tmpfs mounts. Reach libc through nix's re-export only for the calls
that nix does not wrap, ioperm, adjtimex, klogctl, sigqueue, and _exit,
for sched_setscheduler, which musl does not implement for one thread,
and for the child waits that keep real-time signals, as the managed
agent's do. CPUID runs through its core::arch intrinsic, and the port
instructions, in sys::port only, as inline assembly.

Give every resource and every temporary change an owner that releases or
restores it when dropped: port permissions, MSR files, file locks,
created files, which disappear unless kept or renamed, scratch
directories, tmpfs mounts, blocked signal masks, CPU affinity, the idle
scheduling policy, which only the thread that entered it leaves, the
forced rcu_normal setting, and the thread that promotes idle threads.
sys::fork refuses a process that has other threads, and the program
forks only while it has one.

Port the C test hooks with golden unit coverage, and test the real
binary through NVX_GUEST_BINARIES.

Part of #358.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Port nvx-time-probe's latency, pairwise warp, and clock diagnostics as
a static Rust guest binary that keeps the C program's command lines,
version, tables, markers, and exit statuses: 0 on success, 1 when the
warp check fails, 2 for usage errors, and 3 when a diagnostic cannot
prepare or run its measurement. Split the program into option and
kernel-input support, the three diagnostics, and number formatting. The
TSC rate still comes from --tsc-hz, sysfs, the kernel log, cpuinfo, or
a measurement against CLOCK_MONOTONIC_RAW, in that order.

Run each warp pair and ping-pong round on scoped threads pinned to
their CPUs, with 64-byte-aligned atomics and the C program's acquire,
release, and sequentially consistent orderings. Format measured values
with Rust's exact fixed-precision formatting and C's spellings of NaN,
and render UTC times with the proleptic Gregorian civil-date conversion
rather than gmtime.

Follow the guest programs' conventions. Integer options are plain
decimal or 0x-prefixed hexadecimal, as C's base-0 strtoull read them,
rates are finite plain decimals with an optional exponent, which a new
shared parse_f64 reads, and CPU lists are strict, so that the signed,
octal, padded, infinite, hexadecimal-float, and duplicate forms that C
accepted are usage errors. The kernel's own numbers, such as its TSC
rate and clock parameters, are read only in the forms that the kernel
writes.

Extend nvx::guest::sys with the probe's operations: the time-stamp
counter reads that the latency table compares, RDTSC, RDTSCP, and
LFENCE;RDTSC, and the fenced read that brackets a timed region, as
core::arch intrinsics; PAUSE through std::hint::spin_loop; the
clock_gettime and getpid system calls without the vDSO's or libc's
shortcuts; getauxval for the vDSO; sched_yield; the calling thread's
affinity mask and CPU; the raw and coarse monotonic clocks; a one-shot
sleep; the TSC frequency and lockup-detector paths; and the CPUID
leaves, bits, display signature, and MSRs that the clock report prints.
The optional MSR dump reads /dev/cpu/0/msr through the shared MsrFile
owner and reports a faulting read as a #GP.

Cover the formats, the strict option and kernel-number parsers, CPU
lists, percentile ranks, rounding, the shared statuses, and the aligned
atomics, and test the real binary's usage, version, option errors, and
small diagnostics.

Part of #358.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add nvx-time and nvx-time-probe to the Rust guest-binary inventory. The
existing nvx.py build-guest-binaries and test-guest-binaries commands
now build their static musl executables in the same Cargo build as the
other guest programs, check their ELF form, include their digests in
the manifest, and run their prebuilt integration tests.

A build adds both programs, as it adds nvx-managed-agent and
nvx-ingress, to an earlier output whose manifest does not record them.
Test that the immediate predecessor's output, which lacks only the two
time tools, upgrades in place. Document both command lines, and count
nine binaries in the command documentation. The guest-image build
remains unchanged until the final switch.

Part of #358.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 16, 2026 19:35

Copilot AI 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.

🔵 Needs a closer look

Privileged timing and process changes warrant human review, with cross-CPU test coverage incomplete and KVM/MSHV validation not repeated.

3 open findings
2 resolved since last review

🧠 Review effort: Balanced

Comment thread nvx-rs/src/guest/time_probe/warp.rs
Copilot AI balanced review requested due to automatic review settings October 16, 2026 19:42

Copilot AI 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.

🔵 Needs a closer look

The privileged, timing-sensitive rewrite needs final human review and current-head in-VM validation, since the reported VM runs predate the rewrite.

1 open finding
2 resolved since last review

🧠 Review effort: Balanced

@ppenna
Pedro Henrique Penna (ppenna) marked this pull request as ready for review October 16, 2026 19:55
The ports translated the C programs nearly line by line: byte strings
and sentinel values for state, C's fixed buffers, the leniency of
strtoll and scanf, and wrapping arithmetic. Model them with Rust's
types, nix, and the standard library instead, keeping the output, exit
statuses, state file, and port transactions byte-exact for valid input:

- Share the kernel's text formats between both tools: /dev/kmsg and
  syslog records, CPU lists, and /proc/timer_list. This also fixes the
  probe's timer-list summary, which printed handler=none
  hres_active=-1 nohz=-1 on real kernels.
- Type check IDs, violation codes, event sources, state tokens, CPU
  sets, restore packets, time samples, and their errors, and replace
  zero and -1 sentinels with Option.
- Return the checks' failures as values that ? propagates.
- Use TimeSpec, Instant, Duration, std::fs, channels, black_box,
  split_first_chunk, and div_euclid instead of hand-written versions.
- Specialize the latency probe's timing loop per method, as C hoisted
  its switch out of the loop.
- Fail C1 for every CPU that the parallel test hook's jobs cannot run
  on, after the foreground's failure, as C's check_cpus_parallel did,
  rather than for the first only.
- Test the warp probe's CPU-pair protocol on two CPUs, under a timeout,
  and its summary's accounting of stalled and inconsistent pairs.

The tools now read the kernel's text, their own records, and their
test hooks' arguments only in the form in which they are written,
UTF-8 text and plain decimal numbers, and no longer reproduce what
only C's buffers did to oversized input, such as the 127-byte limit on
--new-cpus or the 638-byte cut of an asynchronous console line.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 16, 2026 20:05

Copilot AI 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.

🔵 Needs a closer look

Broad privileged timing and process changes need human review and post-rewrite in-VM validation, alongside resolution of the output compatibility findings.

2 open findings
1 resolved since last review

🧠 Review effort: Balanced

Comment on lines +455 to +458
let _ = writeln!(
output,
"msr {index:#010x} {name:<34} = {value:#x} ({value})"
);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Tracked in #589. The port has printed zero this way since its first revision, so #550 leaves the fix to that issue. #590 covers the same difference in the CPUID fields, and one helper for C's %#x fixes both.

Comment on lines +648 to +663
let _ = writeln!(
output,
"NVX-TIME-PROBE clock clocksource={} available={available} tsc_hz={} tsc_hz_source={} \
hv_vendor={} hv_max_leaf={:#x} hv_features_eax={:#x} hv_features_edx={:#x} \
flags={present} missing_flags={absent} tsc_unstable_msgs={} unchecked_msr_msgs={} {}",
String::from_utf8_lossy(&clocksource),
f0(rate.hz),
rate.source,
sanitize_token(&ids.vendor),
ids.max_leaf,
ids.features_eax,
ids.features_edx,
time.tsc_unstable,
time.unchecked_msr,
timer_summary
);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Tracked in #590, which also covers the eax.max_leaf of the cpuid.0x40000000 line. The port has printed zero this way since its first revision, so #550 leaves the fix to that issue. One helper for C's %#x fixes it and #589.

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.

3 participants