Skip to content

Conversation

jpbrucker
Copy link

These patches add support for ArmVirtQemu to be run in a Realm guest. A lot of it is just plumbing to use the Arm CCA libraries, for example to create DMA mappings in the shared IPA region. We also need to create a mapping to access the shared UART early, enabled emulated variable storage, and measure blobs loaded via fw_cfg.

Long term it would be good to create a single EDK2 platform for Realms rather than one per VMM, for a number of reasons:

  • Confidential computing requires extra support in the firmware, as highlighted by this series. Although I'm working on cloud-hypervisor support for CCA I haven't yet had time to do ArmVirtCloudHv.
  • For attestation the firmware must be measured. Verifiers would be provisioned with a single firmware image rather than one for each platform.
  • An image with a minimal set of features (for example no networking) would considerably reduce the attack surface of the TCB.
  • For attestation the firmware tables, ACPI and DTB, must be measured. To simplify the provisioning required for this, it would be nice to only provision DTBs and have the FW generate ACPI tables like ArmVirtKvmtool does. The number of variations for firmware tables is likely to be quite high.
  • We would have the opportunity to implement a common mechanism for direct kernel boot.

Although I started working on this, it's unlikely I will have time to complete anytime soon. Adding CCA support to ArmVirtQemu is easier for now.

jpbrucker added 14 commits July 1, 2025 13:57
Move the device tree parsing routine into the library constructor, so
that the flash device configuration is available to all drivers that
include this library. The QEMU platform initialization driver will need
to instantiate variable storage emulation depending on the availability
of flash devices.

Move the device tree modification to VirtNorFlashPlatformInitialization(),
because it should only be done once.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
QEMU does not include a flash device when spawning a confidential VM on
Arm, because it cannot do read-only mappings. Support VMs without NOR
flash, by falling back to the emulated variable store.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
Add QemuPlatformDxe which installs the Variable store emulation when a
Flash device is not available.

Link NorFlashQemuLib as a NULL library so that it can setup
PcdEmuVariableNvModeEnable.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
When code in .text uses adrp to obtain an address from .data, if the
sections don't have the same alignment modulo 4KB, GenFw fails with:

  WriteSections64(): Build/ArmVirtQemu-AARCH64/RELEASE_GCC5/AARCH64/ArmPlatformPkg/Sec/Sec/DEBUG/Sec.dll AARCH64 small code model requires identical ELF and PE/COFF section offsets modulo 4 KB.

Since we will need to move ID-map to .data and introduce a writable
buffer for CCA, define the section alignment to 4kB.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
As we're about to introduce more identity mappings into IdMap.S,
introduce a macro that create identity PTEs, to make the page table code
more readable.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
…ART idmap

In a realm, we'll need to patch the early page tables to access the
emulated uart through the unprotected IPA range. Add a third level table
for the VA range which contains the UART.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
A Realm needs to access emulated devices via the unprotected IPA range
(upper IPA bit set). After probing the RMM using some RSI calls, update
the page table entry that maps the UART.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
Pull in the Arm CCA libraries needed for discovering the address space
width and sharing DMA memory with the VMM.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
When creating the identity mapping, copy the 'unprotected' top bit from
the physical address as an attribute in the PTE. The virtual address
then points to the top half of the address space, which in a Realm is
the unprotected half, shared with the host.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
…r CCA

A Realm guest needs to access peripherals emulated with the host with
the 'unprotected' bit set (most significant bit of the Intermediate
Physical Address). Initialize the page tables with all device mappings.
We mainly need the serial device to be immediately accessible for
debugging purposes, but we may as well setup the whole device regions.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
To ensure I/O buffers are shared with the host, add those libs

Signed-off-by: Jean-Philippe Brucker <[email protected]>
Add a small module that calls ArmCcaInitPeiLib function to initialize
the Realm address space.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
Before MMU initialization, call the ArmCcaInitPei function to detect
whether we're in a Realm, and provide the IPA width which is needed to
setup device mappings.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
…tributes

An 'unprotected' bit set by ArmCcaConfigureMmio() may get cleared later
by ArmSetMemoryAttributes(). For example the PCIe ECAM region on QEMU is
mapped late by MapGcdMmioSpace(). Ensure the 'unprotected' bit does not
get cleared.

Note that we should probably consolidate this: ArmCcaConfigureMmio()
initializes those page table entries as valid even though they don't
have the correct memory attributes yet.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
The ArmCcaIoMmuDxe driver depends on gEfiRealmApertureManagementProtocolGuid,
and produces either gEdkiiIoMmuProtocolGuid or gIoMmuAbsentProtocolGuid.
Other drivers, for example those including QemuFwCfgLibMmio, thus depend
on either the IOMMU or IOMMU Absent protocol.

Since ArmCcaIoMmuDxe only produces gEfiRealmApertureManagementProtocolGuid
when in a Realm at the moment, those drivers cannot be loaded when not
in a Realm, and boot doesn't reach BDS. Add an empty instance of
gEfiRealmApertureManagementProtocolGuid so that ArmCcaIoMmuDxe always
produces something and unblocks other drivers.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
Signed-off-by: Dhanus M Lal <[email protected]>
Add a NULL library for non-x86 platforms that need the IoMmuDxe driver
without SEV and TDX.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
As the ArmVirtQemu platforms are getting support for confidential
computing, they needs to start supporting IOMMU protocols that share and
unshare DMA buffers with the host. This means we'll need to ensure
that the driver that provides the IOMMU protocol and client drivers
that perform DMA are loaded in the right order. For instance QemuFwCfgLibMmio
needs new Depex entries so that drivers including this library are
loaded after either gEdkiiIoMmuProtocolGuid or gIoMmuAbsentProtocolGuid
get produced.

Since RiscVVirtQemu uses QemuFwCfgLibMmio, it now needs something that
produces gIoMmuAbsentProtocolGuid. Include IoMmuDxe for this purpose.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
---
Only build-tested
When running in a realm, we must explicitly share DMA buffers with the
host. Use the IoMmuProtocol when available.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
The ArmVirtQemu guest firmware loads the kernel and initrd images from
the host through the FwCfg device. When running in a realm, measure
those images and add them to the realm measurement, so that the realm
owner can later authenticate them.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
Use the Arm CCA BlobVerifier to add hashes of FwCfg images to the realm
measurement.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
When run early in the QEMU boot, writing the static variable
FlagsInitialised causes a Synchronous Exception. Supposedly the data
page containing the static variable isn't mapped writable at this point,
but I didn't investigate further. Use a GUID HOB to cache the variable.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
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.

1 participant