Skip to content

time ABI: boot AMD EPYC Genoa and Turin hosts, and close #396 - #412

Merged
Pedro Henrique Penna (ppenna) merged 3 commits into
devfrom
fix/issue-396-amd-genoa-turin
Oct 7, 2026
Merged

Pedro Henrique Penna (ppenna) merged 3 commits into
devfrom
fix/issue-396-amd-genoa-turin

Conversation

@ppenna

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

Copy link
Copy Markdown
Contributor

Boot AMD EPYC Genoa and Turin hosts on built-in CPU profiles, and close #396, with nanvix/openvmm#119.

Closes #396.

Stacked on #411. This PR's own commits are its top two. It pins nanvix/openvmm 3951c8415, which sits on #411's pin.

Why

#404 pinned amd.milan.v1, and left #396 open for three items:

  • fingerprints of AMD hosts on KVM and MSHV;
  • other AMD generations;
  • AMD CI runners.

GitHub's hosted Actions runners are Azure VMs with AMD and Intel CPUs and working KVM. Copilot cloud agent sessions boot microVMs on them. #404 found these CPUs among them:

CPU Generation Profile before this PR
EPYC 7763 Milan amd.milan.v1
EPYC 9V74 Genoa none
EPYC 9V45 Turin none
Xeon Platinum 8573C Emerald Rapids intel.emeraldrapids.v1

This PR's qualification runs also met a Xeon 6973P-C (Granite Rapids), which has no profile either. A temporary workflow on a scratch branch, deleted since, qualified and fingerprinted these runners in two rounds, on 22 runners.

Commits

Commit Change
119841b4 openvmm: serve AMD EPYC Genoa and Turin hosts Pins nanvix/openvmm 3951c8415. It adds amd.genoa.v1 (25/17) and amd.turin.v1 (26/2), derived from the runners' KVM fingerprints, and an AMD policy rule: KVM-derived AMD profiles drop the Intel speculation-control and IA32_ARCH_CAPABILITIES bits that KVM adds on AMD hosts, which no AMD CPU has and the Hyper-V backends don't present. NVX's copy of the catalog gains both generations. run links #409 instead of #396 for AMD CPUs that no built-in profile serves. The spec, including the WHP row's CPUID exit count, the usage reference, and the setup, CI, and benchmark docs follow
1b678677 copilot-instructions: name the runner CPUs that boot microVMs Names the runner CPUs that a built-in profile serves, and leaves the microVM scenarios to CI on others, such as Granite Rapids

Each commit message details its change and its validation.

Resolution of #396

