Skip to content

openhcl: relay NVIDIA GPUs to CVM guests behind a host config flag - #4207

Draft
Robert Schaedler (robertschaedler3) wants to merge 21 commits into
microsoft:mainfrom
robertschaedler3:robertschaedler3/cgpu-vpci-relay-host-config
Draft

openhcl: relay NVIDIA GPUs to CVM guests behind a host config flag#4207
Robert Schaedler (robertschaedler3) wants to merge 21 commits into
microsoft:mainfrom
robertschaedler3:robertschaedler3/cgpu-vpci-relay-host-config

Conversation

@robertschaedler3

Copy link
Copy Markdown
Member

Relays NVIDIA GPUs (and their NVLink fabric) through the VPCI relay to confidential VM guests, enabling confidential GPU workloads on Azure Local.

The resulting posture is reported in the attestation runtime claims as nvidia-vpci-relay-allowed, so a relying party can tell whether a CVM had its device filter widened.

Why vendor + class rather than an explicit device list?

Datacenter GPUs (H100/H200/HGX H100/H200, HGX B200/B300) are headless and enumerate as 3D controllers rather than VGA, and HGX clusters additionally expose NVSwitch devices that are PCI bridges so a single display-class filter would miss the fabric. Keying on vendor + the two relevant classes covers whole clusters while still rejecting all non-NVIDIA devices, and avoids a rebuild each time a new SKU ships.

Relaying NVIDIA GPUs and NVLink/NVSwitch fabric devices into a
confidential guest was gated behind the `nvidia_vpci_relay_allowed` cargo
feature, which required a separate build. That build has a different
launch measurement, so customers had to re-pin attestation policies to a
new MRDT, and it depended on sideloading remaining permitted.

Replace the build-time feature with a per-VM host configuration flag,
`NvidiaVpciRelayAllowed`, delivered over the existing Device Platform
Settings channel. It defaults to false, so hosts that do not set it are
unaffected and the default relay allow-list is unchanged. This collapses
the two builds back into one: no divergent measurement, no MRDT churn,
and no sideloading dependency.

Report the resulting posture to attestation as a new runtime claim so a
relying party can tell whether a given CVM had the relay widened. The
claim is `Option<bool>` and is skipped during serialization when unset.
This matters beyond wire size: the serialized `AttestationVmConfig` is
also an input to the hardware-derived key KDF, so emitting the field
unconditionally would change the derived sealing keys for every existing
guest and break stateful CVMs across the upgrade. Omitting it when unset
keeps the runtime claims byte-for-byte identical for guests that do not
use the feature, following the precedent already set by `current_time`
and `vmgs_provisioner`. A regression test covers this.

The flag is unmeasured host input. That is acceptable because admission
is not privilege: a relayed non-TDISP device DMAs only into shared
memory and cannot reach guest-private memory or lower a VTL, and the
guest independently attests any device it chooses to trust. The set of
admissible devices remains compiled in; the host can only enable or
disable that fixed set, never widen it.

Also drop the now-redundant `x64-cvm-nvidia-vpci-relay` IGVM recipe,
which was identical to `x64-cvm` apart from the removed feature.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc
…list is empty

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc
Copilot AI lite review requested due to automatic review settings August 10, 2026 21:17

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.

Pull request overview

This PR introduces an opt-in host configuration flag to allow relaying NVIDIA datacenter GPUs (and NVLink/NVSwitch fabric devices) into confidential guests via the VPCI relay, and surfaces that posture in the guest’s attestation runtime claims so relying parties can detect the widened device filter.

Changes:

  • Make VPCI relay device filtering deny-by-default (empty allow-list admits nothing) and rate-limit denial warnings.
  • Add NVIDIA GPU + fabric allow-list rules gated by a new nvidia_vpci_relay_allowed host setting, and emit an optional nvidia-vpci-relay-allowed runtime claim only when actually used.
  • Extend GET/DPS transport structs to carry the new host setting end-to-end, plus update attestation protocol/tests accordingly.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
