[PATCH v4 12/13] mm/hmm: Add flag to track device private pages

Jordan Niethe
2026-01-30T10:53:00Z

address space. This will mean that device private pages no longer have
normal pfns and must be handled separately.

Prepare for this by adding a HMM_PFN_DEVICE_PRIVATE flag to indicate
that a hmm_pfn contains a PFN for a device private page.

Signed-off-by: Jordan Niethe <jniethe@nvidia.com>
Signed-off-by: Alistair Popple <apopple@nvidia.com>

---
v1:
- Update HMM_PFN_ORDER_SHIFT
- Handle hmm_vma_handle_absent_pmd()
v2:
- No change
v3:
- No change
---
include/linux/hmm.h | 4 +++-
mm/hmm.c | 5 +++--
2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/include/linux/hmm.h b/include/linux/hmm.h
index db75ffc949a7..d8756c341620 100644
--- a/include/linux/hmm.h
+++ b/include/linux/hmm.h
@@ -23,6 +23,7 @@ struct mmu_interval_notifier;
* HMM_PFN_WRITE - if the page memory can be written to (requires HMM_PFN_VALID)
* HMM_PFN_ERROR - accessing the pfn is impossible and the device should
* fail. ie poisoned memory, special pages, no vma, etc
+ * HMM_PFN_DEVICE_PRIVATE - the pfn field contains a DEVICE_PRIVATE pfn.
* HMM_PFN_P2PDMA - P2P page
* HMM_PFN_P2PDMA_BUS - Bus mapped P2P transfer
* HMM_PFN_DMA_MAPPED - Flag preserved on input-to-output transformation
@@ -40,6 +41,7 @@ enum hmm_pfn_flags {
HMM_PFN_VALID = 1UL << (BITS_PER_LONG - 1),
HMM_PFN_WRITE = 1UL << (BITS_PER_LONG - 2),
HMM_PFN_ERROR = 1UL << (BITS_PER_LONG - 3),
+ HMM_PFN_DEVICE_PRIVATE = 1UL << (BITS_PER_LONG - 7),
/*
* Sticky flags, carried from input to output,
* don't forget to update HMM_PFN_INOUT_FLAGS
@@ -48,7 +50,7 @@ enum hmm_pfn_flags {
HMM_PFN_P2PDMA = 1UL << (BITS_PER_LONG - 5),
HMM_PFN_P2PDMA_BUS = 1UL << (BITS_PER_LONG - 6),

- HMM_PFN_ORDER_SHIFT = (BITS_PER_LONG - 11),
+ HMM_PFN_ORDER_SHIFT = (BITS_PER_LONG - 12),

/* Input flags */
HMM_PFN_REQ_FAULT = HMM_PFN_VALID,
diff --git a/mm/hmm.c b/mm/hmm.c
index 4ec74c18bef6..14895fa6575f 100644
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -267,7 +267,7 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
if (softleaf_is_device_private(entry) &&
page_pgmap(softleaf_to_page(entry))->owner ==
range->dev_private_owner) {
- cpu_flags = HMM_PFN_VALID;
+ cpu_flags = HMM_PFN_VALID | HMM_PFN_DEVICE_PRIVATE;
if (softleaf_is_device_private_write(entry))
cpu_flags |= HMM_PFN_WRITE;
new_pfn_flags = softleaf_to_pfn(entry) | cpu_flags;
@@ -347,7 +347,8 @@ static int hmm_vma_handle_absent_pmd(struct mm_walk *walk, unsigned long start,
softleaf_to_folio(entry)->pgmap->owner ==
range->dev_private_owner) {
unsigned long cpu_flags = HMM_PFN_VALID |
- hmm_pfn_flags_order(PMD_SHIFT - PAGE_SHIFT);
+ hmm_pfn_flags_order(PMD_SHIFT - PAGE_SHIFT) |
+ HMM_PFN_DEVICE_PRIVATE;
unsigned long pfn = softleaf_to_pfn(entry);
unsigned long i;

--
2.34.1