Skip to contentSkip to conversation

pfn_valid() more generic : arch independent part[0/2]

RFC/PATCH Hiroyuki KAMEZAWA 2 participants 3 messages Oct 6, 2004 – Oct 7, 2004

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

This is generic parts.

Boot-time routine:
At first, information of valid pages is gathered into a list. After gathering all information, 2 level table are created. Why I create table instead of using a list is only for good cache hit.

pfn_valid_init() <- initilize some structures validate_pages(start,size) <- gather valid pfn information pfn_valid_setup() <- create 1st and 2nd table.

Kame <[email protected]>

---

 test-pfn-valid-kamezawa/include/linux/mm.h        |    2
 test-pfn-valid-kamezawa/include/linux/pfn_valid.h |   51 +++++
 test-pfn-valid-kamezawa/mm/page_alloc.c           |  191 ++++++++++++++++++++++
 3 files changed, 244 insertions(+)
include/linux/pfn_valid.h new file +51 -0
diff -puN /dev/null include/linux/pfn_valid.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_PFN_VALID_H
+#define _LINUX_PFN_VALID_H
+/*
+ * Implementing pfn_valid() for managing memory hole.
+ * this uses 2 level table.
+ * 1st table is accessed by index of (pfn >> PFN_VALID_MAPSHIFT).
+ * It has rough information and pointer to 2nd table.
+ * If rough information is enough, 2nd table is not accessed.
+ * 2nd table has (start_pfn, nr_pages) entry which are sorted by start_pfn.
+ */
+
+#ifdef CAREFUL_PFN_VALID
+/* for 2nd level */
+struct pfn_valid_info {
+	unsigned long start_pfn;
+	unsigned long end_pfn;   /* Caution:end_pfn is not included in
+                                    this valid pfn range */
+};
+/* for 1st level */
+typedef union {
+	unsigned short valid;    /* for fast checking. take 2 values */
+	unsigned short index;    /* index to table,start for searching */
+}pfn_validmap_t;
+
+#define PFN_ALL_INVALID 0xffff
+#define PFN_ALL_VALID   0xfffe
+#define pfn_all_valid(ent)   ((ent)->valid == PFN_ALL_VALID)
+#define pfn_all_invalid(ent) ((ent)->valid == PFN_ALL_INVALID)
+
+#ifndef PFN_VALID_MAPSHIFT
+#define PFN_VALID_MAPSHIFT 16
+#endif
+
+#define PFN_VALID_MAPSIZE   (1 << PFN_VALID_MAPSHIFT)
+#define PFN_VALID_MAPMASK   (~(PFN_VALID_MAPSIZE - 1))
+
+extern void __init validate_pages(unsigned long start_pfn,
+				  unsigned long nr_pages);
+extern void __init pfn_valid_init(void);
+extern void __init pfn_valid_setup(void);
+extern int careful_pfn_valid(unsigned long pfn);
+
+#else /* CAREFUL_PFN_VALID */
+
+#define pfn_valid_init() do {}while(0)
+#define validate_pages(a, b) do {}while(0)
+#define pfn_validmap_setup() do{} while(0)
+
+
+#endif /* CAREFUL_PFN_VALID */
+#endif
mm/page_alloc.c renamed from mm/page_alloc.c~careful_pfn_valid +191 -0

200 lines not on this page · raw message

include/linux/mm.h renamed from include/linux/mm.h~careful_pfn_valid +2 -0
diff -puN include/linux/mm.h~careful_pfn_valid include/linux/mm.h
@@ -41,6 +41,8 @@ extern int sysctl_legacy_va_layout;
 #define MM_VM_SIZE(mm)	TASK_SIZE
 #endif
 
+#include <linux/pfn_valid.h>
+
 /*
  * Linux kernel virtual memory manager primitives.
  * The idea being to have a "virtual" mm in the same way

_

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#1 lore raw
Quoted 10 lines

This is generic parts.

Boot-time routine:
At first, information of valid pages is gathered into a list. After gathering all information, 2 level table are created. Why I create table instead of using a list is only for good cache hit.

pfn_valid_init() <- initilize some structures validate_pages(start,size) <- gather valid pfn information pfn_valid_setup() <- create 1st and 2nd table.

Boggle. what on earth are you trying to do?

pfn_valid does exactly one thing - it checks whether there is a struct page for that pfn. Nothing else. Surely that can't possibly take a tenth of this amount of code?

M.

#2 lore raw
Quoted 7 lines · Martin J. Bligh
Quoted 7 lines

This is generic parts.

Boot-time routine:
At first, information of valid pages is gathered into a list. After gathering all information, 2 level table are created. Why I create table instead of using a list is only for good cache hit.

Quoted 8 lines
Quoted 3 lines

pfn_valid_init() <- initilize some structures validate_pages(start,size) <- gather valid pfn information pfn_valid_setup() <- create 1st and 2nd table.

Boggle. what on earth are you trying to do?

I just want to test whether a struct page for that pfn exists or not. ia64 has holes in memmap in a zone, so ia64_pfn_valid() uses get_user() to test whether a page struct exists or not.

In my no-bitmap buddy allocator, I must call pfn_valid() for ia64 at every loop in free_pages_bulk()(in mm/page_alloc.c).
Beacause of holes in memmap, bad_range()(in mm/page_alloc.c) cannot work enough.

code will be like this:

while(...) {
     pfn_of_buddy = some_func(pfn);
     if( bad_range(pfn_of_buddy) )
	       break;
     if( pfn_valid(pfn_of_buddy) )   <----- only for ia64.
                                            this will disappear in other archs.
	       break;
     ....
}

Because pfn_valid() often returns 0 in inner loop of free_pages_bulk(), I want to avoid page fault caused by using get_user() in pfn_valid().

I have 2 plan (1) modify pfn_valid or (2) modify bad_range(). this is plan(1).

In plan(2), 1st/2nd tables are attached to each zone/pgdat.

Quoted 5 lines

pfn_valid does exactly one thing - it checks whether there is a struct page for that pfn. Nothing else. Surely that can't possibly take a tenth of this amount of code?

M.

Kame <[email protected]>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>