qemu/machine: extend data model for Q35 CoCo and NUMA SHM

Add the fields needed to express Q35-specific topologies:

probe.rs:
  - HostTopology: +numa_distances (src/dst/val triples), +cold_plug_ports
    (pre-provisioned pcie-root-port count), +protection (sev-snp-guest /
    tdx-guest capability detected by the host probe)
  - SocketInfo: +host_node, +mem_path, +mem_size for per-socket NUMA pinning
    and /dev/shm or EGM file-backed memory
  - ProtectionDevice enum: SevSnp and Tdx variants, with an id() accessor used
    by platform.rs to set confidential_guest_support on the machine line

topology.rs:
  - PciRootPort: +slot, +multifunction (Q35 cold-plug ports carry these;
    Grace ports do not), +io_reserve (Grace only, absent on Q35)
  - VfioDevice: rombar: bool -> Option<bool> (CoCo Q35 has no rombar field),
    +iommufd_id for per-device CoCo iommufd (Grace uses a shared iommufd0),
    +pci_vendor_id/pci_device_id for x86 CoCo measured-boot attestation
  - VfioDeviceKind::GpuPci: vfio-pci (Q35 / CoCo) vs existing Gpu (vfio-pci-
    nohotplug for Grace aarch64)
  - PciTopology: +cold_plug_ports for pre-provisioned Q35 root ports on pcie.0

q35.rs:
  - Q35: +kernel_irqchip (split for CoCo, absent for vanilla) and
    +confidential_guest_support referencing the protection object id

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
This commit is contained in:
Zvonko Kaiser
2026-07-14 14:58:35 +00:00
parent 8a0ff6c9ca
commit fb9d778065
3 changed files with 68 additions and 1 deletions

View File

@@ -8,11 +8,23 @@ pub(crate) struct HostTopology {
pub sockets: Vec<SocketInfo>,
pub gpu_smmu_groups: Vec<GpuSmmuGroup>,
pub egm_sockets: Vec<EgmSocketInfo>,
/// `-numa dist` entries emitted after all NUMA nodes. Each tuple is (src, dst, val).
pub numa_distances: Vec<(u32, u32, u32)>,
/// Number of pre-provisioned `pcie-root-port` devices on the Q35 default bus
/// (cold-plug topology; `cold_plug_vfio=root-port` in kata config).
pub cold_plug_ports: u32,
pub protection: Option<ProtectionDevice>,
}
pub(crate) struct SocketInfo {
pub id: u32,
pub cpu_range: Range<u32>,
/// Host NUMA node to bind this socket's memory to via `policy=bind`.
pub host_node: Option<u32>,
/// File-backed memory path (e.g. `/dev/shm`). `None` → `memory-backend-ram`.
pub mem_path: Option<String>,
/// Per-socket memory size in bytes. `None` → use the Platform-level default.
pub mem_size: Option<u64>,
}
/// GPUs sharing a physical SMMU must be placed on the same pxb-pcie + arm-smmuv3.
@@ -26,3 +38,33 @@ pub(crate) struct EgmSocketInfo {
pub socket: u32,
pub total_size: u64,
}
/// CoCo hardware protection capability detected by the host probe.
///
/// Drives three platform decisions: the `-object <type>-guest` preamble, the
/// `kernel_irqchip=split` machine flag, and the `CpuModel` (EpycV4 for SNP,
/// Host for TDX).
#[derive(Clone)]
pub(crate) enum ProtectionDevice {
SevSnp {
id: String,
cbitpos: u8,
reduced_phys_bits: u8,
kernel_hashes: bool,
policy: u64,
host_data: Option<String>,
},
/// TDX — fields TBD when a production capture is available.
Tdx {
id: String,
},
}
impl ProtectionDevice {
pub(crate) fn id(&self) -> &str {
match self {
ProtectionDevice::SevSnp { id, .. } => id,
ProtectionDevice::Tdx { id } => id,
}
}
}

View File

@@ -6,9 +6,14 @@ use super::platform::BaseMachine;
pub(crate) struct Q35 {
pub base: BaseMachine,
/// `kernel_irqchip=split` is required for CoCo (SNP/TDX); absent on vanilla Q35.
pub kernel_irqchip: Option<String>,
/// References the id of `Objects::protection`. Set by `apply_host_defaults`
/// when `HostTopology::protection` is `Some`.
pub confidential_guest_support: Option<String>,
/// Not bus-attached; contrast with BusIommu on PciRootComplex.
pub intel_iommu: Option<IntelIommuConfig>,
// pub runtime: RuntimeFeatures, -- Phase 3+
}
pub(crate) struct IntelIommuConfig {

View File

@@ -5,6 +5,9 @@
pub(crate) struct PciTopology {
pub default_bus: Option<String>,
pub roots: Vec<PciRootComplex>,
/// Pre-provisioned root ports emitted on the default bus (Q35 cold-plug topology).
/// Contrast with `roots`, which are pxb-pcie complexes for GPU passthrough.
pub cold_plug_ports: Vec<PciRootPort>,
}
pub(crate) struct PciRootComplex {
@@ -20,18 +23,35 @@ pub(crate) struct PciRootComplex {
pub(crate) struct PciRootPort {
pub id: String,
pub chassis: u8,
/// `slot=N` — required for Q35 root ports; absent on aarch64 Grace ports.
pub slot: Option<u8>,
/// `multifunction=on/off` — required for Q35; absent on Grace.
pub multifunction: Option<bool>,
/// `io-reserve=N` — required for aarch64 Grace ports; absent on Q35.
pub io_reserve: Option<u32>,
pub device: Option<VfioDevice>,
}
pub(crate) struct VfioDevice {
pub id: String,
pub host: String,
pub rombar: bool,
pub rombar: Option<bool>,
pub kind: VfioDeviceKind,
/// When set, an `-object iommufd,id=<iommufd_id>` is emitted immediately before
/// this device and referenced in the device string. Used for CoCo x86 passthrough;
/// Grace uses a single shared `iommufd0` in `Objects::iommufd` instead.
pub iommufd_id: Option<String>,
/// `x-pci-vendor-id` override required for CoCo measured-boot attestation (#12329).
pub pci_vendor_id: Option<u16>,
/// `x-pci-device-id` override required for CoCo measured-boot attestation (#12329).
pub pci_device_id: Option<u16>,
}
pub(crate) enum VfioDeviceKind {
/// `vfio-pci-nohotplug` — aarch64 Grace static binding.
Gpu,
/// `vfio-pci` — x86 Q35 / CoCo passthrough and NIC.
GpuPci,
Nic,
}