openvmm, virt_kvm: support cca isolated partitions based on the v15 KVM patch series - #4293
openvmm, virt_kvm: support cca isolated partitions based on the v15 KVM patch series#4293Chris Oo (chris-oo) wants to merge 6 commits into
Conversation
|
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.
Pull request overview
This PR adds initial support for booting Arm CCA (Realm) isolated guests on the KVM backend, including guestmemfd-backed private memory handling, device/DT address aliasing via the “shared IPA bit”, and user-facing CLI/config validation to constrain unsupported configurations.
Changes:
- Add CCA-aware KVM partition creation and VP run-loop handling (RMI populate for initial private pages; RIPAS change handling; shared-IPA address normalization for MMIO).
- Extend the memory subsystem to model guestmemfd “private state” across x86_64 (VM attributes) and aarch64 (guestmemfd-default / CCA).
- Wire the shared-IPA alias bit through platform info → loader (DT) → device guest memory aliasing, plus CLI/docs updates and validation tests.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| vmm_core/virt/src/generic.rs | Adds shared_gpa_bit to PlatformInfo so backends can report shared-IPA aliasing. |
| vmm_core/virt_whp/src/lib.rs | Populates shared_gpa_bit: None for WHP backend. |
| vmm_core/virt_mshv/src/aarch64/mod.rs | Populates shared_gpa_bit: None for MSHV aarch64 backend. |
| vmm_core/virt_kvm/src/memory.rs | Generalizes guestmemfd private-state handling and adds CCA RIPAS-change cleanup logic. |
| vmm_core/virt_kvm/src/lib.rs | Adds CCA error types/state, plus CCA-fatal handling and run-error mapping for memory faults. |
| vmm_core/virt_kvm/src/cca.rs | Implements initial Realm page population using KVM_ARM_RMI_POPULATE and error mapping. |
| vmm_core/virt_kvm/src/arch/x86_64/mod.rs | Updates SNP guestmemfd setup to use the new private-state enum. |
| vmm_core/virt_kvm/src/arch/aarch64/mod.rs | Adds CCA partition bring-up, Realm VM creation, IPA-size probing, MMIO shared-bit stripping, and RIPAS-change handling. |
| vmm_core/virt_hvf/src/lib.rs | Populates shared_gpa_bit: None for HVF backend. |
| vm/kvm/src/lib.rs | Adds/updates KVM capability constants and a helper to probe maximum Realm IPA size. |
| openvmm/openvmm_entry/src/lib.rs | Adds CLI/config validation for CCA isolation constraints. |
| openvmm/openvmm_entry/src/cli_args.rs | Adds --isolation cca (aarch64) and option validation + tests (hugetlb/private/vhost-user). |
| openvmm/openvmm_core/src/worker/vm_loaders/linux.rs | Threads shared-IPA bit into DT generation (addresses, PSCI method) for CCA guests. |
| openvmm/openvmm_core/src/worker/dispatch.rs | Adds runtime validation for CCA configs and creates an aliased device GuestMemory for shared-IPA DMA. |
| openvmm/membacking/src/memory_manager/mod.rs | Adds GuestMemoryClient::aliased_guest_memory + tests for shared-IPA aliasing. |
| Guide/src/reference/openvmm/management/cli.md | Documents --isolation cca and its current constraints. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| let private = flags & kvm::KVM_MEMORY_EXIT_FLAG_PRIVATE_UAPI != 0; | ||
| let range = MemoryRange::new(gpa..end); | ||
| let state = self.memory.lock(); | ||
| let segments = guest_memfd_range_intersections(range, &state.ranges) | ||
| .map_err(map_cca_conversion_error)?; | ||
|
|
Create Arm CCA realm VMs with the KVM v15 ABI, probe a supported Realm IPA size, populate initial private pages through RMI, and distinguish CCA guestmemfd-default private state from SNP VM memory attributes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5e377cd5-d7c7-4114-8408-e67a5dec5c2b
5c102ca to
b41aa09
Compare
| assert!(matches!( | ||
| guest_memfd_range_intersections(range(0x1000, 0x4000), &slots), | ||
| Err(KvmError::InvalidMapGpaRange) | ||
| )); |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.
Suppressed comments (2)
vmm_core/virt_kvm/src/memory.rs:1041
- This pattern uses the wrong error type:
guest_memfd_range_intersectionsreturnsMemoryError, andKvmErrorhas noInvalidMapGpaRangevariant (and is not imported in x86 test builds). As written, the test target does not compile.
Err(KvmError::InvalidMapGpaRange)
vmm_core/virt_kvm/src/cca.rs:87
KVM_ARM_RMI_POPULATErequires page-aligned base and size, but arbitraryInitialPageImportranges reach the ioctl without validation, so the newly addedUnalignedCcaPopulateRangeerror is never used and callers instead get an opaque ioctl failure. Validate both the range start and length before resolving the slot.
for page in &pages {
let flags = cca_populate_flags(page.import_type)?;
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.
Suppressed comments (2)
openvmm/openvmm_core/src/worker/dispatch.rs:3527
- This binding is never read—the ACPI closure still accesses
self.hypervisor_cfg.with_hvdirectly. Remove it to avoid the unused-variable warning (and the corresponding clippy failure when warnings are denied).
let with_hv = self.hypervisor_cfg.with_hv;
vmm_core/virt_kvm/src/cca.rs:127
- The new CCA import mapping has no automated coverage, even though the analogous SNP import-type mapping is tested in
vmm_core/virt_kvm/src/arch/x86_64/snp.rs:37-69. Add cases proving that normal pages are measured, unmeasured pages use zero flags, and every unsupported import type is rejected; otherwise a flag/match regression can silently change Realm measurements or prevent direct boot.
fn cca_populate_flags(import_type: InitialPageImportType) -> Result<u32, KvmError> {
match import_type {
InitialPageImportType::Normal => Ok(kvm::KVM_ARM_RMI_POPULATE_FLAGS_MEASURE_UAPI),
InitialPageImportType::NormalUnmeasured => Ok(0),
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
vmm_core/virt_kvm/src/cca.rs:91
- This rejects any valid import that spans two KVM slots because
private_memory_range_from_slotsrequires one containing slot, despite the following call explicitly resolving a fully covered multi-slot range. This can occur with supported NUMA layouts: adjacent nodes are separate RAM backings/slots, while the loader merges adjacent imports with identical metadata. Populate each returned segment separately using its own GPA, HVA, and guestmemfd extent, then discard the complete segment list.
let private_range = private_memory_range_from_slots(page.range, &memory.ranges)
.map_err(map_cca_private_range_error)?;
let segments = crate::memory::guest_memfd_range_segments(page.range, &memory.ranges)
.map_err(map_cca_private_range_error)?;
vmm_core/virt_kvm/src/cca.rs:87
InitialPageImportdoes not require a nonempty, page-aligned range, but this path never validates either condition even thoughUnalignedCcaPopulateRangewas added for that purpose. In particular, a zero-length import skips the ioctl and is reported as successfully populated, while an unaligned import leaks a generic ioctl error. Reject empty or non-page-aligned ranges before processing them.
for page in &pages {
let flags = cca_populate_flags(page.import_type)?;
Use the KVM-reported CCA shared GPA bit to build aliased device memory views and advertise shared MMIO addresses to the guest device tree. Mask shared MMIO addresses in KVM before dispatching to device emulation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reject unsupported CCA firmware, Hyper-V, memory layout, backing, and device configurations before constructing the VM. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5e377cd5-d7c7-4114-8408-e67a5dec5c2b
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 602e3e75-e995-466b-8bb1-bf0d094e86e9
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 602e3e75-e995-466b-8bb1-bf0d094e86e9
f827879 to
592d1ce
Compare
| let private_range = private_memory_range_from_slots(page.range, &memory.ranges) | ||
| .map_err(map_cca_private_range_error)?; | ||
| let segments = crate::memory::guest_memfd_range_segments(page.range, &memory.ranges) | ||
| .map_err(map_cca_private_range_error)?; |
| CCA support requires device-tree Linux direct boot with shared userspace RAM | ||
| backing. It does not support Hyper-V enlightenments, VTL2, VMBus, hugetlb | ||
| memory, assigned devices, vhost-user devices, PCIe hotplug, or CXL. |
| match config.isolation { | ||
| virt::IsolationType::None => {} | ||
| virt::IsolationType::Cca => { | ||
| if config.hv_config.is_some() { |
Add support for booting a Linux direct CCA guest using KVM with the v15 cca patch series currently in review on LKML. Note that we do not yet support inplace guest_memfd, but it seems like the patch series works just fine without it. This should support a guest with emulated serial, along with virtio devices exposed over PCIe, similar to the SNP support in KVM and mshv.
Tested via private additional local changes that test VM boot in FVP and QEMU with new incubator definitions and vmm_tests. Support for those will come in future changes, once they're cleaned up and ready for review.