vm/devices/pci/vpci_relay/src/lib.rs Deny-by-default allow-list evaluation, ratelimited warnings, and unit tests for allow-list semantics.
vm/devices/pci/pci_core/src/spec.rs Adds DISPLAY_CONTROLLER_3D PCI subclass constant needed for NVIDIA GPU filtering.
vm/devices/get/guest_emulation_transport/src/client.rs Plumbs nvidia_vpci_relay_allowed from DPS JSON into platform settings.
vm/devices/get/guest_emulation_transport/src/api.rs Adds platform setting field and documentation for NVIDIA VPCI relay gating.
vm/devices/get/guest_emulation_device/src/lib.rs Initializes the new platform setting to a safe default (false).
vm/devices/get/get_protocol/src/dps_json.rs Extends DPS JSON schema with nvidia_vpci_relay_allowed (default false).
openhcl/underhill_core/src/worker.rs Gates NVIDIA allow-list entries and attestation claim emission on the new host flag.
openhcl/underhill_attestation/src/lib.rs Updates attestation test helpers for the new optional claim field.
openhcl/underhill_attestation/src/igvm_attest/mod.rs Updates IGVM attestation tests for the new optional claim field.
openhcl/underhill_attestation/src/hardware_key_sealing.rs Adds regression test ensuring claim omission preserves KDF input when unset.
openhcl/openhcl_attestation_protocol/src/igvm_attest/get.rs Adds the optional nvidia-vpci-relay-allowed runtime claim field with skip_serializing_if.

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

Comment thread openhcl/underhill_core/src/worker.rs Outdated
Comment on lines +2116 to +2117
let vpci_relay_active =
with_vmbus_relay && dps.general.vpci_boot_enabled && isolation.is_isolated();
Comment thread vm/devices/get/guest_emulation_transport/src/api.rs
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 10, 2026 21:24
…ates

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc

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.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Suppressed comments (3)

vm/devices/pci/vpci_relay/src/lib.rs:210

  • AllowedDevice uses Option<...> fields where None acts as the wildcard; the doc currently says a hardware ID of !0 is treated as a wildcard, which doesn't match this API.
    /// Adds an allowed device to the list. If one of the hardware ID is `!0`
    /// then it is treated as a wildcard.

openhcl/openhcl_attestation_protocol/src/igvm_attest/get.rs:496

  • This claim is used to report whether the device filter was widened (per PR description), not whether at least one NVIDIA device was actually present and relayed. The wording “were relayed” is easy to misread as the latter; consider phrasing it as “were allowed to be relayed”.
        /// Whether NVIDIA GPUs and NVLink/NVSwitch fabric devices were relayed
        /// into this guest.

openhcl/underhill_core/src/worker.rs:2134

  • This comment says “devices are actually relayed”, but at this point the code is only deciding whether the feature/claim is enabled (it can be true even if no matching devices are present). Rewording avoids overstating the semantics.
        // Reported only when the devices are actually relayed, and omitted
        // entirely otherwise so that the runtime claims (and hence the sealing
        // key derivation) are unchanged for guests not using this feature.

Comment thread vm/devices/get/guest_emulation_transport/src/api.rs
Comment thread vm/devices/pci/vpci_relay/src/lib.rs
Comment thread openhcl/openhcl_attestation_protocol/src/igvm_attest/get.rs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc
Copilot AI review requested due to automatic review settings August 10, 2026 21:32

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.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (3)

openhcl/openhcl_attestation_protocol/src/igvm_attest/get.rs:499

  • AttestationVmConfig derives MeshPayload, which assigns field numbers by struct field order unless explicitly overridden (see support/mesh/mesh_derive/src/lib.rs:313-323). Inserting nvidia_vpci_relay_allowed here shifts the implicit field numbers for vm_unique_id, vmgs_provisioner, and hardware_sealing_policy, breaking compatibility with existing binaries/protocol consumers. Add explicit #[mesh(N)] numbers to preserve the prior numbering (and give the new field a new number).
        /// Whether NVIDIA GPUs and NVLink/NVSwitch fabric devices were relayed
        /// into this guest.
        ///
        /// `None` when the relay was not enabled for these devices, which is
        /// the default. This field is skipped during serialization when `None`

vm/devices/pci/vpci_relay/src/lib.rs:213

  • The add_allowed_device doc comment still describes the old !0 wildcard behavior, but AllowedDevice now uses Option fields where None is the wildcard (see AllowedDevice::allows). This can mislead callers when building allow-list rules.
    /// Adds an allowed device to the list. If one of the hardware ID is `!0`
    /// then it is treated as a wildcard.
    ///
    /// Devices are denied by default: a relay with no allowed devices admits
    /// nothing.

openhcl/underhill_core/src/worker.rs:2139

  • This comment says the claim is emitted only when NVIDIA devices are "actually relayed", but nvidia_vpci_devices_relayed is derived from enable_vpci_relay && dps.general.nvidia_vpci_relay_allowed (a configuration/allow-list widening), not from observing whether any NVIDIA devices were present. Consider rewording to reflect what the value actually represents.
        // Reported only when the devices are actually relayed, and omitted
        // entirely otherwise so that the runtime claims (and hence the sealing
        // key derivation) are unchanged for guests not using this feature.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc
…mesh field numbering

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc
Copilot AI review requested due to automatic review settings August 10, 2026 22:21

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.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (3)

vm/devices/pci/vpci_relay/src/lib.rs:213

  • The add_allowed_device doc comment still describes a !0 wildcard, but AllowedDevice uses Option fields where None is the wildcard. This mismatch can lead to incorrect callers and makes the deny-by-default semantics harder to understand.
    /// Adds an allowed device to the list. If one of the hardware ID is `!0`
    /// then it is treated as a wildcard.
    ///
    /// Devices are denied by default: a relay with no allowed devices admits
    /// nothing.

openhcl/underhill_core/src/worker.rs:2140

  • This comment says the claim is reported only when the devices are "actually relayed", but nvidia_vpci_devices_relayed is derived from configuration (enable_vpci_relay && ..._allowed) and does not reflect whether any NVIDIA devices were present. Clarifying the wording avoids overstating what the claim means.
        // Reported only when the devices are actually relayed, and omitted
        // entirely otherwise so that the runtime claims (and hence the sealing
        // key derivation) are unchanged for guests not using this feature.
        nvidia_vpci_relay_allowed: nvidia_vpci_devices_relayed.then_some(true),

openhcl/openhcl_attestation_protocol/src/igvm_attest/get.rs:507

  • The runtime-claims field name (nvidia-vpci-relay-allowed) and the PR description suggest this is about whether the host opted in / the device filter was widened, but the doc comment says the devices "were relayed". Align the wording with the intended posture signal to avoid implying that a GPU was necessarily present.
        /// Whether NVIDIA GPUs and NVLink/NVSwitch fabric devices were relayed
        /// into this guest.
        ///
        /// `None` when the relay was not enabled for these devices, which is
        /// the default. This field is skipped during serialization when `None`

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.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (4)

openhcl/underhill_core/src/worker.rs:2139

  • This comment says the claim is reported only when the devices are "actually relayed", but nvidia_vpci_devices_relayed is a configuration/enablement boolean and does not reflect whether any NVIDIA device was present/attached. Rewording this avoids implying stronger semantics than the code provides.
        // Reported only when the devices are actually relayed, and omitted
        // entirely otherwise so that the runtime claims (and hence the sealing
        // key derivation) are unchanged for guests not using this feature.

vm/devices/pci/vpci_relay/src/lib.rs:213

  • The doc comment for add_allowed_device says a hardware ID value of !0 is treated as a wildcard, but AllowedDevice uses Option<...> fields where None is the wildcard. This is misleading for callers and reviewers (especially now that deny-by-default semantics are emphasized).
    /// Adds an allowed device to the list. If one of the hardware ID is `!0`
    /// then it is treated as a wildcard.
    ///
    /// Devices are denied by default: a relay with no allowed devices admits
    /// nothing.

openhcl/openhcl_attestation_protocol/src/igvm_attest/get.rs:510

  • The runtime-claims field name is nvidia_vpci_relay_allowed, and the PR description describes it as reporting whether the device filter was widened. The doc comment currently says NVIDIA devices "were relayed" which implies device presence, not enablement/allowance. This can confuse relying parties and future maintainers about the claim’s semantics.
        /// Whether NVIDIA GPUs and NVLink/NVSwitch fabric devices were relayed
        /// into this guest.
        ///
        /// `None` when the relay was not enabled for these devices, which is
        /// the default. This field is skipped during serialization when `None`

openhcl/underhill_core/src/worker.rs:1730

  • nvidia_vpci_devices_relayed reads like it reflects device presence/attachment, but it’s actually an enablement gate (enable_vpci_relay && ...allowed). Renaming to something like nvidia_vpci_relay_allowed / enable_nvidia_vpci_relay would better match the attestation field and avoid semantic confusion (it’s used both for the allow-list gate and the runtime claim).

This issue also appears on line 2137 of the same file.

    let nvidia_vpci_devices_relayed = enable_vpci_relay && dps.general.nvidia_vpci_relay_allowed;

…esence

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc
Copilot AI review requested due to automatic review settings August 10, 2026 22:40

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.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (1)

