[PATCH v16 29/45] KVM: arm64: CCA: Support runtime faulting of memory

Catalin Marinas catalin.marinas at arm.com
Tue Aug 11 08:42:28 PDT 2026


On Mon, Aug 03, 2026 at 02:43:45PM +0100, Steven Price wrote:
> At runtime if the realm guest accesses memory which hasn't yet been
> mapped then KVM needs to either populate the region or fault the guest.
> 
> For memory in the lower (protected) region of IPA a fresh page is
> provided to the RMM which will zero the contents. For memory in the
> upper (shared) region of IPA, the memory from the memslot is mapped
> into the realm VM non secure.

Is this still true with in-place guestmem conversion?

> @@ -1693,7 +1709,14 @@ static int gmem_abort(const struct kvm_s2_fault_desc *s2fd)
>  	kvm_fault_lock(kvm);
>  	if (mmu_invalidate_retry(kvm, mmu_seq)) {
>  		ret = -EAGAIN;
> -		goto out_unlock;
> +		goto out_release_page;
> +	}
> +
> +	if (kvm_is_realm(kvm)) {
> +		prot &= ~KVM_PGTABLE_PROT_X;
> +		ret = realm_map_ipa(kvm, s2fd->fault_ipa, pfn,
> +				    PAGE_SIZE, prot, memcache);
> +		goto out_release_page;
>  	}

[...]

> +int realm_map_ipa(struct kvm *kvm, phys_addr_t ipa,
> +		  kvm_pfn_t pfn, unsigned long map_size,
> +		  enum kvm_pgtable_prot prot,
> +		  struct kvm_mmu_memory_cache *memcache)
> +{
> +	struct realm *realm = &kvm->arch.realm;
> +
> +	ipa = ALIGN_DOWN(ipa, map_size);
> +	if (!kvm_realm_is_private_address(realm, ipa)) {
> +		return realm_map_non_secure(kvm, ipa, pfn, map_size, prot,
> +					    memcache);
> +	}
> +
> +	/* It's impossible to map protected pages read-only. */
> +	if (WARN_ON(!(prot & KVM_PGTABLE_PROT_W)))
> +		return -EFAULT;
> +	return realm_map_protected(kvm, ipa, pfn, map_size, memcache);
> +}

I was trying to understand (with the help of some LLMs) to understand
whether we can end up on the do_gpf() path as a result of VMM actions.
The above kvm_realm_is_private_address() only checks for the IPA but
does not check against guestmem if the page is truly private. I probably
miss something but the scenario would be something like:

1. VMM creates the gmem region with GUEST_MEMFD_FLAG_MMAP |
   GUEST_MEMFD_FLAG_INIT_SHARED, mmap()able and GUP-pinnable

2. VMM starts an O_DIRECT write() from that mapping; the block layer
   FOLL_PINs the shared folio

3. VMM runs a vCPU so the realm touches the protected-IPA alias of the
   same gfn. gmem_abort() delegates the pinned, still-shared page to
   the RMM

4. The in-flight I/O then reads the now-Realm page from the kernel
   linear map. That access takes a GPF at EL1, so do_gpf() ->
   die_kernel_fault()

x86, IIUC, also checks kvm_gmem_is_private(). They also have
kvm_arch_gmem_make_private() triggered on the kvm_gmem_get_pfn() path
but I got lost in the call sites, not sure whether that's strictly
needed if we check both private IPA and kvm_gmem_is_private().

-- 
Catalin



More information about the linux-arm-kernel mailing list