linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Yonatan Maman <ymaman@nvidia.com>
To: "Jérôme Glisse" <jglisse@redhat.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Jason Gunthorpe" <jgg@ziepe.ca>,
	"Leon Romanovsky" <leon@kernel.org>
Cc: Lyude Paul <lyude@redhat.com>, Danilo Krummrich <dakr@kernel.org>,
	"David Airlie" <airlied@gmail.com>,
	Simona Vetter <simona@ffwll.ch>,
	Alistair Popple <apopple@nvidia.com>,
	Ben Skeggs <bskeggs@nvidia.com>,
	Michael Guralnik <michaelgur@nvidia.com>,
	Or Har-Toov <ohartoov@nvidia.com>,
	Daisuke Matsuda <dskmtsd@gmail.com>,
	Shay Drory <shayd@nvidia.com>, <linux-mm@kvack.org>,
	<linux-rdma@vger.kernel.org>, <dri-devel@lists.freedesktop.org>,
	<nouveau@lists.freedesktop.org>, <linux-kernel@vger.kernel.org>,
	"Yonatan Maman" <Ymaman@Nvidia.com>,
	Gal Shalom <GalShalom@Nvidia.com>
Subject: [PATCH v2 1/5] mm/hmm: HMM API to enable P2P DMA for device private pages
Date: Fri, 18 Jul 2025 14:51:08 +0300	[thread overview]
Message-ID: <20250718115112.3881129-2-ymaman@nvidia.com> (raw)
In-Reply-To: <20250718115112.3881129-1-ymaman@nvidia.com>

From: Yonatan Maman <Ymaman@Nvidia.com>

hmm_range_fault() by default triggered a page fault on device private
when HMM_PFN_REQ_FAULT flag was set. pages, migrating them to RAM. In some
cases, such as with RDMA devices, the migration overhead between the
device (e.g., GPU) and the CPU, and vice-versa, significantly degrades
performance. Thus, enabling Peer-to-Peer (P2P) DMA access for device
private page might be crucial for minimizing data transfer overhead.

Introduced an API to support P2P DMA for device private pages,includes:
 - Leveraging the struct pagemap_ops for P2P Page Callbacks. This callback
   involves mapping the page for P2P DMA and returning the corresponding
   PCI_P2P page.

 - Utilizing hmm_range_fault for initializing P2P DMA. The API
   also adds the HMM_PFN_REQ_TRY_P2P flag option for the
   hmm_range_fault caller to initialize P2P. If set, hmm_range_fault
   attempts initializing the P2P connection first, if the owner device
   supports P2P, using p2p_page. In case of failure or lack of support,
   hmm_range_fault will continue with the regular flow of migrating the
   page to RAM.

This change does not affect previous use-cases of hmm_range_fault,
because both the caller and the page owner must explicitly request and
support it to initialize P2P connection.

Signed-off-by: Yonatan Maman <Ymaman@Nvidia.com>
Signed-off-by: Gal Shalom <GalShalom@Nvidia.com>
---
 include/linux/hmm.h      |  2 ++
 include/linux/memremap.h |  8 ++++++
 mm/hmm.c                 | 57 +++++++++++++++++++++++++++++++---------
 3 files changed, 55 insertions(+), 12 deletions(-)

diff --git a/include/linux/hmm.h b/include/linux/hmm.h
index db75ffc949a7..988c98c0edcc 100644
--- a/include/linux/hmm.h
+++ b/include/linux/hmm.h
@@ -27,6 +27,7 @@ struct mmu_interval_notifier;
  * HMM_PFN_P2PDMA_BUS - Bus mapped P2P transfer
  * HMM_PFN_DMA_MAPPED - Flag preserved on input-to-output transformation
  *                      to mark that page is already DMA mapped
+ * HMM_PFN_ALLOW_P2P - Allow returning PCI P2PDMA page
  *
  * On input:
  * 0                 - Return the current state of the page, do not fault it.
@@ -47,6 +48,7 @@ enum hmm_pfn_flags {
 	HMM_PFN_DMA_MAPPED = 1UL << (BITS_PER_LONG - 4),
 	HMM_PFN_P2PDMA     = 1UL << (BITS_PER_LONG - 5),
 	HMM_PFN_P2PDMA_BUS = 1UL << (BITS_PER_LONG - 6),
+	HMM_PFN_ALLOW_P2P = 1UL << (BITS_PER_LONG - 7),
 
 	HMM_PFN_ORDER_SHIFT = (BITS_PER_LONG - 11),
 
diff --git a/include/linux/memremap.h b/include/linux/memremap.h
index 4aa151914eab..79becc37df00 100644
--- a/include/linux/memremap.h
+++ b/include/linux/memremap.h
@@ -89,6 +89,14 @@ struct dev_pagemap_ops {
 	 */
 	vm_fault_t (*migrate_to_ram)(struct vm_fault *vmf);
 
+	/*
+	 * Used for private (un-addressable) device memory only. Return a
+	 * corresponding PFN for a page that can be mapped to device
+	 * (e.g using dma_map_page)
+	 */
+	int (*get_dma_pfn_for_device)(struct page *private_page,
+				      unsigned long *dma_pfn);
+
 	/*
 	 * Handle the memory failure happens on a range of pfns.  Notify the
 	 * processes who are using these pfns, and try to recover the data on
diff --git a/mm/hmm.c b/mm/hmm.c
index feac86196a65..089e522b346b 100644
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -232,6 +232,49 @@ static inline unsigned long pte_to_hmm_pfn_flags(struct hmm_range *range,
 	return pte_write(pte) ? (HMM_PFN_VALID | HMM_PFN_WRITE) : HMM_PFN_VALID;
 }
 
+static bool hmm_handle_device_private(struct hmm_range *range,
+				      unsigned long pfn_req_flags,
+				      swp_entry_t entry,
+				      unsigned long *hmm_pfn)
+{
+	struct page *page = pfn_swap_entry_to_page(entry);
+	struct dev_pagemap *pgmap = page_pgmap(page);
+	int ret;
+
+	pfn_req_flags &= range->pfn_flags_mask;
+	pfn_req_flags |= range->default_flags;
+
+	/*
+	 * Don't fault in device private pages owned by the caller,
+	 * just report the PFN.
+	 */
+	if (pgmap->owner == range->dev_private_owner) {
+		*hmm_pfn = swp_offset_pfn(entry);
+		goto found;
+	}
+
+	/*
+	 * P2P for supported pages, and according to caller request
+	 * translate the private page to the match P2P page if it fails
+	 * continue with the regular flow
+	 */
+	if (pfn_req_flags & HMM_PFN_ALLOW_P2P &&
+	    pgmap->ops->get_dma_pfn_for_device) {
+		ret = pgmap->ops->get_dma_pfn_for_device(page, hmm_pfn);
+		if (!ret)
+			goto found;
+
+	}
+
+	return false;
+
+found:
+	*hmm_pfn |= HMM_PFN_VALID;
+	if (is_writable_device_private_entry(entry))
+		*hmm_pfn |= HMM_PFN_WRITE;
+	return true;
+}
+
 static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
 			      unsigned long end, pmd_t *pmdp, pte_t *ptep,
 			      unsigned long *hmm_pfn)
@@ -255,19 +298,9 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
 	if (!pte_present(pte)) {
 		swp_entry_t entry = pte_to_swp_entry(pte);
 
-		/*
-		 * Don't fault in device private pages owned by the caller,
-		 * just report the PFN.
-		 */
 		if (is_device_private_entry(entry) &&
-		    page_pgmap(pfn_swap_entry_to_page(entry))->owner ==
-		    range->dev_private_owner) {
-			cpu_flags = HMM_PFN_VALID;
-			if (is_writable_device_private_entry(entry))
-				cpu_flags |= HMM_PFN_WRITE;
-			new_pfn_flags = swp_offset_pfn(entry) | cpu_flags;
-			goto out;
-		}
+		    hmm_handle_device_private(range, pfn_req_flags, entry, hmm_pfn))
+			return 0;
 
 		required_fault =
 			hmm_pte_need_fault(hmm_vma_walk, pfn_req_flags, 0);
-- 
2.34.1



  reply	other threads:[~2025-07-18 11:52 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-18 11:51 [PATCH v2 0/5] *** GPU Direct RDMA (P2P DMA) for Device Private Pages *** Yonatan Maman
2025-07-18 11:51 ` Yonatan Maman [this message]
2025-07-18 14:17   ` [PATCH v2 1/5] mm/hmm: HMM API to enable P2P DMA for device private pages Matthew Wilcox
2025-07-18 14:44     ` Jason Gunthorpe
2025-07-21  0:11       ` Alistair Popple
2025-07-21 13:23       ` Matthew Wilcox
2025-07-22  0:49         ` Alistair Popple
2025-07-23  3:51           ` Jason Gunthorpe
2025-07-23  4:10             ` Alistair Popple
2025-07-24  8:52               ` David Hildenbrand
2025-07-25  0:31                 ` Alistair Popple
2025-07-25  9:51                   ` David Hildenbrand
2025-08-01 16:40                   ` Jason Gunthorpe
2025-08-01 16:50                     ` David Hildenbrand
2025-08-01 16:57                       ` Jason Gunthorpe
2025-08-04  1:51                         ` Alistair Popple
2025-08-05 14:09                           ` Jason Gunthorpe
2025-08-04  7:48                         ` David Hildenbrand
2025-07-21  6:59   ` Christoph Hellwig
2025-07-22  5:42     ` Yonatan Maman
2025-08-01 16:52     ` Jason Gunthorpe
2025-07-18 11:51 ` [PATCH v2 2/5] nouveau/dmem: HMM P2P DMA for private dev pages Yonatan Maman
2025-07-21  7:00   ` Christoph Hellwig
2025-07-22  5:23     ` Yonatan Maman
2025-07-18 11:51 ` [PATCH v2 3/5] IB/core: P2P DMA for device private pages Yonatan Maman
2025-07-18 11:51 ` [PATCH v2 4/5] RDMA/mlx5: Enable P2P DMA with fallback mechanism Yonatan Maman
2025-07-21  7:03   ` Christoph Hellwig
2025-07-23  3:55     ` Jason Gunthorpe
2025-07-24  7:30       ` Christoph Hellwig
2025-08-01 16:46         ` Jason Gunthorpe
2025-07-18 11:51 ` [PATCH v2 5/5] RDMA/mlx5: Enabling ATS for ODP memory Yonatan Maman
2025-07-20 10:30 ` [PATCH v2 0/5] *** GPU Direct RDMA (P2P DMA) for Device Private Pages *** Leon Romanovsky
2025-07-20 21:03   ` Yonatan Maman
2025-07-21  6:49     ` Leon Romanovsky
2025-07-23  4:03       ` Jason Gunthorpe
2025-07-23  8:44         ` Leon Romanovsky
2025-07-21  6:54 ` Christoph Hellwig

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=20250718115112.3881129-2-ymaman@nvidia.com \
    --to=ymaman@nvidia.com \
    --cc=GalShalom@Nvidia.com \
    --cc=airlied@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=apopple@nvidia.com \
    --cc=bskeggs@nvidia.com \
    --cc=dakr@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=dskmtsd@gmail.com \
    --cc=jgg@ziepe.ca \
    --cc=jglisse@redhat.com \
    --cc=leon@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=lyude@redhat.com \
    --cc=michaelgur@nvidia.com \
    --cc=nouveau@lists.freedesktop.org \
    --cc=ohartoov@nvidia.com \
    --cc=shayd@nvidia.com \
    --cc=simona@ffwll.ch \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox