[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aNpm9odmzv__2RyA@google.com>
Date: Mon, 29 Sep 2025 11:01:10 +0000
From: Mostafa Saleh <smostafa@...gle.com>
To: Will Deacon <will@...nel.org>
Cc: linux-kernel@...r.kernel.org, kvmarm@...ts.linux.dev,
linux-arm-kernel@...ts.infradead.org, iommu@...ts.linux.dev,
maz@...nel.org, oliver.upton@...ux.dev, joey.gouly@....com,
suzuki.poulose@....com, yuzenghui@...wei.com,
catalin.marinas@....com, robin.murphy@....com,
jean-philippe@...aro.org, qperret@...gle.com, tabba@...gle.com,
jgg@...pe.ca, mark.rutland@....com, praan@...gle.com
Subject: Re: [PATCH v4 10/28] KVM: arm64: iommu: Shadow host stage-2 page
table
On Fri, Sep 26, 2025 at 03:42:38PM +0100, Will Deacon wrote:
> On Tue, Sep 16, 2025 at 02:24:46PM +0000, Mostafa Saleh wrote:
> > On Tue, Sep 09, 2025 at 03:42:07PM +0100, Will Deacon wrote:
> > > On Tue, Aug 19, 2025 at 09:51:38PM +0000, Mostafa Saleh wrote:
> > > > diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c
> > > > index a01c036c55be..f7d1c8feb358 100644
> > > > --- a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c
> > > > +++ b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c
> > > > @@ -4,15 +4,94 @@
> > > > *
> > > > * Copyright (C) 2022 Linaro Ltd.
> > > > */
> > > > +#include <linux/iommu.h>
> > > > +
> > > > #include <nvhe/iommu.h>
> > > > +#include <nvhe/mem_protect.h>
> > > > +#include <nvhe/spinlock.h>
> > > >
> > > > /* Only one set of ops supported */
> > > > struct kvm_iommu_ops *kvm_iommu_ops;
> > > >
> > > > +/* Protected by host_mmu.lock */
> > > > +static bool kvm_idmap_initialized;
> > > > +
> > > > +static inline int pkvm_to_iommu_prot(enum kvm_pgtable_prot prot)
> > > > +{
> > > > + int iommu_prot = 0;
> > > > +
> > > > + if (prot & KVM_PGTABLE_PROT_R)
> > > > + iommu_prot |= IOMMU_READ;
> > > > + if (prot & KVM_PGTABLE_PROT_W)
> > > > + iommu_prot |= IOMMU_WRITE;
> > > > + if (prot == PKVM_HOST_MMIO_PROT)
> > > > + iommu_prot |= IOMMU_MMIO;
> > >
> > > This looks a little odd to me.
> > >
> > > On the CPU side, the only different between PKVM_HOST_MEM_PROT and
> > > PKVM_HOST_MMIO_PROT is that the former has execute permission. Both are
> > > mapped as cacheable at stage-2 because it's the job of the host to set
> > > the more restrictive memory type at stage-1.
> > >
> > > Carrying that over to the SMMU would suggest that we don't care about
> > > IOMMU_MMIO at stage-2 at all, so why do we need to set it here?
> >
> > Unlike the CPU, the host can set the SMMU to bypass, in that case the
> > hypervisor will attach its stage-2 with no stage-1 configured. So,
> > stage-2 must have the correct attrs for MMIO.
>
> I'm not sure about that.
>
> If the SMMU is in stage-1 bypass, we still have the incoming memory
> attributes from the transaction (modulo MTCFG which we shouldn't be
> setting) and they should combine with the stage-2 attributes in roughly
> the same way as the CPU, no?
Makes sense, we can remove that for now and map all stage-2 with
IOMMU_CACHE. However, that might not be true for other IOMMUs,
as they might not combine attributes as SMMUv3 stage-2, but we
can ignore that for now. I will update the logic in v5.
Thanks,
Mostafa
>
> > > > +static int __snapshot_host_stage2(const struct kvm_pgtable_visit_ctx *ctx,
> > > > + enum kvm_pgtable_walk_flags visit)
> > > > +{
> > > > + u64 start = ctx->addr;
> > > > + kvm_pte_t pte = *ctx->ptep;
> > > > + u32 level = ctx->level;
> > > > + u64 end = start + kvm_granule_size(level);
> > > > + int prot = IOMMU_READ | IOMMU_WRITE;
> > > > +
> > > > + /* Keep unmapped. */
> > > > + if (pte && !kvm_pte_valid(pte))
> > > > + return 0;
> > > > +
> > > > + if (kvm_pte_valid(pte))
> > > > + prot = pkvm_to_iommu_prot(kvm_pgtable_stage2_pte_prot(pte));
> > > > + else if (!addr_is_memory(start))
> > > > + prot |= IOMMU_MMIO;
> > >
> > > Why do we need to map MMIO regions pro-actively here? I'd have thought
> > > we could just do:
> > >
> > > if (!kvm_pte_valid(pte))
> > > return 0;
> > >
> > > prot = pkvm_to_iommu_prot(kvm_pgtable_stage2_pte_prot(pte);
> > > kvm_iommu_ops->host_stage2_idmap(start, end, prot);
> > > return 0;
> > >
> > > but I think that IOMMU_MMIO is throwing me again...
> >
> > We have to map everything pro-actively as we don’t handle page faults
> > in the SMMUv3 driver.
> > This would be a future work where the CPU stage-2 page table is shared with
> > the SMMUv3.
>
> Ah yes, I'd forgotten about that.
>
> Thanks,
>
> Will
Powered by blists - more mailing lists