* Re: [PATCH v5 1/2] iommupt: Do not set C-bit on MMIO backed PTEs
2026-01-25 19:19 ` [PATCH v5 1/2] iommupt: Do not set C-bit on MMIO backed PTEs Wei Wang
@ 2026-01-19 6:31 ` Vasant Hegde
0 siblings, 0 replies; 7+ messages in thread
From: Vasant Hegde @ 2026-01-19 6:31 UTC (permalink / raw)
To: Wei Wang, jgg, kevin.tian, alex, joro, thomas.lendacky,
suravee.suthikulpanit, aik
Cc: iommu, linux-kernel
On 1/26/2026 12:49 AM, Wei Wang wrote:
> AMD Secure Memory Encryption (SME) marks individual memory pages as
> encrypted by setting the C-bit in page table entries. According to the
> AMD APM,any pages corresponding to MMIO addresses must be configured
> with the C-bit clear.
>
> The current *_iommu_set_prot() implementation sets the C-bit on all PTEs
> in the IOMMU page tables. This is incorrect for PTEs backed by MMIO, and
> can break PCIe peer-to-peer communication when IOVA is used. Fix this by
> avoiding the C-bit for MMIO-backed mappings.
>
> For amdv2 IOMMU page tables, there is a usage scenario for GVA->GPA
> mappings, and for the trusted MMIO in the TEE-IO case, the C-bit will need
> to be added to GPA. However, SNP guests do not yet support vIOMMU, and the
> trusted MMIO support is not ready in upstream. Adding the C-bit for trusted
> MMIO can be considered once those features land.
>
> Fixes: 879ced2bab1b ("iommupt: Add the AMD IOMMU v1 page table format")
> Fixes: aef5de756ea8 ("iommupt: Add the x86 64 bit page table format")
> Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
> Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
-Vasant
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v5 0/2] iommu: Avoid setting C-bit for MMIO addresses
2026-01-25 19:19 [PATCH v5 0/2] iommu: Avoid setting C-bit for MMIO addresses Wei Wang
@ 2026-01-19 9:20 ` Jörg Rödel
2026-01-25 19:19 ` [PATCH v5 1/2] iommupt: Do not set C-bit on MMIO backed PTEs Wei Wang
2026-01-25 19:19 ` [PATCH v5 2/2] vfio/type1: Set IOMMU_MMIO in dma->prot for MMIO-backed addresses Wei Wang
2 siblings, 0 replies; 7+ messages in thread
From: Jörg Rödel @ 2026-01-19 9:20 UTC (permalink / raw)
To: Wei Wang
Cc: jgg, kevin.tian, alex, thomas.lendacky, vasant.hegde,
suravee.suthikulpanit, aik, iommu, linux-kernel
On Mon, Jan 26, 2026 at 03:19:19AM +0800, Wei Wang wrote:
> iommupt: Do not set C-bit on MMIO backed PTEs
Applied patch 1, thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v5 0/2] iommu: Avoid setting C-bit for MMIO addresses
@ 2026-01-25 19:19 Wei Wang
2026-01-19 9:20 ` Jörg Rödel
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Wei Wang @ 2026-01-25 19:19 UTC (permalink / raw)
To: jgg, kevin.tian, alex, joro, thomas.lendacky, vasant.hegde,
suravee.suthikulpanit, aik
Cc: iommu, linux-kernel, wei.w.wang
AMD APM specifies that any pages corresponding to MMIO addresses must be
configured with the C-bit clear. The current iommu implementation sets
the C-bit on all PTEs in the IOMMU page tables. This is incorrect for PTEs
backed by MMIO, and can break PCIe peer-to-peer communication when IOVA is
used. Fix this by avoiding the C-bit for MMIO-backed mappings.
v4->v5 change:
- Handle the rare case where adjacent RAM and MMIO ranges are mapped in a
single vfio_pin_map_dma() call. vfio_pin_map_dma() issues separate
vfio_iommu_map() calls for RAM and MMIO, and vfio_pin_pages_remote()
sets dma->prot to indicate MMIO mappings.
Clear IOMMU_MMIO in vfio_pin_pages_remote() when !rsvd, since valid
MMIO mappings always have rsvd == true.
v4 link: https://lore.kernel.org/all/SI2PR01MB439311868FBFB7DDAD19692CDCB4A@SI2PR01MB4393.apcprd01.prod.exchangelabs.com/
v3->v4 change:
- In the 2nd patch, moved the VM_IO check into the
if (is_invalid_reserved_pfn(*pfn)) {} code block to avoid checking it on
error paths.
v3 link: https://lore.kernel.org/lkml/SI2PR01MB439337D5513729BAC122F526DCCDA@SI2PR01MB4393.apcprd01.prod.exchangelabs.com/
v2->v3 changes:
- re-implement the iommu part based on the iommu tree which has the
iommupt patches merged.
v2 link: https://lore.kernel.org/lkml/SI2PR01MB439373CA7A023D8EC4C42040DCC7A@SI2PR01MB4393.apcprd01.prod.exchangelabs.com/
v1->v2 changes:
- 1 used page_is_ram() in the AMD IOMMU driver to detect non-RAM
addresses, avoiding changes to upper-layer callers (vfio and iommufd).
v2 instead lets upper layers explicitly indicate MMIO mappings via the
IOMMU_MMIO prot flag. This avoids the potential overhead of
page_is_ram(). (suggested by Jason Gunthorpe)
v1 link: https://lore.kernel.org/lkml/SI2PR01MB439358422CCAABADBEB21D7CDCF0A@SI2PR01MB4393.apcprd01.prod.exchangelabs.com/
Wei Wang (2):
iommupt: Do not set C-bit on MMIO backed PTEs
vfio/type1: Set IOMMU_MMIO in dma->prot for MMIO-backed addresses
drivers/iommu/generic_pt/fmt/amdv1.h | 3 ++-
drivers/iommu/generic_pt/fmt/x86_64.h | 3 ++-
drivers/vfio/vfio_iommu_type1.c | 15 ++++++++++-----
3 files changed, 14 insertions(+), 7 deletions(-)
base-commit: 46fe65a2c28ecf5df1a7475aba1f08ccf4c0ac1b
--
2.51.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v5 1/2] iommupt: Do not set C-bit on MMIO backed PTEs
2026-01-25 19:19 [PATCH v5 0/2] iommu: Avoid setting C-bit for MMIO addresses Wei Wang
2026-01-19 9:20 ` Jörg Rödel
@ 2026-01-25 19:19 ` Wei Wang
2026-01-19 6:31 ` Vasant Hegde
2026-01-25 19:19 ` [PATCH v5 2/2] vfio/type1: Set IOMMU_MMIO in dma->prot for MMIO-backed addresses Wei Wang
2 siblings, 1 reply; 7+ messages in thread
From: Wei Wang @ 2026-01-25 19:19 UTC (permalink / raw)
To: jgg, kevin.tian, alex, joro, thomas.lendacky, vasant.hegde,
suravee.suthikulpanit, aik
Cc: iommu, linux-kernel, wei.w.wang
AMD Secure Memory Encryption (SME) marks individual memory pages as
encrypted by setting the C-bit in page table entries. According to the
AMD APM,any pages corresponding to MMIO addresses must be configured
with the C-bit clear.
The current *_iommu_set_prot() implementation sets the C-bit on all PTEs
in the IOMMU page tables. This is incorrect for PTEs backed by MMIO, and
can break PCIe peer-to-peer communication when IOVA is used. Fix this by
avoiding the C-bit for MMIO-backed mappings.
For amdv2 IOMMU page tables, there is a usage scenario for GVA->GPA
mappings, and for the trusted MMIO in the TEE-IO case, the C-bit will need
to be added to GPA. However, SNP guests do not yet support vIOMMU, and the
trusted MMIO support is not ready in upstream. Adding the C-bit for trusted
MMIO can be considered once those features land.
Fixes: 879ced2bab1b ("iommupt: Add the AMD IOMMU v1 page table format")
Fixes: aef5de756ea8 ("iommupt: Add the x86 64 bit page table format")
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
---
drivers/iommu/generic_pt/fmt/amdv1.h | 3 ++-
drivers/iommu/generic_pt/fmt/x86_64.h | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/generic_pt/fmt/amdv1.h b/drivers/iommu/generic_pt/fmt/amdv1.h
index aa8e1a8ec95f..3b2c41d9654d 100644
--- a/drivers/iommu/generic_pt/fmt/amdv1.h
+++ b/drivers/iommu/generic_pt/fmt/amdv1.h
@@ -354,7 +354,8 @@ static inline int amdv1pt_iommu_set_prot(struct pt_common *common,
* Ideally we'd have an IOMMU_ENCRYPTED flag set by higher levels to
* control this. For now if the tables use sme_set then so do the ptes.
*/
- if (pt_feature(common, PT_FEAT_AMDV1_ENCRYPT_TABLES))
+ if (pt_feature(common, PT_FEAT_AMDV1_ENCRYPT_TABLES) &&
+ !(iommu_prot & IOMMU_MMIO))
pte = __sme_set(pte);
attrs->descriptor_bits = pte;
diff --git a/drivers/iommu/generic_pt/fmt/x86_64.h b/drivers/iommu/generic_pt/fmt/x86_64.h
index 210748d9d6e8..ed9a47cbb6e0 100644
--- a/drivers/iommu/generic_pt/fmt/x86_64.h
+++ b/drivers/iommu/generic_pt/fmt/x86_64.h
@@ -227,7 +227,8 @@ static inline int x86_64_pt_iommu_set_prot(struct pt_common *common,
* Ideally we'd have an IOMMU_ENCRYPTED flag set by higher levels to
* control this. For now if the tables use sme_set then so do the ptes.
*/
- if (pt_feature(common, PT_FEAT_X86_64_AMD_ENCRYPT_TABLES))
+ if (pt_feature(common, PT_FEAT_X86_64_AMD_ENCRYPT_TABLES) &&
+ !(iommu_prot & IOMMU_MMIO))
pte = __sme_set(pte);
attrs->descriptor_bits = pte;
--
2.51.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v5 2/2] vfio/type1: Set IOMMU_MMIO in dma->prot for MMIO-backed addresses
2026-01-25 19:19 [PATCH v5 0/2] iommu: Avoid setting C-bit for MMIO addresses Wei Wang
2026-01-19 9:20 ` Jörg Rödel
2026-01-25 19:19 ` [PATCH v5 1/2] iommupt: Do not set C-bit on MMIO backed PTEs Wei Wang
@ 2026-01-25 19:19 ` Wei Wang
2026-02-04 15:16 ` Wei Wang
2026-02-25 8:45 ` Wei Wang
2 siblings, 2 replies; 7+ messages in thread
From: Wei Wang @ 2026-01-25 19:19 UTC (permalink / raw)
To: jgg, kevin.tian, alex, joro, thomas.lendacky, vasant.hegde,
suravee.suthikulpanit, aik
Cc: iommu, linux-kernel, wei.w.wang
Before requesting the IOMMU driver to map an IOVA to a physical address,
set the IOMMU_MMIO flag in dma->prot when the physical address corresponds
to MMIO. This allows the IOMMU driver to handle MMIO mappings specially.
For example, on AMD CPUs with SME enabled, the IOMMU driver avoids setting
the C-bit if iommu_map() is called with IOMMU_MMIO set in prot. This
prevents issues with PCIe P2P communication when IOVA is used.
Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
---
drivers/vfio/vfio_iommu_type1.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 5167bec14e36..9fbd2ba519ca 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -583,7 +583,7 @@ static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm,
* returned initial pfn are provided; subsequent pfns are contiguous.
*/
static long vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
- unsigned long npages, int prot, unsigned long *pfn,
+ unsigned long npages, int *prot, unsigned long *pfn,
struct vfio_batch *batch)
{
unsigned long pin_pages = min_t(unsigned long, npages, batch->capacity);
@@ -591,7 +591,7 @@ static long vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
unsigned int flags = 0;
long ret;
- if (prot & IOMMU_WRITE)
+ if (*prot & IOMMU_WRITE)
flags |= FOLL_WRITE;
mmap_read_lock(mm);
@@ -615,7 +615,7 @@ static long vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
unsigned long addr_mask;
ret = follow_fault_pfn(vma, mm, vaddr, pfn, &addr_mask,
- prot & IOMMU_WRITE);
+ *prot & IOMMU_WRITE);
if (ret == -EAGAIN)
goto retry;
@@ -623,6 +623,9 @@ static long vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
if (is_invalid_reserved_pfn(*pfn)) {
unsigned long epfn;
+ if (vma->vm_flags & VM_IO)
+ *prot |= IOMMU_MMIO;
+
epfn = (*pfn | (~addr_mask >> PAGE_SHIFT)) + 1;
ret = min_t(long, npages, epfn - *pfn);
} else {
@@ -709,7 +712,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
cond_resched();
/* Empty batch, so refill it. */
- ret = vaddr_get_pfns(mm, vaddr, npage, dma->prot,
+ ret = vaddr_get_pfns(mm, vaddr, npage, &dma->prot,
&pfn, batch);
if (ret < 0)
goto unpin_out;
@@ -792,6 +795,8 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
out:
dma->has_rsvd |= rsvd;
+ if (!rsvd)
+ dma->prot &= ~IOMMU_MMIO;
ret = vfio_lock_acct(dma, lock_acct, false);
unpin_out:
@@ -850,7 +855,7 @@ static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr,
vfio_batch_init_single(&batch);
- ret = vaddr_get_pfns(mm, vaddr, 1, dma->prot, pfn_base, &batch);
+ ret = vaddr_get_pfns(mm, vaddr, 1, &dma->prot, pfn_base, &batch);
if (ret != 1)
goto out;
--
2.51.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v5 2/2] vfio/type1: Set IOMMU_MMIO in dma->prot for MMIO-backed addresses
2026-01-25 19:19 ` [PATCH v5 2/2] vfio/type1: Set IOMMU_MMIO in dma->prot for MMIO-backed addresses Wei Wang
@ 2026-02-04 15:16 ` Wei Wang
2026-02-25 8:45 ` Wei Wang
1 sibling, 0 replies; 7+ messages in thread
From: Wei Wang @ 2026-02-04 15:16 UTC (permalink / raw)
To: jgg, kevin.tian, alex, joro, thomas.lendacky, vasant.hegde,
suravee.suthikulpanit, aik
Cc: iommu, linux-kernel
On 1/26/26 3:19 AM, Wei Wang wrote:
> Before requesting the IOMMU driver to map an IOVA to a physical address,
> set the IOMMU_MMIO flag in dma->prot when the physical address corresponds
> to MMIO. This allows the IOMMU driver to handle MMIO mappings specially.
> For example, on AMD CPUs with SME enabled, the IOMMU driver avoids setting
> the C-bit if iommu_map() is called with IOMMU_MMIO set in prot. This
> prevents issues with PCIe P2P communication when IOVA is used.
>
> Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> ---
> drivers/vfio/vfio_iommu_type1.c | 15 ++++++++++-----
> 1 file changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 5167bec14e36..9fbd2ba519ca 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -583,7 +583,7 @@ static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm,
> * returned initial pfn are provided; subsequent pfns are contiguous.
> */
> static long vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
> - unsigned long npages, int prot, unsigned long *pfn,
> + unsigned long npages, int *prot, unsigned long *pfn,
> struct vfio_batch *batch)
> {
> unsigned long pin_pages = min_t(unsigned long, npages, batch->capacity);
> @@ -591,7 +591,7 @@ static long vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
> unsigned int flags = 0;
> long ret;
>
> - if (prot & IOMMU_WRITE)
> + if (*prot & IOMMU_WRITE)
> flags |= FOLL_WRITE;
>
> mmap_read_lock(mm);
> @@ -615,7 +615,7 @@ static long vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
> unsigned long addr_mask;
>
> ret = follow_fault_pfn(vma, mm, vaddr, pfn, &addr_mask,
> - prot & IOMMU_WRITE);
> + *prot & IOMMU_WRITE);
> if (ret == -EAGAIN)
> goto retry;
>
> @@ -623,6 +623,9 @@ static long vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
> if (is_invalid_reserved_pfn(*pfn)) {
> unsigned long epfn;
>
> + if (vma->vm_flags & VM_IO)
> + *prot |= IOMMU_MMIO;
> +
> epfn = (*pfn | (~addr_mask >> PAGE_SHIFT)) + 1;
> ret = min_t(long, npages, epfn - *pfn);
> } else {
> @@ -709,7 +712,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
> cond_resched();
>
> /* Empty batch, so refill it. */
> - ret = vaddr_get_pfns(mm, vaddr, npage, dma->prot,
> + ret = vaddr_get_pfns(mm, vaddr, npage, &dma->prot,
> &pfn, batch);
> if (ret < 0)
> goto unpin_out;
> @@ -792,6 +795,8 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
>
> out:
> dma->has_rsvd |= rsvd;
> + if (!rsvd)
> + dma->prot &= ~IOMMU_MMIO;
> ret = vfio_lock_acct(dma, lock_acct, false);
>
> unpin_out:
> @@ -850,7 +855,7 @@ static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr,
>
> vfio_batch_init_single(&batch);
>
> - ret = vaddr_get_pfns(mm, vaddr, 1, dma->prot, pfn_base, &batch);
> + ret = vaddr_get_pfns(mm, vaddr, 1, &dma->prot, pfn_base, &batch);
> if (ret != 1)
> goto out;
>
Hi Alexey,
Just checking in — do you have any further comments on this patch?
For reference, the previous discussion is here:
https://lore.kernel.org/lkml/SI2PR01MB439311868FBFB7DDAD19692CDCB4A@SI2PR01MB4393.apcprd01.prod.exchangelabs.com/
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v5 2/2] vfio/type1: Set IOMMU_MMIO in dma->prot for MMIO-backed addresses
2026-01-25 19:19 ` [PATCH v5 2/2] vfio/type1: Set IOMMU_MMIO in dma->prot for MMIO-backed addresses Wei Wang
2026-02-04 15:16 ` Wei Wang
@ 2026-02-25 8:45 ` Wei Wang
1 sibling, 0 replies; 7+ messages in thread
From: Wei Wang @ 2026-02-25 8:45 UTC (permalink / raw)
To: jgg, kevin.tian, alex, joro, thomas.lendacky, vasant.hegde,
suravee.suthikulpanit, aik
Cc: iommu, linux-kernel
On 1/26/26 3:19 AM, Wei Wang wrote:
> Before requesting the IOMMU driver to map an IOVA to a physical address,
> set the IOMMU_MMIO flag in dma->prot when the physical address corresponds
> to MMIO. This allows the IOMMU driver to handle MMIO mappings specially.
> For example, on AMD CPUs with SME enabled, the IOMMU driver avoids setting
> the C-bit if iommu_map() is called with IOMMU_MMIO set in prot. This
> prevents issues with PCIe P2P communication when IOVA is used.
>
> Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> ---
> drivers/vfio/vfio_iommu_type1.c | 15 ++++++++++-----
> 1 file changed, 10 insertions(+), 5 deletions(-)
Hi Alex W,
The first patch in this series (the IOMMU part) has been merged and
queued for stable. I haven’t seen further comments on the VFIO patch,
so I wanted to check whether you have any feedback or concerns about
it. Thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-02-25 8:46 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-25 19:19 [PATCH v5 0/2] iommu: Avoid setting C-bit for MMIO addresses Wei Wang
2026-01-19 9:20 ` Jörg Rödel
2026-01-25 19:19 ` [PATCH v5 1/2] iommupt: Do not set C-bit on MMIO backed PTEs Wei Wang
2026-01-19 6:31 ` Vasant Hegde
2026-01-25 19:19 ` [PATCH v5 2/2] vfio/type1: Set IOMMU_MMIO in dma->prot for MMIO-backed addresses Wei Wang
2026-02-04 15:16 ` Wei Wang
2026-02-25 8:45 ` Wei Wang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®