NVIDIA: add Arm CCA Realm and RME device-assignment support - #40
NVIDIA: add Arm CCA Realm and RME device-assignment support#40ianm-nv wants to merge 40 commits into
Conversation
This is a temporary patch intended for testing purposes only. It provides definitions related to supporting Realms by the QEMU-VMM. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (backported from commit 46fba3f60f1d5e5ddea835bd5cfb6dced1ddcf47 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
…h_init() Returning an error to kvm_init() is fatal anyway, no need to continue the initialization. Leave the `ret` variable in the function scope because it will be reused when adding RME support. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit c9e0538a3e56bddc6ccbef2595a90c0f01948359 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
Add a new RmeGuest object, inheriting from ConfidentialGuestSupport, to support the Arm Realm Management Extension (RME). It is instantiated by passing on the command-line: -M virt,confidential-guest-support=<id> -object rme-guest,id=<id> This is only the skeleton. Support will be added in following patches. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (backported from commit 84460f046c56f50595e59870ae590d2dc7523e3d https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) [ianm: omitted the ConfidentialGuestSupportProperties QAPI base, which is not available in QEMU 11.0] Signed-off-by: Ian May <ianm@nvidia.com>
Initialise an @rme_guest object and install a handler to get notified when the Realm is ready to start. That way we can finish reading the Realm once we know everything is in place. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (backported from commit 1d293ef90047ad3c5de4784b90537f5f7d701851 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) [ianm: omitted allow_convert_in_place, which is not available in QEMU 11.0] Signed-off-by: Ian May <ianm@nvidia.com>
For a Realm, KVM is much more restrictive on the registers a VMM can initialize. To prepare for Realm VM initialization, split the get/put register functions for a non-secure VM in their own function. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 065b0e57d6a574b852edd7564b5cfdc1b46d606c https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
The target code calls kvm_arm_vcpu_init() to mark the vCPU as part of a Realm. For a Realm vCPU, only x0-x7 can be set at runtime. Before boot, the PC can also be set, and is ignored at runtime. KVM also accepts a few system register changes during initial configuration, as returned by KVM_GET_REG_LIST. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 7b99148ebe2fc60711b059c99e1ca02fa4b587fa https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
When a Realm is requested, create a scratch Realm VM by setting bit 8 of the argument given to the KVM_CREATE_VM ioctl(). Bit 7-0 are reserved for the guest PA size. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 2ce3ab9f6a3bfbac2fca359cbc224fb788d5b25e https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
…essary The Arm KVM code can return different values from KVM_CHECK_EXTENSION depending on the VM type. Use kvm_vm_check_extension() where necessary to ensure we get the right response from KVM. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 0edc61af82210beacbf7ff22ee1c80e27b40d7ec https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
Add a function to register a notifier that is invoked when ROMs get loaded into guest memory. It will be used by Arm confidential guest support, in order to register all blobs loaded into memory with KVM, so that their content is moved into Realm state and measured into the initial VM state. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 5a1c5c57b07cf9501fa548c78454214bb68221da https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
…lm memory Add a Rom notifier to keep track of binary blobs loaded in Realm memory. That way we can deterministically calculate the Realm Initial Measurement (RIM). Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 0288a9c77fcb2db3c5ecab25558d63edd1f5657b https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
Once the Realm descriptor has been created, tell KVM to transfer runtime images (kernel, DT, and rootfs) from guest memory to Realm memory. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 12afb2f135c59600cb84dc14c4375ea1204acb2b https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
…nts in KVM Add "num-breakpoints" and "num-watchpoints" CPU parameters to configure the debug features that KVM presents to the guest. The KVM vCPU configuration is modified by calling SET_ONE_REG on the ID register. This is needed for Realm VMs, whose parameters include breakpoints and watchpoints, and influence the Realm Initial Measurement. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 6fd014297760be023d8a7060ecab8d0e51c51a2c https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
Add a "num-pmu-counters" CPU parameter to configure the number of counters that KVM presents to the guest. This is needed for Realm VMs, whose parameters include the number of PMU counters and influence the Realm Initial Measurement. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit cfc3a5faad3c75f71d9b6ed4b489c31400ccf18a https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
The host cannot access registers of a Realm. Instead of showing all registers as zero in "info registers", display a message about this restriction. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 7568b34e186c5fa9acf17a093143d630cb47ae73 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
The HVC conduit for PSCI is not supported for Realms, so default to SMC. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 1ff3e53b25a2fdde95a042b4f52ebff2b5cebbdd https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
Set the Ream VM bit in the IPA address space size when needed. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit beea72e5f3c30ac36cbe23e8ee758cd57bf4a5b4 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
… for RME When RME is enabled, the upper GPA bit is used to distinguish protected from unprotected addresses. Reserve it when setting up the guest memory map. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 06b813b51fcbfdcdc5cea8938d3162ced0503238 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
The dtb-randomness feature, which adds random seeds to the DTB, isn't really compatible with confidential VMs since it randomizes the Realm Initial Measurement. Enabling it is not an error, but it prevents attestation. It also isn't useful to a Realm, which doesn't trust host input. Currently the feature is automatically enabled, unless the user disables it on the command-line. Change it to OnOffAuto, and automatically disable it for confidential VMs, unless the user explicitly enables it. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit efde425360513e48627474e34942961d60d0407a https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
For confidential VMs we'll want to skip flash device creation. Unfortunately, in virt_instance_init() the machine->cgs member has not yet been initialized, so we cannot check whether confidential guest is enabled. Move virt_flash_create() to machvirt_init(), where we can access the machine->cgs member. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 2da577b703c893c2017b7594946a334cfbf0fa88 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
… guest firmware Use RAM instead of flash to store firmware image and boot information, including UEFI variables. That way the firmware can be measured and included in the Realm's initial measurements. It also prevents variable stored in flash and modified as part of the boot process to be leaked outside the Realm. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 07c798336af663bff4672e187a0e17e9ba101398 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
…emory region In Arm CCA, the guest-physical address space is split in half. The top half represents memory shared between guest and host, and the bottom half is private to the guest. From QEMU's point of view, the two halves are merged into a single region, and pages within this region are either shared or private. Virtual devices implemented by the host are only allowed to access the top half. For emulated MMIO, KVM strips the GPA before returning to QEMU, so the GPA already belongs to QEMU's merged view of guest memory. However DMA addresses cannot be stripped this way and need special handling by the VMM. When emulating DMA the VMM needs to translate the addresses into its merged view. Add an IOMMU memory region on the top half, that retargets DMA accesses to the merged sysmem. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit cb1e21fdd28b25fda8ead6503ece8289e43fb524 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
Some distributions provide packages continaing firmware to be run under QEMU, such as "qemu-efi-aarch64" or "edk2-aarch64". Those packages also contain descriptors in /usr/share/qemu/firmware/*.json listing the firmware features, so that environments like libvirt can figure out which firmware they can load. Define an optional feature for arm64 firmware to indicate that a firmware supports running in a Realm. Firmware implementations need extra support for running in a Realm, in particular to distinguish shared from private guest memory. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Acked-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 627a544c5f7f85d4b5effdcebc09bd96e434fdb6 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
Load DTB without modifications when provided. That way it is possible for a verification entity to reconstruct the Realm's initial measurement. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit 2bb4ca207d08ad80aaac8bc0c4cbe1e1b845b4d9 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
An independent verifier needs to reconstruct the content of guest memory in order to attest that it is running trusted code. To avoid having to reconstruct the bootloader generated by QEMU, skip this step and jump directly to the kernel, with the DTB address in x0 as specified by the Linux boot protocol [1]. [1] https://docs.kernel.org/arch/arm64/booting.html Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> (cherry picked from commit d69e5bf476210877995f17f7d83a095d206234f0 https://gitlab.com/Linaro/cca-public/qemu/-/tree/upstream-v4) Signed-off-by: Ian May <ianm@nvidia.com>
Add a convenience function that pairs with kvm_mark_guest_state_protected(). Signed-off-by: James O. D. Hunt <jameshunt@nvidia.com> Signed-off-by: Ian May <ianm@nvidia.com>
Track successful Realm population and activation so later VM state changes do not re-enter the one-time setup path. Once KVM guest state is protected, also skip the normal Arm virtual-time synchronization that Realm KVM does not support. This preserves QMP stop/cont operation for Realm guests. Signed-off-by: James O. D. Hunt <jameshunt@nvidia.com> Signed-off-by: Ian May <ianm@nvidia.com>
The RFC series defines KVM_VM_TYPE_ARM_REALM as a standalone flag bit (1UL << 30). Our kernel instead carves a 4-bit VM-type field out of bits[11:8] and defines REALM as KVM_VM_TYPE_ARM(1) == 0x100. With the upstream encoding, KVM_CREATE_VM passes bit 30, which our kernel reads as VM type 0 (normal) with a stray reserved bit, so the realm is silently created as a normal VM and every subsequent RMI call fails. Realign the header with include/uapi/linux/kvm.h. Preserve the kernel's KVM_VM_TYPE_ARM_MASK name for the VM-type field; the IPA-size and protected VM fields remain separate. Only REALM and NORMAL are referenced by QEMU, so no code change is needed. Signed-off-by: Ian May <ianm@nvidia.com>
Bring the RFC KVM setup in line with deployed Realm kernels and QEMU reset behavior. Discover the live KVM_ARM_RMI capability when the NVIDIA kernel exports it, validate the module parameter, and report fallback to the compile-time value. Preserve the Arm VM type field and use VM-scoped capability probes. Add targeted diagnostics when KVM rejects main or scratch Realm VM creation with an IPA size that may exceed the RMM S2SZ limit. Avoid normal-VM register synchronization that Realms do not support. Configure the measured PMU counter count through the PMU device attribute, including zero counters, and skip virtual-time adjustment after activation. Initialize the PMU override for every CPU model and apply debug and PMU overrides only on the first vCPU reset because KVM rejects them after the VM has run or the PMU has been created. Reject later property writes rather than reporting a value that the one-shot KVM configuration cannot apply. Signed-off-by: Ian May <ianm@nvidia.com>
Make confidential boot use the resolved firmware filename and fail cleanly when the requested image is missing. Bound DTB copies to their allocated loader region so an oversized tree cannot overwrite adjacent guest memory. Keep the dtb-randomness QOM property compatible with ordinary virt machines while suppressing effective randomness for confidential guests, whose DTB is part of the measured initial state. Signed-off-by: Ian May <ianm@nvidia.com>
Use the selected confidential-guest object when deriving the Realm VM type. Define the VM-type values in QEMU's Arm KVM interface so the machine model does not depend on a host Linux header when built for TCG or HVF. Verify the local Realm value against the imported KVM UAPI in KVM-specific code so any encoding drift fails the build. Preserve requested dtb-randomness independently of its effective measured-boot behavior. Create pflash devices early enough to retain the pflash0 and pflash1 machine properties, but leave them unmapped for Realms. Reject non-KVM launches and pflash-backed Realm firmware before guest initialization. Cover the pflash property ABI with qtests. Signed-off-by: Ian May <ianm@nvidia.com>
Bind Realm state to the confidential-guest object selected by the machine. Remove its notifiers when the object is finalized. Install the Realm DMA address space before PCI and platform devices obtain DMA views, and route virtio-mmio through it. Mirror guestmemfd shared-page transitions into the Realm IOMMU so DMA is exposed only for shared memory. Accept both the shared-bit spelling and the canonical firmware spelling for pages already shared with the RMM. Signed-off-by: Ian May <ianm@nvidia.com>
memory_region_find() truncates a section at a MemoryRegion boundary. Continuing with the original size can update KVM attributes across the full range and then fail to update the first RAMBlock attribute bitmap, leaving the two views inconsistent. Reject requests that do not resolve to one complete section before changing any KVM state. This is a generic guestmemfd conversion check and applies equally to RME, TDX, and SEV-SNP. Signed-off-by: Ian May <ianm@nvidia.com>
RFC v3 keeps pointers supplied by the ROM loader until Realm activation. ROM-only data is freed before the notification, and even persistent data has no lifetime guarantee across that interval. Snapshot each complete image while the notification data is valid. Include zero-filled tails, align and merge page-overlapping images, and place byte-granular contents at the correct offset in page-aligned buffers. Replace an earlier snapshot when a reset reports the same image again before activation. Avoid constructing the zero-filled notification copy when no listener is present. Stop accepting loader notifications after activation and unregister the notifier at that boundary. Convert populated ranges through kvm_convert_memory() so KVM attributes, QEMU's RamDiscardManager bitmap, DMA notifications, and the discarded shared mapping remain synchronized. The population source is the private snapshot, so discarding the guest's shared alias cannot destroy the input data. Validate range arithmetic and buffer alignment, detect KVM ioctls that make no progress, and terminate before vCPUs run if population fails. Signed-off-by: Ian May <ianm@nvidia.com>
Libvirt detects the rme-guest object and then uses query-cca-capabilities to determine whether host KVM supports Realms. Without that command, libvirt clears its CCA capability and rejects an otherwise usable QEMU binary. Implement query-cca-capabilities using the same runtime KVM_CAP_ARM_RMI lookup and VM-scoped capability probe as Realm creation. The response schema matches NVIDIA libvirt commit 00fe79fd234291db242a4c72c2d3373f8f3dcdb2 on nvidia_unstable-11.9. That code consumes return.sections[].measurement-algo. Signed-off-by: Ian May <ianm@nvidia.com>
Import the kernel definitions required for Arm RME device assignment
(RME-DA):
- linux/iommufd.h: VIOMMU/VDEVICE allocation and VDEVICE TSM
operations.
- linux/kvm.h: KVM_EXIT_ARM64_TIO and its kvm_run CCA payload.
- asm-arm64/kvm.h: the RMI_EXIT_VDEV_MAP TIO reason.
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Signed-off-by: Ian May <ianm@nvidia.com>
kvm_convert_memory() can run from multiple vCPU threads without the BQL. Concurrent conversions can race while updating the RamBlockAttributes bitmap, and listener registration or replay can observe an inconsistent transition. Add a mutex covering bitmap access, the listener list, notifications, and replay callbacks. Keeping callbacks inside the critical section orders their side effects with the state they report. This is common guestmemfd synchronization. Listener callbacks, including VFIO DMA map and unmap ioctls, run while the mutex is held; conversions are deliberately serialized to preserve ordering. Signed-off-by: Ian May <ianm@nvidia.com>
A Realm marks device MMIO ranges private when a device is bound to it and shared again when the mapping is released. Honour those requests on the KVM memory-attribute path. Allow RME to convert ram_device regions such as VFIO BARs to shared, clearing PRIVATE so the kernel tears down stale assigned-device stage-2 mappings. Clear VDEV-installed PRIVATE attributes when a device memory slot is removed, and fail closed when that rollback cannot be completed. Advertise assigned-device memory through ConfidentialGuestSupport so the RME-specific paths can be selected. Add the corresponding non-KVM stubs. Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Signed-off-by: Ian May <ianm@nvidia.com>
Add the IOMMUFD plumbing for assigning a VFIO PCI device to an Arm CCA Realm. Keep the RHI function IDs, status values, and request structures consumed by QEMU in include/hw/arm/rme-da.h. These definitions are not generated Linux UAPI and would otherwise be lost when linux-headers is refreshed. Assert the request structure sizes so ABI layout changes fail the build. Build a stage-2 nesting-parent HWPT, VIOMMU, and stage-1 bypass HWPT without changing the legacy single-HWPT path. Keep Realm devices out of ordinary reusable HWPTs and fully unwind failed topology construction. Retry interrupted detach operations and terminate if an attached parent HWPT cannot be detached safely during rollback. Register an opted-in PCI device with an IOMMUFD VDEVICE after its virtual bus number is assigned. Validate the backend, device type, parent HWPT, VIOMMU, nested HWPT, and machine device-assignment support. Track the RID used for registration and reject accesses after bridge renumbering changes the device identity. Propagate synchronous failures and stop the VM on deferred failures. Track run state, clear the failure latch when the VM stops, and retry registration on resume. Reject unsupported hotplug and compile the path only when IOMMUFD is linked. Implement bind, unbind, guest request, measurement, TDI state, and VDEV_MAP operations. Validate request residues and every page of device-memory ranges before changing KVM attributes, and require host-page alignment. If the host rejects a request after PRIVATE attributes are installed, stop the VM rather than guessing at the previous state. Provide stubs for builds without IOMMUFD. Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Signed-off-by: Ian May <ianm@nvidia.com>
Forward the RHI device-assignment hypercalls in the SMCCC Standard Hypervisor range to userspace through a KVM SMCCC filter. Dispatch object, interface-report, measurement, and TDI-state requests to the IOMMUFD TSM helpers, and handle KVM_EXIT_ARM64_TIO for VDEV_MAP validation. Treat the exit data as an untrusted guest interface. Validate routing IDs, object lengths and offsets, response residues, memory-map ranges, and complete guest buffer mappings. Initialize all request and response state, reject unknown exits, preserve KVM register errors, and serialize VFIO lookup and TSM operations with the BQL. Fetch cached objects at offset zero into bounded QEMU-owned buffers before copying the requested slice to Realm memory. This avoids exposing the target kernel's unchecked source-pointer offset to guest input. Reject out-of-range offsets with the corresponding RHI status. Allow CPU-only Realms when the KVM SMCCC filter is unavailable, but disable the assigned-device-memory capability. An opted-in VFIO device then fails during realize instead of starting with unusable RHI forwarding. Confine GP-register synchronization to forwarded hypercalls and release all guest mappings after use. Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Signed-off-by: Ian May <ianm@nvidia.com>
Use the maximum supported Realm IPA width so the shared bit remains stable when the PCI layout changes. Keep the Realm DMA AddressSpace alive while the machine uses it. Release it from the RmeGuest unparent hook to break its reference cycle through the root MemoryRegion owner. Reject deletion of an active Realm object and make partial-initialization cleanup idempotent. Serialize the RAM-discard listener cache so translations cannot race listener teardown. Emit replay MAP notifications from the protected RamBlockAttributes callback so bitmap changes and MAP or UNMAP notifications remain ordered. Document the required nesting between ram_discard_lock and the RamBlockAttributes lock. Limit notifier mappings to the shared-bit DMA alias. Accept canonical and shared-bit RAM addresses only while the RAM discard manager records the page as shared. For addresses outside tracked RAM, classify the target through address_space_memory: permit non-RAM MMIO such as GIC ITS MSI writes, while untracked RAM, including VFIO BARs, continues to fail closed. Track and remove the Realm migration blocker along with the ROM notifier, VM-state handler, memory listener, and DMA AddressSpace during teardown. Signed-off-by: Ian May <ianm@nvidia.com>
BaseOS Kernel ReviewNote 🔄 Review in progressBoro is reviewing this pull request. Results will appear here when ready. 🔍 Review artifacts
Review metadata
This comment is maintained by BaseOS Reviewer and updated when the GitHub watcher publishes a newer review. |
|
@ianm-nv I reviewed this PR and confirmed that the issues I had mentioned previously in my cursory review a few weeks ago are now resolved. There are some new findings and a few "informational notes" (findings, but classified a bit differently due to recognition that this is beta code). I'm not sure how actionable these are at this point in time as none of them appear to functionally affect the "good path". Will let you review and then we can discuss how best to proceed. Findings1. [P1] Realm DMA conversion can succeed after a VFIO map/unmap failureWhen a Realm page changes between private and shared, target/arm/kvm-rme.c:560 publishes an IOMMU MAP or UNMAP event. Through the registered notifier chain, this reaches hw/vfio/listener.c:156, which performs the actual VFIO/IOMMUFD mapping operation. If that operation fails, VFIO reports the error but cannot return it because the generic IOMMU notifier interface returns void. Control eventually returns to target/arm/kvm-rme.c:598, which unconditionally returns zero. As a result, For a private-to-shared transition, the CPU-visible page can become shared while the assigned device has no corresponding DMA mapping. For a shared-to-private transition, an old device mapping can remain after QEMU considers device access revoked. This breaks the invariant that KVM attributes, QEMU’s RAM-discard bitmap, and IOMMUFD mappings describe the same sharing state. Replay of existing shared pages uses the same notification mechanism, so a failed replay MAP can also be logged without preventing VFIO device setup from continuing. 2. [P2] Realm boot images cannot cross RAM MemoryRegion boundariesQEMU can construct contiguous guest RAM from multiple NUMA memory backends: Guest-visible RAM There is no address-space hole at this boundary, so a kernel, initrd, or ELF segment spanning it is still entirely within valid guest RAM. QEMU creates these adjacent backend regions in hw/core/numa.c:627, and Realm machine validation does not reject such a configuration. The Realm loader records and page-aligns complete boot-image ranges. It can also coalesce overlapping or adjacent loader entries without considering the underlying RAM backend boundaries: target/arm/kvm-rme.c:200 At VM activation, target/arm/kvm-rme.c:130 passes each complete range to kvm_convert_memory(). That function uses memory_region_find(), which returns only the portion contained in the first leaf MemoryRegion, and then explicitly rejects the range when the returned section is smaller than requested: accel/kvm/kvm-all.c:3393 The resulting error propagates to the Realm run-state handler, which terminates QEMU during startup. The failure depends on image placement: the same image and memory backends can work or fail depending on whether an image happens to straddle one of the otherwise transparent NUMA boundaries. 3. [P2] Large zero-filled ELF segments create two full-size staging buffersFor an ELF PT_LOAD segment, QEMU distinguishes: p_filesz: bytes physically present in the ELF file When p_memsz > p_filesz, the remainder is normally an implicit zero-filled BSS tail. rom_add_elf_program() deliberately retains only the file-backed portion and records the larger in-memory size, avoiding a separate p_memsz allocation: hw/core/loader.c:1211 The Realm loader notification path materializes that sparse representation into a contiguous buffer. hw/core/loader.c:1300 first allocates and zeroes p_memsz bytes, then copies the p_filesz data into it. While that temporary buffer remains For a segment with 16 MiB of file data and a 1 GiB in-memory size, the notifier path temporarily holds two additional 1 GiB buffers. This is in addition to guest RAM and the mapped ELF file. Under a process or cgroup memory limit, an This applies only to direct ELF loading with a substantial p_memsz - p_filesz difference. Raw Arm Linux Image files and ELF segments without a meaningful zero-filled tail do not experience the duplicate full-size allocation. Informational notes4. The beta implementation does not provide RHI_DA_VERSIONThe RHI-DA SMCCC filter starts at RHI_DA_FEATURES (0x4b), leaving RHI_DA_VERSION (0x4a) outside the range forwarded to QEMU: target/arm/kvm.c:610 The RHI dispatcher likewise handles FEATURES, OBJECT_SIZE, OBJECT_READ, and the VDEV operations, but has no VERSION case: target/arm/kvm.c:2139 Published DEN0148 beta1 describes RHI_DA_VERSION as the protocol-discovery operation. A guest following that sequence would receive SMCCC_RET_NOT_SUPPORTED and conclude that RHI-DA is unavailable. The RFC v4 Linux guest used with this beta stack does not follow that sequence. It calls RHI_DA_FEATURES directly, which is forwarded and handled successfully. Consequently, the missing version call does not create a current functional problem and is noted only as relevant to future ABI alignment. See the Arm DEN0148 RHI specification (https://documentation-service.arm.com/static/6980b4be9135fd4e42bbf2ed?token=). 5. RHI_DA_OBJECT_READ uses source-offset semanticsThe object-read handler maps the guest’s AArch64 argument registers as follows: x2 / call->in[2] = object type See target/arm/kvm.c:1987. QEMU interprets x5 as an offset into the source object: copy_len = MIN(max_len, object_size - offset); Under that interpretation, an offset of 128 means “skip the first 128 bytes of the object and place the remaining data at the beginning of the guest buffer.” Published DEN0148 beta1 describes the field as an offset within the destination buffer. Under that interpretation, the complete object would be copied to guest_ipa + offset. The NVIDIA kernel branch inspected implements the source-offset convention, and its current guest callers always set gprs[5] to zero. With a zero offset, the two interpretations produce exactly the same result. The difference is therefore latent and does not affect the currently inspected beta guest. |
Summary
This series adds Arm Confidential Compute Architecture (CCA) Realm support
to the NVIDIA QEMU 11.0 branch. It imports Linaro's QEMU CCA RFC v4, adapts
it to the QEMU 11.0 and NVIDIA kernel interfaces, adds Realm pause/resume,
and integrates Arm RME device assignment (RME-DA).
The NVIDIA follow-up commits validate Realm creation and image loading,
constrain shared-memory DMA, check RME-DA requests, and correct machine
configuration, object teardown, and DMA replay ordering. They also support
NVIDIA kernels whose live
KVM_CAP_ARM_RMInumber differs from the QEMUbuild-time headers.
The series adds the downstream
query-cca-capabilitiesQMP interface usedby NVIDIA libvirt to determine whether host KVM supports Realms.
Series layout
The branch contains 40 linear commits on top of
nvidia_unstable-11.0(45aa1ef85148):into their final implementations.
Provenance
The imported commits record their corresponding Linaro source hashes.
Commits requiring changes for QEMU 11.0 are identified as backports and
describe the relevant adaptation.
Main NVIDIA adaptations and fixes
KVM_CAP_ARM_RMIvalue through the NVIDIA KVM moduleparameter, validate it, cache it, and fall back to the build-time value
when the parameter is unavailable.
VM-scoped KVM capability checks.
valid, merge page-overlapping images, and bound Realm population to valid
RAM ranges.
aliases through the Realm DMA address space.
RME-DA.
validate lengths, offsets, mappings, residues, routing IDs, and
device-memory ranges; serialize device access; and fail closed on rollback
or registration errors.
them.
active RME object, and break the RmeGuest/AddressSpace reference cycle.
callbacks so DMA mappings cannot become stale during a concurrent memory
conversion.
query-cca-capabilitiesusing the response schema consumed byNVIDIA libvirt commit
00fe79fd234291db242a4c72c2d3373f8f3dcdb2on
nvidia_unstable-11.9.