diff options
| author | Mostafa Saleh <smostafa@google.com> | 2026-01-20 09:19:25 +0000 |
|---|---|---|
| committer | Joerg Roedel <joerg.roedel@amd.com> | 2026-01-21 12:51:48 +0100 |
| commit | d414b83dc5f90a6a9a656cd6fbb9378ddc824032 (patch) | |
| tree | bafa8ac6600f082fd46beff9a54573e4c7ec2ba1 | |
| parent | 2e2f6b0ef8551bf3bd8255729d27e3ad9451e562 (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.h | 6 | ||||
| -rw-r--r-- | mm/page_ext.c | 23 |
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(). * |