openhcl/underhill_core/src/worker.rs:1739

  • This change introduces a new host-configurable gate (nvidia_vpci_relay_allowed) and a new attestation runtime claim (nvidia-vpci-relay-allowed). The OpenHCL VMBus/VPCI Guide page documents VPCI relay and filtering but does not mention this new flag/claim, so readers won’t know how to enable it or how it impacts attestation/sealing behavior.
    // Whether the NVIDIA GPU and NVLink/NVSwitch allow-list entries are
    // installed: the host must opt in, and the VPCI relay must be running.
    // This is an enablement gate -- it does not indicate that such a device is
    // present or attached.
    //
    // This single value gates both the relay allow-list entries and the
    // attestation claim that reports them. Do not re-derive either from a
    // different set of conditions: if the two can disagree, the host can widen
    // the filter while attestation reports that it did not.
    let enable_nvidia_vpci_relay = enable_vpci_relay && dps.general.nvidia_vpci_relay_allowed;

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc
Copilot AI review requested due to automatic review settings August 12, 2026 18:17

Copilot AI commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

One or more custom setup steps configured for this repository failed during this Copilot code review run:

Restore packages

Setup steps run before each review. If the review above is missing context, or no review was posted at all, the failing step above may be the cause. See the workflow run for failure details, fix your setup steps configuration, and re-request a review.

Note

You can configure setup steps for Copilot code review separately from Copilot cloud agent with a copilot-code-review.yml file. Read the docs for details.

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.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated no new comments.

Suppressed comments (2)

vm/devices/pci/vpci_relay/Cargo.toml:31

  • vpci_relay now has unit tests; if you switch them to use test_with_tracing::test (as done in other PCI crates), the crate needs a test_with_tracing dev-dependency so it compiles.
tracelimit.workspace = true
tracing.workspace = true

vm/devices/pci/vpci_relay/src/lib.rs:468

  • The new unit tests use the built-in #[test], so tracing won’t be initialized for these tests. In this repo’s PCI-related crates, unit tests typically import test_with_tracing::test so #[test] expands to the tracing-initializing attribute (e.g. vm/devices/pci/vpci_client/src/tests.rs:28, vm/devices/pci/vfio_assigned_device/src/lib.rs:1576).

Please add use test_with_tracing::test; to this module (and add the corresponding dev-dependency in Cargo.toml).

mod tests {
    use super::AllowedDevice;
    use super::device_allowed;
    use pci_core::spec::hwid::ClassCode;
    use pci_core::spec::hwid::HardwareIds;
    use pci_core::spec::hwid::ProgrammingInterface;
    use pci_core::spec::hwid::Subclass;

… setting

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc
Copilot AI review requested due to automatic review settings August 12, 2026 18: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.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.

Suppressed comments (2)

vm/devices/pci/vpci_relay/Cargo.toml:41

  • If you adopt the repo’s common test_with_tracing::test convention for these new unit tests, vpci_relay will also need test_with_tracing as a dev-dependency. Adding it here avoids relying on transitive dev-deps from other crates.
sparse_mmap.workspace = true

[dev-dependencies]
vpci.workspace = true
mesh.workspace = true

vm/devices/pci/vpci_relay/src/lib.rs:467

  • The new unit tests use #[test] without importing test_with_tracing::test, which means tracing may not be initialized consistently with the rest of the codebase’s unit tests. Importing test_with_tracing::test in this module keeps test behavior consistent and ensures traces show up when tests fail.
    use super::device_allowed;
    use pci_core::spec::hwid::ClassCode;
    use pci_core::spec::hwid::HardwareIds;
    use pci_core::spec::hwid::ProgrammingInterface;
    use pci_core::spec::hwid::Subclass;

…ridges

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5621a3b2-62f0-42aa-914b-32d48349f3cc
Copilot AI review requested due to automatic review settings August 12, 2026 20:40

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.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

openvmm/openvmm_entry/src/cli_args.rs:857

  • This PR adds a new user-facing CLI flag (--nvidia-vpci-relay-allowed), but there is no corresponding update to the OpenVMM Guide CLI reference. Please document the new flag (and its security/attestation implications) in Guide/src/reference/openvmm/management/cli.md so users can discover it and understand when to use it.
    /// allow NVIDIA GPUs and NVLink/NVSwitch fabric devices through the VTL 2
    /// VPCI relay's device filter.
    #[clap(long, requires("vtl2"))]
    pub nvidia_vpci_relay_allowed: bool,

Comment on lines 71 to 75
pub vmbus_redirection: bool,
/// Allow NVIDIA GPUs and NVLink/NVSwitch fabric devices through the
/// VPCI relay's device filter.
pub nvidia_vpci_relay_allowed: bool,
/// Enable the TPM.
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.

2 participants