#396 plan item Status
1-4, 7 Done in #404
5. Fingerprint AMD hosts on every backend Milan on WHP: #404. Milan, Genoa, and Turin on KVM: GitHub's runners, here. MSHV, bare-metal AMD hosts, and Ryzen need hosts that neither the development hosts nor CI have, so #409 tracks them
6. Pin one profile per microarchitecture and qualify its hosts amd.milan.v1 (#404), and amd.genoa.v1 and amd.turin.v1 (here). All three qualified on KVM here, and Milan on WHP in #404
8. Check whether GitHub-hosted runners are AMD #404 found AMD runners. Now every runner CPU met has a profile, except Granite Rapids, which #408 tracks. The Copilot instructions name the served CPUs
AMD CI runners with their own performance series #410

Validation

  • GitHub-hosted runners, release v0.1.0-dev.57eabdc503d6 (8 runners):

    • 5 EPYC 7763 runners passed --cpu-fingerprint, doctor H1 to H4, and the full default test-microvm suite on amd.milan.v1. No KVM host had run amd.milan.v1 before.
    • An 8573C runner passed the same checks and 9 scenario runs on intel.emeraldrapids.v1.
    • A 9V74 and a 9V45 runner wrote the fingerprints that the new profiles derive from.
  • GitHub-hosted runners, KVM build of b1d84c6db (14 runners). b1d84c6db differs from the pinned 3951c8415 only in commit messages and virt_whp's tests. Each of the 13 runners of a served CPU (4 Genoa, 1 Turin, 7 Milan, 1 Emerald Rapids) passed:

    • --cpu-fingerprint and doctor H1 to H4 on its profile;
    • the time ABI preflight on its profile and on its host profile;
    • all 34 runs of the full default test-microvm suite;
    • 9 host-profile scenario runs.

    Their warp probes measured at most 37 ns, with no backward step and no CPU budget overrun. The Granite Rapids runner failed auto with E_PROFILE_HOST_UNKNOWN, and passed on its host profile.

  • Bare metal and local, release builds of b1d84c6db with the guest artifacts of v0.1.0-dev.57eabdc503d6. Hosts: prometheus28 (WHP), prometheus30 (MSHV), prometheus31 and prometheus32 (KVM), all Xeon Silver 4114 (Skylake-SP), and an EPYC 7763 VM with WHP. Each host passed:

    • nvx.py verify and doctor H1 to H3 on intel.skylake-sp.v1 or amd.milan.v1, whose digests are unchanged;
    • the preflight on those profiles and on their host profiles;
    • the full default test-microvm suite.

    OpenVMM's unit tests pass on Windows and on the Linux hosts, and its MSHV hardware tests pass on prometheus30. On the pinned 3951c8415, virt_whp's unit tests (36) and WHP hardware tests (16) pass on the EPYC 7763 VM.

  • NVX checks on the EPYC 7763 VM:

    • compileall;
    • the validate-nvx unit tests (740), adversarial tests (70), and host-connect tests (4), and every --help check;
    • Ruff check and format, and Pyright for Linux and Windows.

CI's microVM runners are Ice Lake-SP and Emerald Rapids Xeons, so CI exercises no AMD profile. The GitHub-hosted runs above cover KVM on AMD. #409 tracks MSHV on AMD hosts.

Scope and exclusions

Dependencies

Review follow-ups

  • The Copilot instructions said that cold boots fail on any runner CPU other than those named, but built-in profiles also serve Skylake-SP, Ice Lake-SP, and Alder Lake. The guidance now names the runner CPUs met and leaves the microVM scenarios to CI on the others (folded into 1b678677).
  • The spec's WHP row still counted 9 CPUID exits only for amd.milan.v1. Genoa and Turin list 0x8000001E too, so it now says 9 for every AMD v1 profile (folded into 119841b4). To test that count, virt_whp's time ABI tests, which sampled only Milan among the AMD profiles, now sample Genoa and Turin too. That showed one comparison's non-vacuity guard, which required nonzero results at half as many probes as the profile has entries, failing for profiles with many explicit zero leaves. It now counts the profile's nonzero entries (cpu_profile: pin AMD Genoa and Turin CPU profiles nanvix/openvmm#119, 3951c8415).

Pin nanvix/openvmm aa9f6c4fa, one commit on 07850d27a. MSHV's
--cpu-fingerprint, and so doctor H2, now reads the CPUID entries outside
the selected profile on a probe partition configured from the profile,
as a cold boot reads them on its own partition (E_CPU_UNLISTED).

#390's finding 2 showed that on WHP, the fingerprint's own probe
partition, which enables every feature that the hypervisor offers,
presents CET's XSAVE components 0xd.11 and 0xd.12 on CET-capable hosts.
H2 therefore failed hosts whose cold boot passes. #394 pinned the fix
for WHP, and left MSHV on its own probe partition until a CET-capable
MSHV host showed whether it needs the same. No such host is available:
the bare-metal Skylake-SP hosts predate CET, and Azure withholds CET from
the roots of its Emerald Rapids VMs, which report neither IBT nor shadow
stacks. MSHV's probe partition likewise enables every processor and
XSAVE feature of the host partition. So OpenVMM now measures on MSHV
what a cold boot measures, which holds whatever the hypervisor offers.
The probe partition is created as a microVM's time ABI partition is,
without x2APIC or SMT and with the processor feature banks and XSAVE
features derived from the profile, and its VP 0 reads the host's
candidates with the cold boot's bulk read. Verification step 6 of the
time ABI specification and the H2 row of the CI guide now say that MSHV,
like WHP, checks a configured partition.

With this, #390's findings 2 to 4 are resolved; #394 resolved findings 3
and 4, and finding 2 on WHP. Finding 1's remaining client generations,
Tiger Lake and Meteor Lake, need fingerprints from such hosts, which
neither the development hosts nor CI have. #408 now tracks them,
together with a run on a CET-capable MSHV host. After a cold boot fails
on a CPU that no built-in profile serves, run's guidance therefore links
#408 for Intel CPUs instead of #390, and the usage reference does too.
AMD CPUs keep #396. The guidance also linked #390 for the CPUs of other
vendors, which the time ABI excludes, and now links no issue for them
(time_abi.CPU_SUPPORT_ISSUES).

Validation:

- On prometheus30, a bare-metal Xeon Silver 4114 (Skylake-SP, 6/85/4)
  with MSHV on Azure Linux 3.0, with a musl release build of the pinned
  OpenVMM tree and the guest artifacts of v0.1.0-dev.57eabdc503d6:
  - OpenVMM's new virt_mshv hardware test passes. The 7 host entries
    outside intel.skylake-sp.v1 (0xf.1, 0x10.1 to 0x10.3, 0x12.1, 0x12.2,
    and 0x14.1) read zero on the configured partition.
  - The virt_mshv unit tests pass (77).
  - `--cpu-fingerprint` passes, and so do `doctor --backend mshv --checks
    H1 H2 H3`.
- On an AMD EPYC 7763 VM with Windows 11 and WHP, these checks pass:
  - `nvx.py verify`;
  - the validate-nvx unit tests (740), adversarial tests (70), and
    host-connect tests (4), and every `--help` check;
  - Ruff check and format, and Pyright for Linux and Windows.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6844f112-d265-4538-bd05-aadcfe322f84

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.

Copilot review overview

🟡 Changes recommended

The runner guidance incorrectly claims every unlisted CPU lacks a built-in profile, potentially causing valid local tests to be skipped.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
What changed in this PR

Adds built-in Genoa and Turin CPU profile support and updates NVX’s catalog, tests, and documentation.

Changes:

  • Pins OpenVMM with new AMD profiles and portability policy.
  • Extends CPU detection, guidance, and tests.
  • Documents supported hosts and remaining qualification gaps.
File Description
.github/​copilot-instructions.md Updates hosted-runner CPU guidance.
doc/​benchmarks.md Documents AMD performance-series requirements.
doc/​ci.md Adds Genoa and Turin to H2 qualification.
doc/​design/​time-abi.md Updates the profile catalog and AMD contract.
doc/​setup.md Lists newly supported AMD generations.
doc/​usage.md Documents profiles, limitations, and tracking issues.
openvmm Pins the OpenVMM profile and policy changes.
scripts/​nvx_tools/​time_abi.py Adds generation mappings and vendor-specific issue guidance.
scripts/​test_nvx_tools.py Updates CLI guidance tests.
scripts/​test_time_abi.py Tests the expanded catalog and mappings.

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

Comment thread .github/copilot-instructions.md Outdated
Copilot AI balanced review requested due to automatic review settings October 6, 2026 19: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.

Copilot review overview

🔵 Needs a closer look

It changes immutable CPU ABI profiles through an unmerged dependency and retains one stale backend-contract statement.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
Resolved since last review (1)

Comment thread doc/design/time-abi.md
Pin nanvix/openvmm 3951c8415, one commit on aa9f6c4fa. It pins
amd.genoa.v1 for family 25 model 17 and amd.turin.v1 for family 26 model
2, so a cold boot with --cpu-profile auto boots AMD's fourth- and
fifth-generation EPYC CPUs (#396). It also makes every AMD profile clear
Intel's enumerations of its speculation controls and of
IA32_ARCH_CAPABILITIES, which KVM adds on AMD hosts, and its WHP backend
tests cover both profiles.

#404 pinned amd.milan.v1, and other AMD generations waited for hosts that
could fingerprint them. GitHub's hosted Actions runners are such hosts.
They are Azure VMs whose CPU, which Copilot Setup Steps reports, is an AMD
EPYC 7763 (Milan), 9V74 (Genoa), or 9V45 (Turin), or an Intel Xeon
Platinum 8573C (Emerald Rapids) or Xeon 6973P-C (Granite Rapids). Copilot
cloud agent sessions boot microVMs there, on KVM. A temporary workflow on
a scratch branch, deleted since, ran on 22 runners in two rounds:

- With release v0.1.0-dev.57eabdc503d6 (OpenVMM 07850d27a), five EPYC
  7763 runners passed --cpu-fingerprint, doctor H1 to H4, and all 34 runs
  of the full default test-microvm suite on amd.milan.v1, which no KVM host
  had run. An 8573C runner passed --cpu-fingerprint, doctor H1 to H4, and
  9 scenario runs on intel.emeraldrapids.v1, which no KVM host had run
  either. A 9V74 and a 9V45 runner failed with E_PROFILE_HOST_UNKNOWN,
  after --cpu-fingerprint wrote the fingerprints that the new profiles
  derive from.
- With a KVM build of b1d84c6db, which differs from the pinned OpenVMM
  only in commit messages and in virt_whp's tests, each of the 13
  runners of a served CPU passed:
  - --cpu-fingerprint and doctor H1 to H4 on its profile;
  - the time ABI preflight on its profile and on its host profile;
  - all 34 runs of the full default test-microvm suite on its profile;
  - the 9 runs of the guest-boot, guest-identity, smp, smp-snapshot,
    console-snapshot, and time-abi-conformance scenarios on its host
    profile.

  Those runners were 4 Genoa, 1 Turin, 7 Milan, and 1 Emerald Rapids.
  Their warp probes measured at most 37 ns, with no backward step and no
  CPU budget overrun. The Granite Rapids runner failed auto with
  E_PROFILE_HOST_UNKNOWN, and passed those 9 runs on its host profile.

NVX's copy of the catalog, time_abi.CPU_GENERATIONS, gains genoa and
turin, as test_the_catalog_copy_matches_openvmm_pinned_profiles requires.
The usage reference's CPU profiles section, the setup guide, the CI
guide's H2 row, and doc/benchmarks.md follow. The time ABI specification
updates its catalog, generation names, brand strings, msrs field, and AMD
profiles; the KVM row's MSR exit count, which an AMD KVM host now runs;
and the WHP row's CPUID exit count, 9 for every AMD profile, since each
lists 0x8000001E.

With this, #396 is resolved, except for work that needs AMD hosts that
neither the development hosts nor CI have. #409 now tracks that work: MSHV
on any AMD host, Genoa and Turin on MSHV and WHP, Milan on MSHV, bare-metal
AMD hosts, and AMD client CPUs. #410 tracks AMD CI runners with their own
performance series, and doc/benchmarks.md links it. So for an AMD CPU
that no built-in profile serves, run's guidance now links #409 instead of
#396, and the usage reference does too.

Validation:

- On the bare-metal Xeon Silver 4114 hosts (Skylake-SP: prometheus28 with
  WHP, prometheus30 with MSHV, and prometheus31 and prometheus32 with
  KVM), and on an AMD EPYC 7763 VM with Windows 11 and WHP, the checks
  below pass. They used release builds of b1d84c6db and the guest
  artifacts of v0.1.0-dev.57eabdc503d6:
  - `nvx.py verify`;
  - doctor H1 to H3, on intel.skylake-sp.v1 and amd.milan.v1, whose
    digests are unchanged;
  - the time ABI preflight on those profiles and on intel.host.v1 and
    amd.host.v1;
  - the full default test-microvm suite.

  On prometheus30, OpenVMM's MSHV hardware tests pass. On prometheus30 and
  prometheus32, the cpu_profile, virt_mshv, and virt_kvm unit tests pass.
- On the EPYC 7763 VM, these checks pass:
  - compileall;
  - the validate-nvx unit tests (740), adversarial tests (70), and
    host-connect tests (4), and every `--help` check;
  - Ruff check and format, and Pyright for Linux and Windows;
  - the pinned OpenVMM's virt_whp unit tests (36) and its WHP hardware
    tests (16).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6844f112-d265-4538-bd05-aadcfe322f84
Copilot cloud agent sessions run test-microvm on GitHub's hosted runners,
whose CPU changes from one job to the next (#396, plan item 8). With
amd.genoa.v1 and amd.turin.v1, a built-in CPU profile serves every runner
CPU that the qualification runs met but one: the AMD EPYC 7763, 9V74, and
9V45, and the Intel Xeon Platinum 8573C. On the Xeon 6973P-C (Granite
Rapids), which #408 tracks, every microVM cold boot fails with
E_PROFILE_HOST_UNKNOWN, and test-microvm has no --cpu-profile option. So
the instructions now name the served runner CPUs, among the generations
that doc/usage.md lists, and tell the agent to leave the microVM scenarios
to CI on a runner CPU that no built-in profile serves. The setup summary
already names the runner's CPU.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6844f112-d265-4538-bd05-aadcfe322f84
Copilot AI balanced review requested due to automatic review settings October 6, 2026 20:54

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.

Copilot review overview

🔵 Needs a closer look

The immutable cross-hypervisor CPU ABI and OpenVMM pin require final human review, with exact-head CI still in progress.

Review effort: Balanced
Findings: None

Resolved since last review (1)

@ppenna
Pedro Henrique Penna (ppenna) merged commit c0f099d into dev Oct 7, 2026
57 of 59 checks passed
@ppenna
Pedro Henrique Penna (ppenna) deleted the fix/issue-396-amd-genoa-turin branch October 7, 2026 14:17
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.

Support AMD CPUs in the time ABI's CPU profiles

2 participants