From: Marc Zyngier <maz@kernel.org>
To: Ryan Roberts <ryan.roberts@arm.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Arnd Bergmann <arnd@arndb.de>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Oliver Upton <oupton@kernel.org>,
Alex Williamson <alex@shazbot.org>,
Jason Gunthorpe <jgg@nvidia.com>, Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Jean-Philippe Brucker <jpb@kernel.org>,
Oded Gabbay <ogabbay@kernel.org>,
Jonathan Corbet <corbet@lwn.net>,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
kvm@vger.kernel.org, devicetree@vger.kernel.org,
dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org
Subject: Re: [RFC PATCH v2 11/15] KVM: arm64: Export stage-2 MMU config
Date: Thu, 22 Oct 2026 16:43:27 +0100 [thread overview]
Message-ID: <86h5idzqow.wl-maz@kernel.org> (raw)
In-Reply-To: <20261015142552.4128028-12-ryan.roberts@arm.com>
On Thu, 15 Oct 2026 15:25:45 +0100,
Ryan Roberts <ryan.roberts@arm.com> wrote:
>
> From: Jean-Philippe Brucker <jpb@kernel.org>
>
> Provide an API to drivers that want to share the stage 2 configuration
> of a VM with their device. At the moment it is rather limited:
>
> * No invalidation notifiers. The TLBs on the device side, if any,
> receive CPU TLB invalidations.
>
> * No remote page fault support. All paging still takes the normal data
> abort route on the CPU. Options are pinning all guest memory or
> device-specific mechanism for reporting pending faults to the guest.
>
> * No nested VMs. Although we could perhaps support assigning devices to
> the hyp context of a nested VM, it seems performative.
>
> So for the moment this API works for devices that share the CPU MMU, but
> the SMMU driver could use it with DVM.
>
> Signed-off-by: Jean-Philippe Brucker <jpb@kernel.org>
> ---
> arch/arm64/include/asm/kvm_host.h | 11 ++++
> arch/arm64/include/asm/kvm_mmu.h | 1 +
> arch/arm64/kvm/mmu.c | 102 ++++++++++++++++++++++++++++++
> arch/arm64/kvm/sys_regs.c | 14 +---
> 4 files changed, 117 insertions(+), 11 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 30d0082b15ec..c0932b43f959 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -235,6 +235,14 @@ struct kvm_s2_mmu {
> atomic_t refcnt;
> };
>
> +/* stage 2 MMU configuration, for drivers that speak VMSA */
> +struct kvm_arch_guest_mmu {
> + u64 hcr;
> + u64 hcrx;
> + u64 vtcr;
> + u64 vttbr;
> +};
> +
> struct kvm_arch_memory_slot {
> };
>
> @@ -1720,4 +1728,7 @@ static __always_inline enum fgt_group_id __fgt_reg_to_group_id(enum vcpu_sysreg
>
> long kvm_get_cap_for_kvm_ioctl(unsigned int ioctl, long *ext);
>
> +struct kvm_arch_guest_mmu *kvm_arch_get_guest_mmu(struct kvm *kvm);
> +void kvm_arch_put_guest_mmu(struct kvm *kvm, struct kvm_arch_guest_mmu *mmu);
> +
> #endif /* __ARM64_KVM_HOST_H__ */
> diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
> index 6eae7e7e2a68..8a9d385fe14d 100644
> --- a/arch/arm64/include/asm/kvm_mmu.h
> +++ b/arch/arm64/include/asm/kvm_mmu.h
> @@ -185,6 +185,7 @@ int kvm_handle_guest_sea(struct kvm_vcpu *vcpu);
> int kvm_handle_guest_abort(struct kvm_vcpu *vcpu);
>
> phys_addr_t kvm_mmu_get_httbr(void);
> +u64 kvm_mmu_get_hcr(struct kvm *kvm, u64 hcr);
> phys_addr_t kvm_get_idmap_vector(void);
> int __init kvm_mmu_init(u32 hyp_va_bits);
>
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 2d44cd6a5aed..0bf1dff2a41f 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -2805,3 +2805,105 @@ void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled)
>
> trace_kvm_toggle_cache(*vcpu_pc(vcpu), was_enabled, now_enabled);
> }
> +
> +#define HCR_MMU_BITS (HCR_VM | HCR_PTW | HCR_DC | HCR_TGE | HCR_RW | \
> + HCR_CD | HCR_ID | HCR_E2H | HCR_NV | HCR_NV1 | \
> + HCR_FWB | HCR_ATA | HCR_DCT)
> +
> +/* Update MMU-specific host bits of HCR_EL2 */
> +u64 kvm_mmu_get_hcr(struct kvm *kvm, u64 hcr)
> +{
> + lockdep_assert_held(&kvm->arch.config_lock);
> +
> + WARN_ON(!test_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED,
> + &kvm->arch.flags));
> +
> + hcr &= ~HCR_MMU_BITS;
> + hcr |= HCR_VM | HCR_PTW;
> +
> + if (has_vhe() || has_hvhe())
> + hcr |= HCR_E2H;
> +
> + if (cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
> + hcr |= HCR_FWB;
> +
> + if (kvm_has_mte(kvm))
> + hcr |= HCR_ATA;
> +
> + if (!test_bit(KVM_ARM_VCPU_EL1_32BIT, kvm->arch.vcpu_features))
> + hcr |= HCR_RW;
> +
> + return hcr;
> +}
> +
> +/**
> + * kvm_arch_get_guest_mmu - Get a reference to the guest MMU config
> + * @kvm: KVM instance. Caller must hold a reference.
> + *
> + * Get the stage 2 MMU config of an EL1 VM. The returned object contains
> + * settings that do not change until the object is released with
> + * kvm_arch_put_guest_mmu(). This function does not support nested VMs.
> + *
> + * HCR has lots of settings, some of which differ between vCPUs, but most of
> + * them control traps. For EL1 VMs, the bits relevant to MMU translation are
> + * common to all vCPUs:
> + * - VM, PTW, DC, TGE, CD, ID, NV, NV1, DCT have fixed values.
> + * - E2H, FWB, ATA depend on host CPU features (respectively VHE, FWB and MTE2).
> + * - RW depends on vCPU features. This function does not support 32-bit VMs.
> + *
> + * HCRX: EnSDERR, EnSNERR set to 0. TODO: is GCSEn relevant?
> + *
> + * VTCR is set once for the VM, depends on the VM's IPA size.
> + *
> + * VTTBR:
> + * - VMID is pinned, until kvm_arch_put_guest_mmu() is called.
> + * - PGD is allocated and freed with the vm (the caller must hold their
> + * reference to @kvm). KVM may create and remove page table mappings at any
> + * moment, and uses normal TLB maintenance operations to synchronize with
> + * page table walkers. KVM does not notify the caller about mapping changes.
> + * - CNP is a property of the host system.
> + *
> + * Return: a new kvm_arch_guest_mmu instance, or an error pointer on failure.
> + */
> +struct kvm_arch_guest_mmu *kvm_arch_get_guest_mmu(struct kvm *kvm)
> +{
> + int ret;
> + struct kvm_arch_guest_mmu *mmu;
> +
> + guard(mutex)(&kvm->arch.config_lock);
> +
> + if (is_protected_kvm_enabled())
> + return ERR_PTR(-EOPNOTSUPP);
How does this compose with CCA? Can it be restricted to exclusively
running VHE rather than also dealing with the lesser configurations?
> +
> + if (!test_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED, &kvm->arch.flags) ||
> + test_bit(KVM_ARM_VCPU_EL1_32BIT, kvm->arch.vcpu_features) ||
> + test_bit(KVM_ARM_VCPU_HAS_EL2, kvm->arch.vcpu_features))
> + return ERR_PTR(-EINVAL);
> +
> + ret = kvm_arm_pinned_vmid_get(kvm);
> + if (ret < 0)
> + return ERR_PTR(ret);
> +
> + ret = -ENOMEM;
> + mmu = kzalloc_obj(*mmu, GFP_KERNEL_ACCOUNT);
> + if (!mmu)
> + goto err_unpin_vmid;
> +
> + mmu->vtcr = kvm->arch.mmu.vtcr;
> + mmu->vttbr = kvm_get_vttbr(&kvm->arch.mmu);
> + mmu->hcr = kvm_mmu_get_hcr(kvm, 0);
How about the hcrx field in the structure?
> +
> + return mmu;
> +
> +err_unpin_vmid:
> + kvm_arm_pinned_vmid_put(kvm);
> + return ERR_PTR(ret);
> +}
> +EXPORT_SYMBOL_GPL(kvm_arch_get_guest_mmu);
It really feels like this is a bit upside down. Since you are actively
pinning the S2 MMU context, it should only be a matter of taking a
reference on the kvm struct (just like KVM devices do), and handing
off the kvm_s2_mmu structure, rather than copying things. When you're
done with it, drop the reference.
If there is a need to deal with a different value for HCR_EL2 (or
anything else), it can be done in the code that makes use of it,
rather than being in the KVM code.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
next prev parent reply other threads:[~2026-10-22 15:43 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-15 14:25 [RFC PATCH v2 00/15] Arm Core Local Accelerator Driver Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 01/15] misc/arm-cla: Add driver skeleton and documentation Ryan Roberts
2026-10-15 14:35 ` sashiko-bot
2026-10-15 14:25 ` [RFC PATCH v2 02/15] misc/arm-cla: Add launch operation helpers Ryan Roberts
2026-10-15 14:42 ` sashiko-bot
2026-10-15 16:17 ` Greg Kroah-Hartman
2026-10-15 16:32 ` Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 03/15] dt-bindings: misc: Add Arm Core Local Accelerator Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 04/15] misc/arm-cla: Probe firmware-described devices Ryan Roberts
2026-10-15 14:37 ` sashiko-bot
2026-10-15 14:25 ` [RFC PATCH v2 05/15] misc/arm-cla: Initialize devices on CPU bringup Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 06/15] misc/arm-cla: Accelerator context save and restore Ryan Roberts
2026-10-15 14:41 ` sashiko-bot
2026-10-15 14:25 ` [RFC PATCH v2 07/15] misc/arm-cla: Set up memory translation context Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 08/15] misc/arm-cla: Manage domain contexts Ryan Roberts
2026-10-15 14:38 ` sashiko-bot
2026-10-15 14:25 ` [RFC PATCH v2 09/15] misc/arm-cla: Add userspace interface Ryan Roberts
2026-10-15 14:47 ` sashiko-bot
2026-10-15 14:25 ` [RFC PATCH v2 10/15] KVM: arm64: Introduce support to pin VMIDs Ryan Roberts
2026-10-15 14:38 ` sashiko-bot
2026-10-15 14:25 ` [RFC PATCH v2 11/15] KVM: arm64: Export stage-2 MMU config Ryan Roberts
2026-10-15 14:43 ` sashiko-bot
2026-10-22 15:43 ` Marc Zyngier [this message]
2026-10-23 15:56 ` Jean-Philippe Brucker
2026-10-15 14:25 ` [RFC PATCH v2 12/15] vfio: Support VFIO devices that access the CPU MMU Ryan Roberts
2026-10-15 14:44 ` sashiko-bot
2026-10-15 16:44 ` Jason Gunthorpe
2026-10-20 11:51 ` Ryan Roberts
2026-10-20 14:09 ` Jason Gunthorpe
2026-10-20 15:06 ` Ryan Roberts
2026-10-20 15:13 ` Alex Williamson
2026-10-20 15:55 ` Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 13/15] misc/arm-cla: Add stage-2 MTC and VM context switch Ryan Roberts
2026-10-15 14:40 ` sashiko-bot
2026-10-15 14:25 ` [RFC PATCH v2 14/15] misc/arm-cla: Support exclusive context assignment Ryan Roberts
2026-10-15 14:41 ` sashiko-bot
2026-10-15 14:25 ` [RFC PATCH v2 15/15] misc/arm-cla: Add vfio-mdev user interface Ryan Roberts
2026-10-15 14:49 ` sashiko-bot
2026-10-15 16:41 ` Jason Gunthorpe
2026-10-16 14:22 ` Jean-Philippe Brucker
2026-10-16 14:42 ` Jason Gunthorpe
2026-10-20 10:41 ` Ryan Roberts
2026-10-20 14:15 ` Jason Gunthorpe
2026-10-20 14:27 ` Ryan Roberts
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=86h5idzqow.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=alex@shazbot.org \
--cc=arnd@arndb.de \
--cc=catalin.marinas@arm.com \
--cc=conor+dt@kernel.org \
--cc=corbet@lwn.net \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=gregkh@linuxfoundation.org \
--cc=jgg@nvidia.com \
--cc=jpb@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=ogabbay@kernel.org \
--cc=oupton@kernel.org \
--cc=robh@kernel.org \
--cc=ryan.roberts@arm.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.