Repository navigation
cpu_profile: support AMD CPUs, pin amd.milan.v1, and serve AMD's configuration MSRs - #115
Merged
Merged
Conversation
Only Intel CPUs could have a CPU profile (microsoft/nvx#396, rows 1 to 4 and 7). Identity validation accepted only GenuineIntel, host profiles served only Intel CPUs, and the VM-owned bits, the derivation policy, and OpenVMM's topology leaves covered only Intel's CPUID layout. On an AMD host, auto and --cpu-profile host both failed with E_PROFILE_HOST_UNKNOWN; a profile derived from an AMD fingerprint failed validation, and, once accepted, every cold boot would have failed with E_CPU_SURFACE, because OpenVMM sets AMD topology fields that the profile pinned. A profile's vendor is now a CpuVendor: Intel, or AMD, which profile IDs spell amd. Hygon CPUs, which follow AMD's layout, still have neither a profile nor a host profile. derive_host_profile derives amd.host.v1 on an AMD host, with the brand string "AMD Processor (host profile)", and supports_host_profiles accepts AMD CPUs, so OpenVMM's auto error also names --cpu-profile host there. KnownGeneration takes the vendor too. auto's errors name --cpu-profile host in one more case: a cold boot whose built-in profile the backend does not support now fails with E_PROFILE_UNSUPPORTED and the hint, on an Intel or AMD host, because a host profile derives from what the backend supports and can boot where the built-in one cannot. The VM worker adds the hint as a context of the error, which keeps the backend's chain and code, wherever the code arises: the WHP and MSHV feature banks at partition creation, or the support check of every backend. Explicit profile IDs, host, restores, and other vendors' CPUs get no hint, as for E_PROFILE_HOST_UNKNOWN. vm_owned_bits and pinned_mask take the profile's vendor. AMD profiles leave AMD's topology fields to the VM: the core count and APIC ID size of 0x80000008 ECX, each cache's sharing count in 0x8000001D EAX[25:14], and the processor topology of 0x8000001E (EAX, EBX[15:0], and ECX[10:0]), which leaf 1 and the extended topology leaves complete as on Intel. Leaf 4's fields stay VM-owned on Intel only. The Intel profiles keep pinning AMD's fields, which a vendor-neutral rule would have unpinned, so their encodings and digests are unchanged, as the catalog's golden digests check. The derivation policy gains an AMD section, which only AMD profiles take, so it derives every Intel profile as before and keeps its version. 0x80000005, 0x8000001D, 0x8000001E, and 0x80000021 keep data (AMD_DATA_LEAVES). 0x8000001D lists its subleaves up to the null cache type, as leaf 4 does, in profiles and in derivation, and combines by majority, like the other cache descriptors. The policy clears SVM, IBS, SKINIT, the watchdog timer, LWP, the node ID MSR, the performance counter extensions, the performance TSC, the data breakpoint and address mask extensions, and MONITORX in 0x80000001 ECX; the instructions-retired counter, INVLPGB, RDPRU, memory bandwidth enforcement, PPIN, CPPC, and branch sampling in 0x80000008 EBX; and CPUID faulting, which writes HWCR, and workload classification in 0x80000021 EAX, with its EBX and EDX. It keeps the speculation controls and immunities that KVM can present: IBPB, IBRS, STIBP, and SSBD in 0x80000008 EBX, and AutoIBRS, LFENCE serialization, SBPB, SRSO_NO, and the TSA bits in 0x80000021. BTC_NO goes: KVM never enumerates it in KVM_GET_SUPPORTED_CPUID, so every KVM host would fail a profile that set it, and a guest loses nothing without it, because Linux marks no CPU of family 0x19 or later as affected by RETBLEED (cpu_vuln_blacklist), which is all that BTC_NO decides there. PSFD stays only beside a SPEC_CTRL control, Intel's IBRS or AMD's IBRS, STIBP, or SSBD (has_spec_ctrl_control): PSFD is a bit of SPEC_CTRL, which KVM lets a guest access only with such a control, and OpenVMM's KVM backend withholds PSFD from KVM's supported surface otherwise. strip_psfd_leaf now calls the same function, so the policy and the KVM surface cannot disagree. The rule reads the derived table, which is the guest's CPUID, not each fingerprint: backends that each offer PSFD beside another control would otherwise keep PSFD while the intersection drops both controls. The policy also clears 0x80000001 EBX, the brand ID and package type, and 3DNowPrefetch: on the Azure AMD EPYC 7763 host that this work used, WHP presents 3DNowPrefetch to guests but not to the Hyper-V root, whose CPUID the cold-boot support check reads, so a profile that pinned it would fail there with E_PROFILE_UNSUPPORTED, while Linux infers PREFETCHW from long mode whatever the bit says. 0x80000001 EAX, where AMD repeats the CPU's signature, now describes the CPU as leaf 1's does, so a host of another stepping of a generation, such as Milan-X's stepping 2, supports its profile; Intel CPUs leave it zero. TOPOEXT stays: Linux reads the cache and processor topology through it, and without it finds no shared cache. topology_cpuid therefore writes AMD's cache sharing in 0x8000001D, as it writes leaf 4's on Intel: each VP has its own L1 and L2 caches, shared only with an SMT sibling, and the socket shares the L3, which Linux's cacheinfo_amd_init_llc_id reads from the last cache's count. Before, an AMD guest saw the host's L3 grouping. Every AMD partition gets it, not only the time ABI's, as every Intel partition gets leaf 4's. Unit tests derive host profiles and a Milan profile from the CPUID that a WHP probe partition presented on an AMD EPYC 7763 (family 0x19, model 1, stepping 1), and from that CPUID with what KVM can offer on bare metal added: the identity, the VM-owned fields and their masks, the cache subleaves, the policy's clears and keeps, majority votes on 0x8000001D, and the support of another stepping and of a root that lacks 3DNowPrefetch, and that PSFD stays only beside a SPEC_CTRL control, also when two backends offer different ones, and BTC_NO never. Others check that Intel profiles keep pinning AMD's fields, that an Intel fingerprint with values in AMD's leaves derives what the Intel policy alone gives, PSFD and BTC_NO included, that the effective CPUID of an AMD profile takes OpenVMM's AMD topology, that topology_cpuid shares the L3 across the socket in 0x8000001D at 1 to 8 VPs with and without SMT, and that auto names --cpu-profile host on an AMD host that no pinned profile serves, and not on a Hygon one, and where the backend lacks the profile on Intel and AMD hosts only, not for explicit profiles, host, restores, or other codes. The Guide's snapshot and CLI pages name amd.host.v1 and the hint. Under the CI-pinned Rust 1.95.0, cpu_profile (104 tests), virt (64), openvmm_core (98), and openvmm_helpers (98) pass, as do clippy --all-targets and rustdoc with warnings denied for those packages, clippy for x86_64-unknown-linux-gnu for cpu_profile, virt, virt_kvm, and virt_mshv, and xtask fmt. In a Linux container (rust:1.95.0), cpu_profile, virt_kvm (40 tests), and virt_mshv (76) pass. virt_whp's unit tests and its 16 hardware tests pass on the EPYC 7763 with WHP; no pinned profile serves that host yet, so the profile tests skip. Part of microsoft/nvx#396. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 01c35bf1-81da-4f98-8380-8a902ac0e5f9
MSHV and WHP derive a partition's processor feature banks from its CPU profile through HV_FEATURES, which mapped each bank bit to Intel's CPUID bit only (microsoft/nvx#396, row 5). AMD enumerates IBRS, IBPB, STIBP, SSBD, and PSFD in 0x80000008 EBX, and SVM in 0x80000001 ECX, so under an AMD profile profile_features read Intel's bits, which AMD profiles leave clear, and cleared those bank bits. The partition would have lost SPEC_CTRL and PRED_CMD while the profile's CPUID still advertised them, and a guest's unchecked SPEC_CTRL write would have raised #GP (G_UNCHECKED_MSR). The AMD-only bits that the banks define were unmapped, so they followed the host instead of the profile. An HvFeature now says where AMD CPUs enumerate its feature (AmdCpuid, read through cpuid_for): IBRS, IBPB, STIBP, and SSBD (mdd) in 0x80000008 EBX bits 14, 12, 15, and 24, PSFD in bit 28, and nested virtualization in SVM, 0x80000001 ECX[2]. The table gains the AMD-only bits: VIRT_SSBD (virt_spec_ctrl), the always-on STIBP preference, IBPB_RET (ibpb_rsb_flush), and BTC_NO in 0x80000008 EBX, and SBPB, IBPB_BRTYPE, SRSO_NO, SRSO_USER_KERNEL_NO, VERW_CLEAR (vrew_clear), and the TSA_L1_NO and TSA_SQ_NO immunities in 0x80000021. Intel profiles pin those bits clear, and the fleet's Intel hosts offer none of their bank bits, so the Intel profiles' banks are unchanged, as the tests of the fleet's hosts check. profile_features takes the bits of the profile's vendor, and restrict_cpuid_to_features, which builds the cheap supported surface from a host's CPUID, those of the vendor that the CPUID reports. The IA32_ARCH_CAPABILITIES bank bits keep Intel's meaning: AMD CPUs enumerate their immunities in CPUID, and SSB_NO's AMD bit, 0x80000008 EBX[26], stays unmapped. One feature controls no CPUID bit on AMD CPUs: intel_prefetch_support, Intel's PREFETCHW, whose bit, 0x80000001 ECX[8], AMD CPUs enumerate as 3DNowPrefetch. WHP presents that bit to AMD guests whatever the feature, which the EPYC 7763 host below does not even offer, so cpuid_for returns None for it on AMD (AmdCpuid::Uncontrolled): an AMD profile leaves the feature as the host offers it, and an AMD host's cheap surface keeps the bit. Mapping it cleared the feature under an AMD profile, which clears the bit, without hiding the bit, which only the profile's CPUID results do. The WHP and MSHV hardware tests that check the table, and the WHP and MSHV tests that check a host's profile against its features, read the CPUID bits of the vendor. On the Azure AMD EPYC 7763 host (Milan; family 0x19, model 1, stepping 1), WHP offers PSFD, BTC_NO, and nested virtualization but no speculation controls (bank 0 0x06020fcb67f79fbf, bank 1 0x200001ed), and features_control_the_mapped_cpuid_bits passes with the AMD bits: clearing psfd_support removes only 0x80000008 EBX[28], and btc_no_support only EBX[29]. Clearing nested_virt_support removes nothing there, because the probe partition presents no SVM. The bits that the host does not offer follow the AMD APM and the TLFS's names, unverified on hardware, and so does every MSHV mapping. Unit tests check that an AMD profile follows its own CPUID on that host's banks, keeping CLZERO and dropping SVM, RDPRU, APERF/MPERF, PSFD, and BTC_NO, which the derivation policy clears there; takes the speculation controls, PSFD from AMD's bit beside them, and the immunities from AMD's bits on a host that offers them, while BTC_NO goes; fails with E_PROFILE_UNSUPPORTED naming each one a host lacks; that a host's cheap surface loses AMD's bits, not Intel's, for the features it lacks; and that intel_prefetch_support controls 0x80000001 ECX[8] on Intel CPUs only. Under the CI-pinned Rust 1.95.0, cpu_profile's 108 unit tests and virt_whp's 35 pass, as do the 16 virt_whp hardware tests on the EPYC 7763; no pinned profile serves that host yet, so the profile tests skip. clippy --all-targets and rustdoc with warnings denied pass for cpu_profile and virt_whp, and for virt_kvm and virt_mshv on x86_64-unknown-linux-gnu, and xtask fmt makes no change. In a Linux container (rust:1.95.0), virt_kvm's 40 and virt_mshv's 76 unit tests pass. Part of microsoft/nvx#396. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 01c35bf1-81da-4f98-8380-8a902ac0e5f9
…files A Linux guest of an AMD CPU profile reads two AMD configuration MSRs that no backend presented as the time ABI needs them: - HWCR (0xc0010015): bsp_init_amd reads it with an unchecked rdmsr on every AMD CPU whose CPUID has the invariant TSC, which the time ABI's CPUID always sets. A fault fails the guest's G_UNCHECKED_MSR check, and a clear TscFreqSel (bit 24) makes Linux log "[Firmware Bug]: TSC doesn't count with P0 frequency!". WHP's legacy stub reads it as 0, and so does KVM. - DE_CFG (0xc0011029): init_amd sets its LFENCE serialization bit on every CPU whose CPUID does not enumerate it, with safe accessors. WHP does not implement it, so the read raises #GP and Linux silently loses the serializing LFENCE that its RDTSC ordering relies on. virt::time_abi::msr now defines the contract, AMD_CONFIG_MSRS: under an AMD CPU profile, HWCR reads as TscFreqSel only and DE_CFG as LFENCE serialization only, on every VP and backend; a write of the value that a read returns succeeds and changes nothing, and any other write raises #GP. Linux writes neither on a profile's CPU: it sets IRPERF_EN only when CPUID enumerates the instructions-retired counter and CPUID faulting only on request, and the derivation policy clears both. Each backend routes the two MSRs to OpenVMM under an AMD profile only, so Intel partitions keep their handling exactly: - WHP: UnhandledMsrs exits already deliver them; serve_msr answers them ahead of the legacy stubs. - KVM: the MSR filter of an AMD profile also denies them, so the accesses exit to OpenVMM (9 filter ranges, within KVM's 16). - MSHV: an AMD profile also installs MSR intercepts for them. The Guide's Time and CPU compatibility section states the contract. MSHV also presents AMD's processor topology leaf 0x8000001E per VP. Like the extended topology leaves, the hypervisor does not provide its per-VP fields for these partitions, so create_vp registers each VP's own result: the extended APIC ID, the compute unit ID within the socket, and the socket's node ID, computed as virt::x86::topology computes the BSP's and as the WHP and KVM backends already present them. This completes row 6 of the issue, and with the AMD cache sharing of 0x8000001D and the core count of 0x80000008 from the first commit, the guest's AMD topology is consistent on every backend, so profiles keep TOPOEXT instead of hiding it. Tests cover the contract's values and writes, the KVM filter ranges of both vendors, the MSR serving of each backend under both vendors (Intel partitions leave HWCR and DE_CFG to their existing handling), and the MSHV per-VP 0x8000001E values with and without SMT across sockets. Validation, with Rust 1.95.0: - cargo test -p virt -p virt_whp: 65 and 36 passed. - cargo test -p virt_whp -- --ignored --test-threads=1 on an AMD EPYC 7763 (Milan) Azure VM with nested WHP: all 16 hardware tests passed. - cargo test -p virt_kvm -p virt_mshv in a Linux container (rust:1.95.0): 41 and 77 passed; their hardware tests need /dev/kvm and /dev/mshv. - cargo clippy --all-targets -D warnings for virt, virt_whp, and openvmm_core, and for virt_kvm and virt_mshv with --target x86_64-unknown-linux-gnu; rustdoc with -D warnings for all four; cargo xtask fmt --fix. - On the same WHP host, a release build booted the NVX Alpine guest (Linux 6.18.38) on 4 VPs with --cpu-profile host (amd.host.v1): the BSP read HWCR once (0x1000000) and every VP read DE_CFG once (0x2), with no write; dmesg had no Firmware Bug or unchecked MSR access line; nvx-time reported phase=boot status=ok; each CPU's APIC ID matched its initial APIC ID; and the L3 cache was shared across all 4 CPUs. The KVM and MSHV paths are hardware-unverified: no AMD KVM or MSHV host was available. Part of microsoft/nvx#396. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 01c35bf1-81da-4f98-8380-8a902ac0e5f9
No pinned profile served an AMD CPU, so --cpu-profile auto, the default, failed every AMD host with E_PROFILE_HOST_UNKNOWN (microsoft/nvx#396, plan item 5). The catalog now pins amd.milan.v1, AMD EPYC, third generation (Milan): family 25 (0x19), model 1, steppings 0 to 15. No other generation uses family 25 model 1, so the generation takes every stepping of the Milan die, Milan-X's 2 included, whose CPUID differs in its signature and L3 size: the profile's checks treat 0x80000001 EAX, 0x80000006, and 0x8000001D as descriptive, as the derivation tests check for stepping 2. Genoa (model 17) and the Zen 3 client parts stay without a profile. As intel.alderlake.v1 was, the profile is derived from one fingerprint: openvmm --cpu-fingerprint on WHP on an Azure Standard_D16as_v5 VM with an AMD EPYC 7763 (stepping 1) and nested Hyper-V, surface digest sha256:35a6cf971fd37b3f28176b1164b37efeec4bcb5094b5d8222d581ee1dd3e7307. The derivation policy, unchanged since the first commit of this series (openvmm-cpu-profile-policy/v1 with its AMD rules), derives it with cargo run -p cpu_profile --example derive_profile -- milan 1 <fingerprint> ID amd.milan.v1, digest sha256:463ee0368dc01bf56a3ab1157d62b21b51d11b3dcccb46c804864748ef696543. It presents what that host's WHP offers its guests, under the policy: AVX2, SHA, VAES, VPCLMULQDQ, and the x87, SSE, and AVX XSAVE states; TOPOEXT with the cache leaves 0x80000005 and 0x8000001D, whose sharing counts OpenVMM sets per VM, and 0x8000001E, whose IDs it sets per VP; CLZERO; a 48-bit physical address width; the brand string "AMD EPYC Processor (Milan)"; and no pinned MSR, since AMD CPUs have no IA32_ARCH_CAPABILITIES. It has no SVM, RDPRU, SME or SEV (0x8000001F is zero), and, because that WHP offers none, no IBRS, IBPB, STIBP, or SSBD and nothing in 0x80000021. That WHP offers PSFD and BTC_NO, but the policy drops both: PSFD without a SPEC_CTRL control, and BTC_NO, which KVM never enumerates. So no KVM host of the generation fails the profile on either bit, which a KVM surface of the same CPU now checks, and 0x80000008 EBX holds CLZERO and the XSAVE error pointer bit only. Linux guests of the profile mitigate Spectre v2 with retpolines and report SSB, SRSO, and TSA as vulnerable on every host. Milan hosts on KVM and MSHV, whose bare-metal view offers more, should support the profile, but none was available to verify it, nor the AMD paths of those backends; a later revision derived from such hosts could add the speculation controls, and PSFD beside them. pinned_data.rs, regenerated with generate_pinned from the five files in catalog order, gains the new profile's block and changes nothing else but the array's length: the four Intel profiles' constants are byte-identical, and their JSON files and golden digests are unchanged, which the catalog test checks. Tests: - catalog: Milan and Milan-X select amd.milan.v1; Genoa, an Intel CPU, and a Hygon CPU with Milan's signature select nothing; selecting the other vendor's profile fails with E_CPU_GENERATION; the new file has its golden digest. - derive: the pinned profile is the policy's derivation of the EPYC 7763's recorded CPUID (test_support::MILAN_WHP_CPUID), re-deriving every pinned profile, Milan's included, reproduces it, and a KVM host of that CPU, which offers neither PSFD nor BTC_NO, supports it. - check: the --cpu-fingerprint check of that host passes with a partition configured from the profile, though its probe partition presents CET's XSAVE components outside the profile. - The tests that assumed Intel profiles take each profile's vendor: the L3 sharing test reads 0x8000001D on AMD, openvmm_helpers' effective CPUID record test builds AMD's topology fields, and virt_whp's unit tests run amd.milan.v1 too: its CPUID exits add 0x8000001E (9 exits), its brand is its generation's, and the comparison with the profile programming of de39f6a, which predates AMD profiles, ignores AMD's topology fields. Validation, with Rust 1.95.0: - cargo test: cpu_profile 111, virt 65, virt_whp 36, openvmm_core 98, and openvmm_helpers 98 passed; in a Linux container (rust:1.95.0), cpu_profile, virt, virt_kvm (41), and virt_mshv (77) passed. - On the EPYC 7763 WHP host, all 16 virt_whp hardware tests passed, now with amd.milan.v1 rather than skipping: the profile's feature bank 1 is 0x24, VP 0 presents the profile programming's CPUID at all 390 probes but for AMD's topology fields, and the host's two entries outside the profile (0xd.11 and 0xd.12, CET) read zero on a partition of the profile. - A release build there prints NVX-CPU-PROFILE: status=pass backend=whp generation=milan profile=amd.milan.v1 profile_digest=sha256:463ee036... for --cpu-fingerprint. - clippy --all-targets and rustdoc with warnings denied for cpu_profile, virt, virt_whp, openvmm_core, and openvmm_helpers, and for virt_kvm and virt_mshv on x86_64-unknown-linux-gnu; cargo xtask fmt --fix. Part of microsoft/nvx#396. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 01c35bf1-81da-4f98-8380-8a902ac0e5f9
|
This PR modifies files containing For more on why we check whole files, instead of just diffs, check out the Rustonomicon |
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
It changes the cross-backend CPU ABI and includes AMD KVM and MSHV paths without runtime validation.
Review effort: Balanced
Findings: None
What changed in this PR
Adds AMD CPU-profile support to the time ABI, including the pinned Milan profile and backend-specific topology, feature, and MSR handling.
Changes:
- Adds AMD-aware profile derivation, validation, topology, and Hyper-V feature mappings.
- Pins
amd.milan.v1and enables AMD host profiles. - Serves AMD HWCR and DE_CFG consistently across WHP, KVM, and MSHV.
| File | Description |
|---|---|
Guide/src/reference/openvmm/management/cli.md |
Documents AMD host-profile selection. |
Guide/src/user_guide/openvmm/snapshots.md |
Documents Milan and AMD snapshot behavior. |
openvmm/openvmm_core/src/worker/dispatch.rs |
Propagates AMD profile guidance in errors. |
openvmm/openvmm_core/src/worker/dispatch/time_abi.rs |
Expands host-profile hints to AMD. |
openvmm/openvmm_helpers/src/snapshot/time.rs |
Covers AMD profiles in snapshot handling. |
vmm_core/cpu_profile/profiles/amd.milan.v1.json |
Defines the pinned Milan profile. |
vmm_core/cpu_profile/src/catalog.rs |
Adds Milan to the profile catalog. |
vmm_core/cpu_profile/src/check.rs |
Tests Milan fingerprint compatibility. |
vmm_core/cpu_profile/src/derive.rs |
Implements vendor-specific AMD derivation. |
vmm_core/cpu_profile/src/effective.rs |
Handles AMD VM-owned topology fields. |
vmm_core/cpu_profile/src/hv_banks.rs |
Maps Hyper-V banks to AMD CPUID bits. |
vmm_core/cpu_profile/src/lib.rs |
Exposes AMD profile APIs. |
vmm_core/cpu_profile/src/pinned.rs |
Registers the Milan profile. |
vmm_core/cpu_profile/src/pinned_data.rs |
Adds generated Milan profile data. |
vmm_core/cpu_profile/src/profile.rs |
Adds vendor-aware profile validation and masks. |
vmm_core/cpu_profile/src/surface.rs |
Classifies AMD surface fields. |
vmm_core/cpu_profile/src/test_support.rs |
Provides AMD fingerprint fixtures. |
vmm_core/cpu_profile/src/vendor.rs |
Defines supported CPU vendors. |
vmm_core/virt/src/time_abi/cpuid.rs |
Tests AMD cache topology presentation. |
vmm_core/virt/src/time_abi/msr.rs |
Defines fixed AMD configuration MSRs. |
vmm_core/virt/src/x86/topology.rs |
Generates AMD cache-sharing topology. |
vmm_core/virt_kvm/src/arch/x86_64/mod.rs |
Propagates profile vendor into KVM setup. |
vmm_core/virt_kvm/src/arch/x86_64/time_abi.rs |
Routes AMD MSRs through KVM userspace handling. |
vmm_core/virt_mshv/src/x86_64/mod.rs |
Adds AMD per-VP identity setup. |
vmm_core/virt_mshv/src/x86_64/profile_features.rs |
Makes feature tests vendor-aware. |
vmm_core/virt_mshv/src/x86_64/time_abi.rs |
Adds AMD MSR and topology handling. |
vmm_core/virt_whp/src/profile_features.rs |
Updates WHP feature mapping tests. |
vmm_core/virt_whp/src/time_abi.rs |
Serves AMD MSRs and CPUID through WHP. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This was referenced Oct 6, 2026
This was referenced Oct 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Support AMD CPUs in the time ABI's CPU profiles, for microsoft/nvx#396. This accepts AMD CPUs in profiles and host profiles, gives AMD profiles their own derivation rules and VM-owned topology fields, maps the Hyper-V feature banks to AMD's CPUID bits, serves AMD's HWCR and DE_CFG MSRs, and pins
amd.milan.v1. The four Intel profiles stay byte-identical.Why
Every microVM cold boot selects a CPU profile, and only Intel profiles existed. On an AMD host,
--cpu-profile autoand--cpu-profile hostboth failed withE_PROFILE_HOST_UNKNOWN. A profile derived from an AMD fingerprint failed validation. Had it been accepted, every cold boot would have failed withE_CPU_SURFACE, because OpenVMM sets AMD topology fields that the profile pinned. microsoft/nvx#396 lists the eight blockers.Commits
d290df675cpu_profile, virt: accept AMD CPUs in CPU profiles and host profilesCpuVendorandamd.host.v1. AMD's topology fields (0x80000008ECX,0x8000001Dsharing counts,0x8000001E) are VM-owned in AMD profiles only. The derivation policy gains an AMD section: data leaves0x80000005,0x8000001D,0x8000001E, and0x80000021; SVM, IBS, LWP, MONITORX, RDPRU, PPIN, CPPC, SME/SEV, and BTC_NO cleared; PSFD kept only with a SPEC_CTRL control, by the condition that KVM's supported surface now shares.0x8000001Dsubleaves are handled like leaf 4's, with one L3 per socket.auto'sE_PROFILE_HOST_UNKNOWNandE_PROFILE_UNSUPPORTEDcold-boot errors name--cpu-profile hoston Intel and AMD hosts905993c36cpu_profile: map the Hyper-V feature banks to AMD's CPUID bits933c1de0cvirt: serve AMD's HWCR and DE_CFG and per-VP 0x8000001E under AMD profiles0x8000001Eper VP. TOPOEXT stays07850d27acpu_profile: pin an AMD Milan CPU profile, amd.milan.v1amd.milan.v1covers family 25, model 1, every stepping. It is derived from one WHP fingerprint of an Azure EPYC 7763 VM, with digestsha256:463ee0368dc01bf56a3ab1157d62b21b51d11b3dcccb46c804864748ef696543Each commit message details its rules, tests, and validation.
Intel invariance
pinned_data.rschanges only the array length and appends Milan's block.strip_psfd_leafreads the same bits as before, through a function it now shares with the policy.Pre-publication review
An independent review of the first revision found that it pinned BTC_NO and PSFD in
amd.milan.v1:kvm_cpu_cap_init(CPUID_8000_0008_EBX, ...)omits it.So every KVM Milan host, GitHub's EPYC 7763 runners included, would have failed with
E_PROFILE_UNSUPPORTED. The AMD policy now clears BTC_NO, which Linux never needs on family 0x19 or later because it marks no such CPU as Retbleed-affected. It also clears PSFD, which is controlled through SPEC_CTRL, unless a SPEC_CTRL control stays. The profile was re-derived:0x80000008EBX changed from0x30000005to0x00000005.Scope and exclusions
0x8000001E) are unit-tested only, and Milan hosts on KVM and MSHV are unverified.amd.milan.v1has no speculation controls, because the source WHP offers none. Its Linux guests therefore use retpolines and report SSB, SRSO, and TSA as vulnerable on every host.virt_whpdoes not build foraarch64-pc-windows-msvc(lib.rs:1390), as at the base.Validation
The series is based on
mainata41cf7351, which includes #113. The two changes don't overlap in code, and both sides' Guide edits are kept.On an Azure Standard_D16as_v5 VM (AMD EPYC 7763, 25/1/1) with Windows 11 build 26200 and nested WHP, under the CI-pinned Rust 1.95.0, at each of the four commits:
--all-targetsand rustdoc with warnings denied, andxtask fmt, on Windows. Forvirt_kvmandvirt_mshv, clippy also runs forx86_64-unknown-linux-gnu.cpu_profile104, 108, 108, and 111;virt64, 64, 65, and 65;virt_whp35, 35, 36, and 36;openvmm_core98,openvmm_helpers98, andopenvmm_entry179;virt_kvm41 andvirt_mshv77 in arust:1.95.0Linux container, wherecpu_profile111 andvirt65 also pass.virt_whphardware tests on the EPYC 7763, at every commit. At the head they run onamd.milan.v1.With a release build of the head,
--cpu-fingerprintpasses withamd.milan.v1. NVX's runtime validation on the same host is described in microsoft/nvx#404.Dependents