[RFC][PATCH] unify pfn_to_page [1/25] generic page_to_pfn / pfn_to_page

From: KAMEZAWA Hiroyuki
Date: Mon Feb 06 2006 - 05:46:29 EST


3 memory models are now available, memmaps of 3 models are defined as

FLATMEM --- pfn = (page - mem_map) + offset
DISCONTIGMEM --- pfn = (page - page_node(page)->node_mem_map) +
(page_node(page)->node_start_pfn)
SPARSEMEM --- see linux/mmzone.h , generic ones are defined.

Now, each arch has its own page_to_pfn()/pfn_to_page() on FLATMEM/DISCONTIGIMEM.
But most of them keeps above assumptions and looks same to i386's ones.

This patch unifies each arch's page_to_pfn/pfn_to_page to generic ones.
This patch is against 2.6.16-rc2.

comments ?

-- Kame

This patch defines generic page_to_pfn()/pfn_to_page().
For DISCONTIGMEM, page_to_pfn/pfn_to_page are not inlined.
(x86_64 already has not-inlined version and it reduces text size.)

If FLATMEM and memmap <-> pfn translation needs offset,
ARCH_PFN_OFFSET is defined by each archs.

If DISCONTIGMEM , each arch defines arch_pfn_to_nid().
If necessary, arch_local_map_nr(pfn, nid) is also defined.
arch_local_map_nr() calculates page offset in a node.

Signed-Off-By: KAMEZAWA Hiruyoki <kamezawa.hiroyu@xxxxxxxxxxxxx>


Index: cleanup_pfn_page/include/linux/mm.h
===================================================================
--- cleanup_pfn_page.orig/include/linux/mm.h
+++ cleanup_pfn_page/include/linux/mm.h
@@ -512,6 +512,32 @@ static inline void set_page_links(struct
extern struct page *mem_map;
#endif

+#if !defined(ARCH_HAS_PFN_PAGE) && !defined(CONFIG_SPARSEMEM)
+#if CONFIG_FLATMEM
+
+#ifndef ARCH_PFN_OFFSET
+#define ARCH_PFN_OFFSET 0
+#endif
+static inline unsigned long page_to_pfn(struct page *page)
+{
+ return (unsigned long)(page - mem_map) + ARCH_PFN_OFFSET;
+}
+static inline struct page *pfn_to_page(unsigned long pfn)
+{
+ return mem_map + (pfn - ARCH_PFN_OFFSET);
+}
+#endif /* CONFIG_FLATMEM */
+#ifdef CONFIG_DISCONTIGMEM
+/* arch_pfn_to_nid/arch_local_map_nr is defined if necesary */
+#ifndef arch_local_map_nr
+#define arch_local_map_nr(pfn ,nid) ((pfn) - NODE_DATA(nid)->node_start_pfn)
+#endif
+extern unsigned long page_to_pfn(struct page *page);
+extern struct page* pfn_to_page(unsigned long pfn);
+#endif /* CONFIG_DISCONTIGMEM */
+
+#endif
+
static __always_inline void *lowmem_page_address(struct page *page)
{
return __va(page_to_pfn(page) << PAGE_SHIFT);
Index: cleanup_pfn_page/mm/page_alloc.c
===================================================================
--- cleanup_pfn_page.orig/mm/page_alloc.c
+++ cleanup_pfn_page/mm/page_alloc.c
@@ -85,6 +85,25 @@ int min_free_kbytes = 1024;
unsigned long __initdata nr_kernel_pages;
unsigned long __initdata nr_all_pages;

+#if defined(CONFIG_DISCONTIGMEM) && !defined(CONFIG_VIRTUAL_MEM_MAP)
+
+struct page *pfn_to_page(unsigned long pfn)
+{
+ struct pglist_data *pgdat;
+ int nid = arch_pfn_to_nid(pfn);
+ pgdat = NODE_DATA(nid);
+ return pgdat->node_mem_map + arch_local_map_nr(pfn, nid);
+}
+EXPORT_SYMBOL(pfn_to_page);
+
+unsigned long page_to_pfn(struct page *page)
+{
+ struct zone *z = page_zone(page);
+ return z->zone_start_pfn + (unsigned long)(page - z->zone_mem_map);
+}
+EXPORT_SYMBOL(page_to_pfn);
+#endif
+
#ifdef CONFIG_DEBUG_VM
static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
{


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/