* [PATCH] unify pfn_to_page take 2 [1/25] generic funcs
@ 2006-02-08 5:41 KAMEZAWA Hiroyuki
2006-02-08 7:00 ` Kyle McMartin
0 siblings, 1 reply; 3+ messages in thread
From: KAMEZAWA Hiroyuki @ 2006-02-08 5:41 UTC (permalink / raw)
To: Linux Kernel Mailing List
Definitions of pfn_to_page/page_to_pfn are defined in each arch's include files.
But most of them just do the same thing.
This patch consolidates all definitions to generic one.
Changelog: v1->v2
- linux/memory_model.h is added. this defines pfn<->page translation.
- new config options (set by arch) CONFIG_DONT_INLINE_PFN_TO_PAGE
and CONFIG_ARCH_HAS_PFN_TO_PAGE are added.
- SPARSEMEM's page_to_pfn is moved to linux/memory_model.h
-- Kame.
This patch adds generci pfn_to_page/page_to_pfn definition.
Now, each arch has its own page_to_pfn/pfn_to_page. But most of them
do the same arithmatic. And I think this arithmatic is defined by memory model,
not by architecture.
3 types of arithmatic is defined in linux/memory_model.h.
New configs are added.
CONFIG_ARCH_HASH_PFN_TO_PAGE ..... for arch which uses *unusual* memory model.
(see m68k..)
CONFIG_DONT_INLINE_PFN_TO_PAGE ... for achh which doesn't want to make these
funcs inlined. (for sparc64, x86_64, maybe
making good result for some other archs.)
Helper macro ARCH_PFN_OFFSET, arch_pfn_to_nid, arch_local_pfn_offset()
are also added.
Signed-Off-BY: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Index: test-layout-free-zone/include/linux/memory_model.h
===================================================================
--- /dev/null
+++ test-layout-free-zone/include/linux/memory_model.h
@@ -0,0 +1,88 @@
+#ifndef __LINUX_MEMORY_MODEL_H
+#define __LINUX_MEMORY_MODEL_H
+/*
+ * pfn <-> page struct arithmatic for each memory model.
+ *
+ * 3 memory models are supported.
+ *
+ * FLATMEM -- pfn = (page - mem_map) + offset
+ * page struct is contigous to max_pfn.
+ * DISCONTIGMEM -- pfn = (page - node->node_mem_map) + node->node_start_pfn.
+ * page struct is contigous within each node.
+ * SPARSEMEM -- pfn = pfn_to_section(page_to_section(page)) + offset in section.
+ * page struct is contigous in each section.
+ */
+
+#ifndef CONFIG_ARCH_HAS_PFN_TO_PAGE
+/*
+ * some arch defines helper macro if necessary.
+ */
+/* used by FLATMEM */
+#ifndef ARCH_PFN_OFFSET
+#define ARCH_PFN_OFFSET (0UL)
+#endif
+
+/* used by DISCONTIGMEM */
+#ifndef arch_pfn_to_nid
+#define arch_pfn_to_nid(pfn) pfn_to_nid((pfn))
+#endif
+
+#ifndef arch_local_pfn_offset
+#define arch_local_pfn_offset(pfn, nid) ((pfn) - NODE_DATA((nid))->node_start_pfn)
+#endif
+
+#ifdef CONFIG_DONT_INLINE_PFN_TO_PAGE
+
+/* not-inlined version for some archs. funcs are defined in mm/page_alloc.c */
+extern unsigned long page_to_pfn(struct page *page);
+extern struct page *pfn_to_page(unsigned long pfn);
+
+#else
+
+#if defined(CONFIG_FLATMEM)
+
+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);
+}
+
+#elif defined(CONFIG_DISCONTIGMEM)
+
+static inline unsigned long page_to_pfn(struct page *page)
+{
+ struct zone *z = page_zone(page)
+ return (unsigned long)(page - z->zone_mem_map) + z->zone_start_pfn;
+}
+
+static inline struct page *pfn_to_page(unsigned long pfn)
+{
+ int nid = arch_pfn_to_nid(pfn);
+ struct pglist_data *pgdat = NODE_DATA(nid);
+ return pgdat->node_mem_map + arch_local_pfn_offset(pfn, nid);
+}
+
+#elif defined(CONFIG_SPARSEMEM)
+
+static inline unsigned long page_to_pfn(struct page *page)
+{
+ long section_id = page_to_section(page);
+ return page - __section_mem_map_addr(__nr_to_section(section_id));
+}
+
+static inline struct page * pfn_to_page(unsigned long pfn)
+{
+ return __section_mem_map_addr(__pfn_to_section(pfn)) + pfn;
+}
+
+#endif /* CONFIG_FLATMEM/DISCONTIGMEM/SPARSEMEM */
+
+#endif /* CONFIG_DONT_INLINE_PFN_TO_PAGE */
+
+#endif /* CONFIG_ARCH_HAS_PFN_TO_PAGE */
+
+#endif /* __LINUX_MEMORY_MODEL_H */
Index: test-layout-free-zone/include/linux/mmzone.h
===================================================================
--- test-layout-free-zone.orig/include/linux/mmzone.h
+++ test-layout-free-zone/include/linux/mmzone.h
@@ -602,16 +602,6 @@ static inline struct mem_section *__pfn_
return __nr_to_section(pfn_to_section_nr(pfn));
}
-#define pfn_to_page(pfn) \
-({ \
- unsigned long __pfn = (pfn); \
- __section_mem_map_addr(__pfn_to_section(__pfn)) + __pfn; \
-})
-#define page_to_pfn(page) \
-({ \
- page - __section_mem_map_addr(__nr_to_section( \
- page_to_section(page))); \
-})
static inline int pfn_valid(unsigned long pfn)
{
Index: test-layout-free-zone/mm/page_alloc.c
===================================================================
--- test-layout-free-zone.orig/mm/page_alloc.c
+++ test-layout-free-zone/mm/page_alloc.c
@@ -85,6 +85,55 @@ int min_free_kbytes = 1024;
unsigned long __initdata nr_kernel_pages;
unsigned long __initdata nr_all_pages;
+/*
+ * page <-> pfn translation, not-inlined ver. (see linux/memory_model.h)
+ */
+#ifdef CONFIG_DONT_INLINE_PFN_TO_PAGE
+#if defined(CONFIG_FLATMEM)
+
+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);
+}
+
+#elif defined (CONFIG_DISCONTIGMEM)
+
+unsigned long page_to_pfn(struct page *page)
+{
+ struct zone *z = page_zone(page)
+ return (unsigned long)(page - z->zone_mem_map) + z->zone_start_pfn;
+}
+
+struct page *pfn_to_page(unsigned long pfn)
+{
+ int nid = arch_pfn_to_nid(pfn);
+ struct pglist_data *pgdat = NODE_DATA(nid);
+ return pgdat->node_mem_map + arch_local_pfn_offset(pfn, nid);
+}
+
+#elif defined (CONFIG_SPARSEMEM)
+
+static inline unsigned long page_to_pfn(struct page *page)
+{
+ long section_id = page_to_section(page);
+ return page - __section_mem_map_addr(__nr_to_section(section_id));
+}
+
+static inline struct page * pfn_to_page(unsigned long pfn)
+{
+ return __section_mem_map_addr(__pfn_to_section(pfn)) + pfn;
+}
+#endif
+
+EXPORT_SYMBOL(pfn_to_page);
+EXPORT_SYMBOL(page_to_pfn);
+#endif
+
#ifdef CONFIG_DEBUG_VM
static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
{
Index: test-layout-free-zone/include/linux/mm.h
===================================================================
--- test-layout-free-zone.orig/include/linux/mm.h
+++ test-layout-free-zone/include/linux/mm.h
@@ -512,6 +512,9 @@ static inline void set_page_links(struct
extern struct page *mem_map;
#endif
+/* include pfn <-> page struct arithmatic for each memory model */
+#include <linux/memory_model.h>
+
static __always_inline void *lowmem_page_address(struct page *page)
{
return __va(page_to_pfn(page) << PAGE_SHIFT);
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] unify pfn_to_page take 2 [1/25] generic funcs
2006-02-08 5:41 [PATCH] unify pfn_to_page take 2 [1/25] generic funcs KAMEZAWA Hiroyuki
@ 2006-02-08 7:00 ` Kyle McMartin
2006-02-08 7:20 ` KAMEZAWA Hiroyuki
0 siblings, 1 reply; 3+ messages in thread
From: Kyle McMartin @ 2006-02-08 7:00 UTC (permalink / raw)
To: KAMEZAWA Hiroyuki; +Cc: Linux Kernel Mailing List
On Wed, Feb 08, 2006 at 02:41:22PM +0900, KAMEZAWA Hiroyuki wrote:
> +#ifndef CONFIG_ARCH_HAS_PFN_TO_PAGE
> +/*
Since this file is entirely conditionalized on ARCH_HAS_PFN_TO_PAGE,
might it be better to put this in asm-generic/ and include it from
an asm- header instead of adding yet another ARCH_HAS_ define?
This way, m68k (iirc?) could just not include that header, and not
worry about this define.
Then again, adding the include to every arches headers likely offsets
some of the C code reduction. However, it's still a win on the unified
definition and long term maintainability angle. Perhaps someone more
authoritative than little old me, could cast judgement on this.
> [...]
> +#ifdef CONFIG_DONT_INLINE_PFN_TO_PAGE
> +
> +/* not-inlined version for some archs. funcs are defined in
> mm/page_alloc.c */
> +extern unsigned long page_to_pfn(struct page *page);
> +extern struct page *pfn_to_page(unsigned long pfn);
> +
> +#else
> +
Commenting this #else might improve readability.
Cheers!
Kyle
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] unify pfn_to_page take 2 [1/25] generic funcs
2006-02-08 7:00 ` Kyle McMartin
@ 2006-02-08 7:20 ` KAMEZAWA Hiroyuki
0 siblings, 0 replies; 3+ messages in thread
From: KAMEZAWA Hiroyuki @ 2006-02-08 7:20 UTC (permalink / raw)
To: Kyle McMartin; +Cc: Linux Kernel Mailing List
Kyle McMartin wrote:
> On Wed, Feb 08, 2006 at 02:41:22PM +0900, KAMEZAWA Hiroyuki wrote:
>> +#ifndef CONFIG_ARCH_HAS_PFN_TO_PAGE
>> +/*
>
> Since this file is entirely conditionalized on ARCH_HAS_PFN_TO_PAGE,
> might it be better to put this in asm-generic/ and include it from
> an asm- header instead of adding yet another ARCH_HAS_ define?
>
> This way, m68k (iirc?) could just not include that header, and not
> worry about this define.
>
> Then again, adding the include to every arches headers likely offsets
> some of the C code reduction. However, it's still a win on the unified
> definition and long term maintainability angle. Perhaps someone more
> authoritative than little old me, could cast judgement on this.
>
I named the file as memory_model.h, so I placed it under linux/
But ,as you say, memory_model.h is entirely conditional on ARCH_HASH_PFN_TO_PAGE.
Can someone advise me ?
>> [...]
>> +#ifdef CONFIG_DONT_INLINE_PFN_TO_PAGE
>> +
>> +/* not-inlined version for some archs. funcs are defined in
>> mm/page_alloc.c */
>> +extern unsigned long page_to_pfn(struct page *page);
>> +extern struct page *pfn_to_page(unsigned long pfn);
>> +
>> +#else
>> +
>
> Commenting this #else might improve readability.
>
Ah, okay. thanks.
Regards,
-- Kame
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2006-02-08 7:19 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-08 5:41 [PATCH] unify pfn_to_page take 2 [1/25] generic funcs KAMEZAWA Hiroyuki
2006-02-08 7:00 ` Kyle McMartin
2006-02-08 7:20 ` KAMEZAWA Hiroyuki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox