summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMostafa Saleh <smostafa@google.com>2026-01-20 09:19:25 +0000
committerJoerg Roedel <joerg.roedel@amd.com>2026-01-21 12:51:48 +0100
commitd414b83dc5f90a6a9a656cd6fbb9378ddc824032 (patch)
treebafa8ac6600f082fd46beff9a54573e4c7ec2ba1
parent2e2f6b0ef8551bf3bd8255729d27e3ad9451e562 (diff)
mm/page_ext: Add page_ext_get_from_phys()
The IOMMU code operates on physical addresses which can be outside of system RAM. Add a new function page_ext_get_from_phys() to abstract the logic of checking the address and returning the page_ext. Signed-off-by: Mostafa Saleh <smostafa@google.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
-rw-r--r--include/linux/page_ext.h6
-rw-r--r--mm/page_ext.c23
2 files changed, 29 insertions, 0 deletions
diff --git a/include/linux/page_ext.h b/include/linux/page_ext.h
index 76c817162d2f..61e876e255e8 100644
--- a/include/linux/page_ext.h
+++ b/include/linux/page_ext.h
@@ -93,6 +93,7 @@ static inline bool page_ext_iter_next_fast_possible(unsigned long next_pfn)
#endif
extern struct page_ext *page_ext_get(const struct page *page);
+extern struct page_ext *page_ext_from_phys(phys_addr_t phys);
extern void page_ext_put(struct page_ext *page_ext);
extern struct page_ext *page_ext_lookup(unsigned long pfn);
@@ -215,6 +216,11 @@ static inline struct page_ext *page_ext_get(const struct page *page)
return NULL;
}
+static inline struct page_ext *page_ext_from_phys(phys_addr_t phys)
+{
+ return NULL;
+}
+
static inline void page_ext_put(struct page_ext *page_ext)
{
}
diff --git a/mm/page_ext.c b/mm/page_ext.c
index 297e4cd8ce90..e2e92bd27ebd 100644
--- a/mm/page_ext.c
+++ b/mm/page_ext.c
@@ -539,6 +539,29 @@ struct page_ext *page_ext_get(const struct page *page)
}
/**
+ * page_ext_from_phys() - Get the page_ext structure for a physical address.
+ * @phys: The physical address to query.
+ *
+ * This function safely gets the `struct page_ext` associated with a given
+ * physical address. It performs validation to ensure the address corresponds
+ * to a valid, online struct page before attempting to access it.
+ * It returns NULL for MMIO, ZONE_DEVICE, holes and offline memory.
+ *
+ * Return: NULL if no page_ext exists for this physical address.
+ * Context: Any context. Caller may not sleep until they have called
+ * page_ext_put().
+ */
+struct page_ext *page_ext_from_phys(phys_addr_t phys)
+{
+ struct page *page = pfn_to_online_page(__phys_to_pfn(phys));
+
+ if (!page)
+ return NULL;
+
+ return page_ext_get(page);
+}
+
+/**
* page_ext_put() - Working with page extended information is done.
* @page_ext: Page extended information received from page_ext_get().
*