[PATCH 1/2] PCI/P2PDMA: Allow P2PDMA in VMware guests on Intel hosts

From: Pavel Popov

Date: Fri Oct 09 2026 - 11:52:39 EST


Peer-to-Peer DMA (P2PDMA) between two devices requires either a shared
upstream bridge or a host bridge matching pci_p2pdma_whitelist[]. In
VMware guests, passthrough devices appear directly on virtual root
buses without host bridge devices. Consequently, P2PDMA checks
evaluate endpoint Device IDs against the host bridge whitelist,
causing P2PDMA requests to fail regardless of host support.

This affects discrete devices such as GPUs, NICs and NVMe drives.

The P2PDMA host bridge check does not work in a VMware guest. Bypass it on
Intel hosts under VMware, starting with Skylake-SP, the first Xeon
Scalable generation. Xeon Scalable introduced UPI and is whitelisted for
P2PDMA without restrictions. AMD Zen and newer are already covered by
cpu_supports_p2pdma(), so the bypass is implemented for Intel hosts only.

Tested with the Intel Level Zero P2P benchmark (ze_peer) on Arc Pro B60
cards in a Linux guest on VMware ESXi 9.0 (Emerald Rapids host).

Reviewed-by: Jim Chow <jim.chow@xxxxxxxxxxxx>
Signed-off-by: Pavel Popov <pavel.e.popov@xxxxxxxxx>
---
drivers/pci/p2pdma.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 9334eb314663..d96f44d0738a 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -21,6 +21,12 @@
#include <linux/seq_buf.h>
#include <linux/xarray.h>

+#ifdef CONFIG_X86
+#include <asm/cpu_device_id.h>
+#include <asm/hypervisor.h>
+#include <asm/intel-family.h>
+#endif
+
struct pci_p2pdma {
struct gen_pool *pool;
bool p2pmem_published;
@@ -532,6 +538,19 @@ static bool cpu_supports_p2pdma(void)
return false;
}

+static bool hypervisor_supports_p2pdma(void)
+{
+#ifdef CONFIG_X86
+ /* Hypervisor hides host topology, allow p2pdma on Skylake and newer */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+ boot_cpu_data.x86_vfm >= INTEL_SKYLAKE_X &&
+ hypervisor_is_type(X86_HYPER_VMWARE))
+ return true;
+#endif
+
+ return false;
+}
+
static const struct pci_p2pdma_whitelist_entry {
unsigned short vendor;
int device;
@@ -781,6 +800,7 @@ calc_map_type_and_dist(struct pci_dev *provider, struct pci_dev *client,

map_through_host_bridge:
if (!cpu_supports_p2pdma() &&
+ !hypervisor_supports_p2pdma() &&
!host_bridge_whitelist(provider, client, acs_redirects)) {
if (verbose)
pci_warn(client, "cannot be used for peer-to-peer DMA as the client and provider (%s) do not share an upstream bridge or whitelisted host bridge\n",
--
2.53.0