pfn_valid() more generic : arch independent part[0/2]
Subsystems (3)
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
@@ -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
@@ -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>
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 structuresvalidate_pages(start,size)<- gather valid pfn informationpfn_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.
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 structuresvalidate_pages(start,size)<- gather valid pfn informationpfn_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_validdoes 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>