hw/vfio/listener.c | 47 +++++++++++++++++++++++++------------------- hw/vfio/trace-events | 2 +- 2 files changed, 28 insertions(+), 21 deletions(-)
The vfio_known_safe_misalignment() whitelist (currently TPM CRB only)
requires a new entry every time a device exposes a non-page-aligned
region, which does not scale.
Replace it with a DMA capability check: a region that is not
page-aligned or is smaller than a host page can never be a valid DMA
target, so a page-offset mismatch is harmless and only traced. Only
warn for page-aligned, page-sized regions where the mismatch could
indicate a real mapping problem.
This removes the TPM CRB dependency from the VFIO listener and
eliminates the need for per-device whitelisting entirely.
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Link: https://lore.kernel.org/qemu-devel/20260702160640.3875666-1-clg@redhat.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
hw/vfio/listener.c | 47 +++++++++++++++++++++++++-------------------
hw/vfio/trace-events | 2 +-
2 files changed, 28 insertions(+), 21 deletions(-)
diff --git a/hw/vfio/listener.c b/hw/vfio/listener.c
index c19600e980a8d02217b5d9df4aca8f879ab2c5d5..f2c3603a920b99002630d6f47af5bbbdfed8be86 100644
--- a/hw/vfio/listener.c
+++ b/hw/vfio/listener.c
@@ -40,7 +40,6 @@
#include "migration/misc.h"
#include "migration/qemu-file.h"
#include "system/tcg.h"
-#include "system/tpm.h"
#include "vfio-migration-internal.h"
#include "vfio-helpers.h"
#include "vfio-listener.h"
@@ -352,20 +351,17 @@ static void vfio_ram_discard_unregister_listener(VFIOContainer *bcontainer,
g_free(vrdl);
}
-static bool vfio_known_safe_misalignment(MemoryRegionSection *section)
+static bool vfio_section_misaligned(MemoryRegionSection *section)
{
- MemoryRegion *mr = section->mr;
-
- if (!TPM_IS_CRB(mr->owner)) {
- return false;
- }
+ return (section->offset_within_address_space & ~qemu_real_host_page_mask()) !=
+ (section->offset_within_region & ~qemu_real_host_page_mask());
+}
- /* this is a known safe misaligned region, just trace for debug purpose */
- trace_vfio_known_safe_misalignment(memory_region_name(mr),
- section->offset_within_address_space,
- section->offset_within_region,
- qemu_real_host_page_size());
- return true;
+static bool vfio_section_dma_capable(MemoryRegionSection *section)
+{
+ return QEMU_IS_ALIGNED(section->offset_within_address_space,
+ qemu_real_host_page_size()) &&
+ int128_ge(section->size, int128_make64(qemu_real_host_page_size()));
}
static bool vfio_listener_valid_section(MemoryRegionSection *section,
@@ -379,17 +375,28 @@ static bool vfio_listener_valid_section(MemoryRegionSection *section,
return false;
}
- if (unlikely((section->offset_within_address_space &
- ~qemu_real_host_page_mask()) !=
- (section->offset_within_region & ~qemu_real_host_page_mask()))) {
- if (!vfio_known_safe_misalignment(section)) {
- error_report("%s received unaligned region %s iova=0x%"PRIx64
+ if (unlikely(vfio_section_misaligned(section))) {
+ /*
+ * A region that is not page-aligned or is smaller than a host
+ * page can never be a valid DMA target, so the misalignment is
+ * harmless. Only warn for page-aligned, page-sized regions
+ * where the offset mismatch could indicate a real problem.
+ */
+ if (vfio_section_dma_capable(section)) {
+ error_report("vfio: region %s page-offset mismatch prevents"
+ " DMA mapping (iova=0x%"PRIx64
" offset_within_region=0x%"PRIx64
- " qemu_real_host_page_size=0x%"PRIxPTR,
- __func__, memory_region_name(section->mr),
+ " page_size=0x%"PRIxPTR ")",
+ memory_region_name(section->mr),
section->offset_within_address_space,
section->offset_within_region,
qemu_real_host_page_size());
+ } else {
+ trace_vfio_listener_region_misaligned(
+ memory_region_name(section->mr),
+ section->offset_within_address_space,
+ section->offset_within_region,
+ qemu_real_host_page_size());
}
return false;
}
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index bfdaf229e42b0d9d40e38c828c97cf47eb831a87..8cbad9ad0f3a4cbcbb3b5f00ac7afe392a821071 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -99,7 +99,7 @@ vfio_spapr_group_attach(int groupfd, int tablefd) "Attached groupfd %d to liobn
vfio_listener_region_add_iommu(const char* name, uint64_t start, uint64_t end) "region_add [iommu] %s 0x%"PRIx64" - 0x%"PRIx64
vfio_listener_region_del_iommu(const char *name) "region_del [iommu] %s"
vfio_listener_region_add_ram(uint64_t iova_start, uint64_t iova_end, void *vaddr) "region_add [ram] 0x%"PRIx64" - 0x%"PRIx64" [%p]"
-vfio_known_safe_misalignment(const char *name, uint64_t iova, uint64_t offset_within_region, uintptr_t page_size) "Region \"%s\" iova=0x%"PRIx64" offset_within_region=0x%"PRIx64" qemu_real_host_page_size=0x%"PRIxPTR
+vfio_listener_region_misaligned(const char *name, uint64_t iova, uint64_t offset_within_region, uintptr_t page_size) "Region \"%s\" iova=0x%"PRIx64" offset_within_region=0x%"PRIx64" qemu_real_host_page_size=0x%"PRIxPTR
vfio_listener_region_add_no_dma_map(const char *name, uint64_t iova, uint64_t size, uint64_t page_size) "Region \"%s\" 0x%"PRIx64" size=0x%"PRIx64" is not aligned to 0x%"PRIx64" and cannot be mapped for DMA"
vfio_listener_region_skip_dma_map(const char *name, uint64_t iova, uint64_t size) "Region \"%s\" 0x%"PRIx64" size=0x%"PRIx64" marked to skip IOMMU mapping"
vfio_listener_region_del(uint64_t start, uint64_t end) "region_del 0x%"PRIx64" - 0x%"PRIx64
--
2.54.0
On Wed, 8 Jul 2026 15:36:04 +0200 Cédric Le Goater <clg@redhat.com> wrote: > The vfio_known_safe_misalignment() whitelist (currently TPM CRB only) > requires a new entry every time a device exposes a non-page-aligned > region, which does not scale. Arguable as we have exactly one class of device so far that's validated as safe. > Replace it with a DMA capability check: a region that is not > page-aligned or is smaller than a host page can never be a valid DMA > target, so a page-offset mismatch is harmless and only traced. Only > warn for page-aligned, page-sized regions where the mismatch could > indicate a real mapping problem. But it's the composition into the address space and how that address space is defined to the guest that matters. Imagine a minimum counter example to the test presented here, a page-size range of RAM in the VM is composed by a device as two contiguous sub-page MemoryRegions. We only see the individual MRs here, they're each sub-page, the shape suggests they're not DMA targets, but together they map contiguously into the VM address space. KVM can trap and emulate them as normal RAM. QEMU emulated devices can DMA to them as RAM. VFIO cannot map them through the IOMMU. That is what this test is meant to validate. The judgment that the control register range for a TPM device presented as a RAM MR is not a meaningful DMA target for a vfio device is the thing that cannot be determined based only on the shape of the MR. > This removes the TPM CRB dependency from the VFIO listener and > eliminates the need for per-device whitelisting entirely. And removes the diagnostic it provided. Thanks, Alex
On 7/8/26 17:06, Alex Williamson wrote: > On Wed, 8 Jul 2026 15:36:04 +0200 > Cédric Le Goater <clg@redhat.com> wrote: > >> The vfio_known_safe_misalignment() whitelist (currently TPM CRB only) >> requires a new entry every time a device exposes a non-page-aligned >> region, which does not scale. > > Arguable as we have exactly one class of device so far that's validated > as safe. > >> Replace it with a DMA capability check: a region that is not >> page-aligned or is smaller than a host page can never be a valid DMA >> target, so a page-offset mismatch is harmless and only traced. Only >> warn for page-aligned, page-sized regions where the mismatch could >> indicate a real mapping problem. > > But it's the composition into the address space and how that address > space is defined to the guest that matters. Imagine a minimum counter > example to the test presented here, a page-size range of RAM in the VM > is composed by a device as two contiguous sub-page MemoryRegions. We > only see the individual MRs here, they're each sub-page, the shape > suggests they're not DMA targets, but together they map contiguously > into the VM address space. KVM can trap and emulate them as normal > RAM. QEMU emulated devices can DMA to them as RAM. VFIO cannot map > them through the IOMMU. > > That is what this test is meant to validate. The judgment that the > control register range for a TPM device presented as a RAM MR is not a > meaningful DMA target for a vfio device is the thing that cannot be > determined based only on the shape of the MR. ok. I understand. this is difficult to address cleanly without a white list then. Which is what "Extend safe misalignment check to tpm-ppi region" proposes. I will let it cool down. This change is not critical. It is part of a broader effort to avoid giving users the wrong impression that the problem comes from VFIO when analyzing diagnostic logs with errors/warnings spread across the system. This is not the only VFIO message in this category. C.
© 2016 - 2026 Red Hat, Inc.