CONFIG_NONLINEAR for small systems
Subsystems (4)
Following this email will be a series of patches which provide a
sample implementation of a simplified CONFIG_NONLINEAR memory model. The first two cleanup general infrastructure to minimise code duplication. The third introduces an allocator for the numa remap space on i386. The fourth generalises the page flags code to allow the reuse of the NODEZONE bits. The final three are the actual meat of the implementation for both i386 and ppc64.
050-bootmem-use-NODE_DATA
060-refactor-setup_memory-i386
080-alloc_remap-i386
100-cleanup-node-zone
150-nonlinear
160-nonlinear-i386
170-nonlinear-ppc64
As has been observed the CONFIG_DISCONTIGMEM implementation is inefficient space-wise where a system has a sparse intra-node memory configuration. For example we have systems where node 0 has a 1GB hole within it. Under CONFIG_DISCONTIGMEM this results in the struct page's for this area being allocated from ZONE_NORMAL and never used; this is particularly problematic on these 32bit systems as we are already under severe pressure in this zone.
The generalised CONFIG_NONLINEAR memory model described at OLS seemed provide more than enough decriptive power to address this issue but provided far more functionality that was required. Particularly it breaks the identity V=P+c to allow compression of the kernel address space, which is not required on these smaller systems.
This patch set is implemented as a proof-of-concept to show that a simplified CONFIG_NONLINEAR based implementation could provide sufficient flexibility to solve the problems for these systems.
In the longer term I'd like to see a single CONFIG_NONLINEAR implementation which allowed these various features to be stacked in combination as required.
Thoughts?
-apw
--
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>
050 bootmem use NODE_DATA
Convert the default non-node based bootmem routines to use NODE_DATA(0). This is semantically and functionally identical in any non-node configuration as NODE_DATA(x) is defined as below.
#define NODE_DATA(nid) (&contig_page_data)
For the node cases (CONFIG_NUMA and CONFIG_DISCONTIG_MEM) we can use these non-node forms where all boot memory is defined on node 0.
Revision: $Rev$
diffstat 050-bootmem-use-NODE_DATA
--- bootmem.c | 10 ++++------ 1 files changed, 4 insertions(+), 6 deletions(-)
mm/bootmem.c +4 -6
@@ -343,31 +343,29 @@ unsigned long __init free_all_bootmem_noreturn (free_all_bootmem_core (pgdat)); } -#ifndef CONFIG_DISCONTIGMEM unsigned long __init init_bootmem (unsigned long start,unsigned long pages) { max_low_pfn = pages; min_low_pfn = start; -return (init_bootmem_core (&contig_page_data, start,0 , pages)); +return (init_bootmem_core (NODE_DATA (0 ), start,0 , pages)); }#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE void __init reserve_bootmem (unsigned long addr,unsigned long size) { -reserve_bootmem_core (contig_page_data.bdata, addr, size); +reserve_bootmem_core (NODE_DATA (0 )->bdata, addr, size); }#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ void __init free_bootmem (unsigned long addr,unsigned long size) { -free_bootmem_core (contig_page_data.bdata, addr, size); +free_bootmem_core (NODE_DATA (0 )->bdata, addr, size); }unsigned long __init free_all_bootmem (void ) { -return (free_all_bootmem_core (&contig_page_data)); +return (free_all_bootmem_core (NODE_DATA (0 ))); } -#endif /* !CONFIG_DISCONTIGMEM */ void *__init __alloc_bootmem (unsigned long size,unsigned long align,unsigned long goal) {
--
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>
Re: 050 bootmem use NODE_DATA
Quoted 8 lines · Andy Whitcroft
Convert the default non-node based bootmem routines to use
NODE_DATA(0). This is semantically and functionally identical in any non-node configuration asNODE_DATA(x)is defined as below.#define
NODE_DATA(nid)(&contig_page_data)For the node cases (
CONFIG_NUMAandCONFIG_DISCONTIG_MEM) we can use these non-node forms where all boot memory is defined on node 0.
Andy, this patch looks like good stuff, even outside of the context of nonlinear. Care to forward it on?
-- Dave
--
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>
060 refactor setup_memory i386
In reply to Andy WhitcroftRefactor the i386 default and CONFIG_DISCONTIG_MEM setup_memory() functions to share the common bootmem initialisation code. This code is intended to be identical, but there are currently some fixes applied to one and not the other. This patch extracts this common initialisation code.
Revision: $Rev$
diffstat 060-refactor-setup_memory-i386
--- kernel/setup.c | 25 ++++++------ mm/discontig.c | 117 +-------------------------------------------------------- 2 files changed, 18 insertions(+), 124 deletions(-)
arch/i386/kernel/setup.c +14 -11
@@ -941,8 +941,6 @@ unsigned long __init find_max_low_pfn(voreturn max_low_pfn; } -#ifndef CONFIG_DISCONTIGMEM -/* * Free all available memory for boot time allocation. Used * as a callback function by efi_memory_walk()
@@ -1016,15 +1014,15 @@ static void __init reserve_ebda_region(vreserve_bootmem (addr,PAGE_SIZE ); } +#ifndef CONFIG_DISCONTIGMEM +void __init setup_bootmem_allocator (void );static unsigned long __init setup_memory (void ) { -unsigned long bootmap_size, start_pfn, max_low_pfn; -/* * partially used pages are not usable - thus * we are rounding upwards: */ - start_pfn =PFN_UP (init_pg_tables_end); + min_low_pfn =PFN_UP (init_pg_tables_end);find_max_pfn ();
@@ -1040,10 +1038,19 @@ static unsigned long __init setup_memory#endif printk (KERN_NOTICE "%ldMB LOWMEM available.\n" ,pages_to_mb (max_low_pfn)); + +setup_bootmem_allocator (); + return max_low_pfn; +} +#endif /* !CONFIG_DISCONTIGMEM */ + +void __init setup_bootmem_allocator (void ) +{ +unsigned long bootmap_size;/* * Initialize the boot-time allocator (with low memory only): */ - bootmap_size =init_bootmem (start_pfn, max_low_pfn); + bootmap_size =init_bootmem (min_low_pfn, max_low_pfn);register_bootmem_low_pages (max_low_pfn);
@@ -1053,7 +1060,7 @@ static unsigned long __init setup_memory* the (very unlikely) case of us accidentally initializing the * bootmem allocator with an invalid RAM area. */ -reserve_bootmem (HIGH_MEMORY , (PFN_PHYS (start_pfn) + +reserve_bootmem (HIGH_MEMORY , (PFN_PHYS (min_low_pfn) + bootmap_size +PAGE_SIZE -1 ) - (HIGH_MEMORY ));/*
@@ -1110,11 +1117,7 @@ static unsigned long __init setup_memory } }#endif -return max_low_pfn; } -#else -extern unsigned long setup_memory (void ); -#endif /* !CONFIG_DISCONTIGMEM */ /* * Request address space for all standard RAM and ROM resources
arch/i386/mm/discontig.c +4 -113
139 lines not on this page · raw message
--
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>
080 alloc_remap i386
In reply to Andy WhitcroftIntroduce a new allocator for the NUMA the scares remap space.
Revision: $Rev$
diffstat 080-alloc_remap-i386
--- arch/i386/mm/discontig.c | 55 ++++++++++++++++++++++++++++++++++++++++------ include/asm-i386/mmzone.h | 2 + mm/page_alloc.c | 35 ++++++++++++++++++++++++++--- 3 files changed, 83 insertions(+), 9 deletions(-)
arch/i386/mm/discontig.c +49 -6
@@ -81,6 +81,9 @@ unsigned long node_remap_offset[MAX_NUMNvoid *node_remap_start_vaddr[MAX_NUMNODES ];void set_pmd_pfn (unsigned long vaddr,unsigned long pfn,pgprot_t flags); +void *node_remap_end_vaddr[MAX_NUMNODES ]; +void *node_remap_alloc_vaddr[MAX_NUMNODES ]; +/* * FLAT - support for basic PC memory model with discontig enabled, essentially * a single node with all available processors in it with a flat
@@ -136,13 +139,36 @@ static void __init allocate_pgdat(int ni } } +void *alloc_remap (int nid,unsigned long size) +{ +void *allocation = node_remap_alloc_vaddr[nid]; + +printk (KERN_WARNING "APW: alloc_remap(%d, %08lx)\n" , nid, size); + + size =ALIGN (size,L1_CACHE_BYTES ); + +if (!allocation) +return 0 ; +if ((allocation + size) >= node_remap_end_vaddr[nid]) +return 0 ; + + node_remap_alloc_vaddr[nid] += size; + +memset (allocation,0 , size); + +printk (KERN_WARNING "APW: alloc_remap(%d, %08lx) = %p\n" , nid, size, + allocation); + +return allocation; +} +void __init remap_numa_kva (void ) {void *vaddr;unsigned long pfn;int node; -for (node =1 ; node < numnodes; ++node) { +for (node =0 ; node < numnodes; ++node) {for (pfn=0 ; pfn < node_remap_size[node]; pfn +=PTRS_PER_PTE ) { vaddr = node_remap_start_vaddr[node]+(pfn<<PAGE_SHIFT ); set_pmd_pfn((ulong) vaddr,
@@ -152,15 +178,21 @@ void __init remap_numa_kva(void) } } +/* APW/XXX: not here .. */ +unsigned long zone_bitmap_calculate (unsigned long nr_pages);static unsigned long calculate_numa_remap_pages (void ) {int nid;unsigned long size, reserve_pages =0 ; -for (nid =1 ; nid < numnodes; nid++) { +for (nid =0 ; nid < numnodes; nid++) {/* calculate the size of the mem_map needed in bytes */ size = (node_end_pfn[nid] - node_start_pfn[nid] +1 ) *sizeof (struct page ) +sizeof (pg_data_t); + +/* Allow for the bitmaps. */ + size +=zone_bitmap_calculate (node_end_pfn[nid] - node_start_pfn[nid] +1 ); +/* convert size to large (pmd size) pages, rounding up */ size = (size +LARGE_PAGE_BYTES -1 ) /LARGE_PAGE_BYTES ;/* now the roundup is correct, convert to PAGE_SIZE pages */
@@ -168,8 +200,8 @@ static unsigned long calculate_numa_remaprintk ("Reserving %ld pages of KVA for lmem_map of node %d\n" , size, nid); node_remap_size[nid] = size; - reserve_pages += size; node_remap_offset[nid] = reserve_pages; + reserve_pages += size;printk ("Shrinking node %d from %ld pages to %ld pages\n" , nid, node_end_pfn[nid], node_end_pfn[nid] - size); node_end_pfn[nid] -= size;
@@ -236,12 +268,18 @@ unsigned long __init setup_memory(void) (ulong) pfn_to_kaddr(max_low_pfn));for (nid =0 ; nid < numnodes; nid++) { node_remap_start_vaddr[nid] =pfn_to_kaddr ( - (highstart_pfn + reserve_pages) - node_remap_offset[nid]); + highstart_pfn + node_remap_offset[nid]); +/* Init the node remap allocator */ + node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] + + (node_remap_size[nid] *PAGE_SIZE ); + node_remap_alloc_vaddr[nid] = node_remap_start_vaddr[nid] + +ALIGN (sizeof (pg_data_t),PAGE_SIZE ); +allocate_pgdat (nid);printk ("node %d will remap to vaddr %08lx - %08lx\n" , nid, (ulong ) node_remap_start_vaddr[nid], - (ulong )pfn_to_kaddr (highstart_pfn + reserve_pages - - node_remap_offset[nid] + node_remap_size[nid])); + (ulong )pfn_to_kaddr (highstart_pfn + + node_remap_offset[nid] + node_remap_size[nid])); }printk ("High memory starts at vaddr %08lx\n" , (ulong )pfn_to_kaddr (highstart_pfn));
@@ -307,6 +345,10 @@ void __init zone_sizes_init(void)* normal bootmem allocator, but other nodes come from the * remapped KVA area - mbligh */ +free_area_init_node (nid,NODE_DATA (nid), + zones_size, start, zholes_size); + +#if 0 if (!nid)free_area_init_node (nid,NODE_DATA (nid), zones_size, start, zholes_size);
@@ -319,6 +361,7 @@ void __init zone_sizes_init(void)free_area_init_node (nid,NODE_DATA (nid), zones_size, start, zholes_size); } +#endif }return ; }
include/asm-i386/mmzone.h +2 -0
@@ -16,6 +16,8 @@#else /* summit or generic arch */ #include <asm/srat.h> #endif +#define HAVE_ARCH_ALLOC_REMAP 1 +#else /* !CONFIG_NUMA */ #define get_memcfg_numa get_memcfg_numa_flat#define get_zholes_size (n) (0)
mm/page_alloc.c +32 -3
@@ -94,6 +94,9 @@ static void bad_page(const char *functio page->mapping =NULL ; } +/* APW/XXX: not here. */ +void *alloc_remap (int nid,unsigned long size); +#ifndef CONFIG_HUGETLB_PAGE #define prep_compound_page (page, order) do { } while (0)#define destroy_compound_page (page, order) do { } while (0)
@@ -1442,11 +1445,23 @@ unsigned long pages_to_bitmap_size(unsigreturn bitmap_size; } +unsigned long zone_bitmap_calculate (unsigned long nr_pages) +{ +unsigned long overall_size =0 ; +int order; + +for (order =0 ; order <MAX_ORDER -1 ; order++) + overall_size +=pages_to_bitmap_size (order, nr_pages); + +return overall_size; +} +void zone_init_free_lists (struct pglist_data *pgdat,struct zone *zone,unsigned long size) {int order;for (order =0 ; ; order++) {unsigned long bitmap_size; +unsigned long *map;INIT_LIST_HEAD (&zone->free_area[order].free_list);if (order ==MAX_ORDER -1 ) {
@@ -1455,8 +1470,15 @@ void zone_init_free_lists(struct pglist_ } bitmap_size =pages_to_bitmap_size (order, size); - zone->free_area[order].map = - (unsigned long *)alloc_bootmem_node (pgdat, bitmap_size); + +#ifdef HAVE_ARCH_ALLOC_REMAP + map = (unsigned long *)alloc_remap (pgdat->node_id, + bitmap_size); + if (!map) +#endif + map = (unsigned long *)alloc_bootmem_node (pgdat, + bitmap_size); + zone->free_area[order].map = map; } }
@@ -1581,9 +1603,16 @@ static void __init free_area_init_core(svoid __init node_alloc_mem_map (struct pglist_data *pgdat) {unsigned long size; +void *map; size = (pgdat->node_spanned_pages +1 ) *sizeof (struct page ); - pgdat->node_mem_map =alloc_bootmem_node (pgdat, size); + +#ifdef HAVE_ARCH_ALLOC_REMAP + map = (unsigned long *)alloc_remap (pgdat->node_id, size); + if (!map) +#endif + map =alloc_bootmem_node (pgdat, size); + pgdat->node_mem_map = map;#ifndef CONFIG_DISCONTIGMEM mem_map = contig_page_data.node_mem_map;#endif
--
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>
100 cleanup node zone
In reply to Andy Whitcroftdiffstat 100-cleanup-node-zone
--- mm.h | 43 ++++++++++++++++++++++++++++++++++++------- mmzone.h | 16 +++------------- 2 files changed, 39 insertions(+), 20 deletions(-)
include/linux/mm.h +36 -7
@@ -376,16 +376,41 @@ static inline void put_page(struct page* We'll have up to (MAX_NUMNODES * MAX_NR_ZONES) zones total, * so we use (MAX_NODES_SHIFT + MAX_ZONES_SHIFT) here to get enough bits. */ -#define NODEZONE_SHIFT (sizeof(page_flags_t)*8 - MAX_NODES_SHIFT - MAX_ZONES_SHIFT) -#define NODEZONE (node, zone) ((node << ZONES_SHIFT) | zone) + +#define FLAGS_SHIFT (sizeof(page_flags_t)*8) + +/* 32bit: NODE:ZONE */ +#define PGFLAGS_NODES_SHIFT (FLAGS_SHIFT - NODES_SHIFT) +#define PGFLAGS_ZONES_SHIFT (PGFLAGS_NODES_SHIFT - ZONES_SHIFT) + +#define ZONETABLE_SHIFT (NODES_SHIFT + ZONES_SHIFT) +#define PGFLAGS_ZONETABLE_SHIFT (FLAGS_SHIFT - ZONETABLE_SHIFT) + +#if NODES_SHIFT +ZONES_SHIFT >FLAGS_TOTAL_SHIFT +#error NODES_SHIFT+ZONES_SHIFT > FLAGS_TOTAL_SHIFT +#endif + +#define NODEZONE (node, zone) ((node << ZONES_SHIFT) | zone) + +#define ZONES_MASK (~((~0UL) << ZONES_SHIFT)) +#define NODES_MASK (~((~0UL) << NODES_SHIFT)) +#define ZONETABLE_MASK (~((~0UL) << ZONETABLE_SHIFT)) + +#define PGFLAGS_MASK (~((~0UL) << PGFLAGS_ZONETABLE_SHIFT)static inline unsigned long page_zonenum (struct page *page) { -return (page->flags >>NODEZONE_SHIFT ) & (~(~0UL <<ZONES_SHIFT )); +if (FLAGS_SHIFT == (PGFLAGS_ZONES_SHIFT +ZONES_SHIFT )) +return (page->flags >>PGFLAGS_ZONES_SHIFT ); +else +return (page->flags >>PGFLAGS_ZONES_SHIFT ) &ZONES_MASK ; }static inline unsigned long page_to_nid (struct page *page) { -return (page->flags >> (NODEZONE_SHIFT +ZONES_SHIFT )); +if (FLAGS_SHIFT == (PGFLAGS_NODES_SHIFT +NODES_SHIFT )) +return (page->flags >>PGFLAGS_NODES_SHIFT ); +else +return (page->flags >>PGFLAGS_NODES_SHIFT ) &NODES_MASK ; }struct zone ;
@@ -393,13 +418,17 @@ extern struct zone *zone_table[];static inline struct zone *page_zone (struct page *page) { -return zone_table[page->flags >>NODEZONE_SHIFT ]; +if (FLAGS_SHIFT == (PGFLAGS_ZONETABLE_SHIFT +ZONETABLE_SHIFT )) +return zone_table[page->flags >>PGFLAGS_ZONETABLE_SHIFT ]; +else +return zone_table[page->flags >>PGFLAGS_ZONETABLE_SHIFT & +ZONETABLE_MASK ]; }static inline void set_page_zone (struct page *page,unsigned long nodezone_num) { - page->flags &= ~(~0UL <<NODEZONE_SHIFT ); - page->flags |= nodezone_num <<NODEZONE_SHIFT ; + page->flags &=PGFLAGS_MASK ; + page->flags |= nodezone_num <<PGFLAGS_ZONETABLE_SHIFT ; }#ifndef CONFIG_DISCONTIGMEM
include/linux/mmzone.h +3 -13
@@ -389,27 +389,17 @@ extern struct pglist_data contig_page_da* with 32 bit page->flags field, we reserve 8 bits for node/zone info. * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes. */ -#define MAX_NODES_SHIFT 6 +#define FLAGS_TOTAL_SHIFT 8 +#elif BITS_PER_LONG ==64 /* * with 64 bit flags field, there's plenty of room. */ -#define MAX_NODES_SHIFT 10 +#define FLAGS_TOTAL_SHIFT 12#endif #endif /* !CONFIG_DISCONTIGMEM */ -#if NODES_SHIFT >MAX_NODES_SHIFT -#error NODES_SHIFT > MAX_NODES_SHIFT -#endif - -/* There are currently 3 zones: DMA, Normal & Highmem, thus we need 2 bits */ -#define MAX_ZONES_SHIFT 2 - -#if ZONES_SHIFT >MAX_ZONES_SHIFT -#error ZONES_SHIFT > MAX_ZONES_SHIFT -#endif - extern DECLARE_BITMAP(node_online_map, MAX_NUMNODES);#if defined(CONFIG_DISCONTIGMEM ) || defined(CONFIG_NUMA )
--
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>
150 nonlinear
In reply to Andy WhitcroftCONFIG_NONLINEAR memory model.
Revision: $Rev$
diffstat 150-nonlinear
--- include/linux/mm.h | 103 +++++++++++++++++++++++++++++++++--- include/linux/mmzone.h | 140 +++++++++++++++++++++++++++++++++++++++++++++++-- include/linux/numa.h | 2 init/main.c | 1 mm/Makefile | 2 mm/bootmem.c | 15 ++++- mm/memory.c | 2 mm/nonlinear.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++ mm/page_alloc.c | 87 +++++++++++++++++++++++++++++- 9 files changed, 469 insertions(+), 20 deletions(-)
include/linux/mm.h +95 -8
@@ -379,24 +379,76 @@ static inline void put_page(struct page#define FLAGS_SHIFT (sizeof(page_flags_t)*8) -/* 32bit: NODE:ZONE */ +/* +* CONFIG_NONLINEAR: +* If there is room for SECTIONS, NODES AND ZONES then: +* NODE:ZONE:SECTION +* else: +* SECTION:ZONE +* +* Otherwise: +* NODE:ZONE +*/ +#ifdef CONFIG_NONLINEAR + +#if FLAGS_TOTAL_SHIFT >=SECTIONS_SHIFT +NODES_SHIFT +ZONES_SHIFT + +/* NODE:ZONE:SECTION */ #define PGFLAGS_NODES_SHIFT (FLAGS_SHIFT - NODES_SHIFT)#define PGFLAGS_ZONES_SHIFT (PGFLAGS_NODES_SHIFT - ZONES_SHIFT) +#define PGFLAGS_SECTIONS_SHIFT (PGFLAGS_ZONES_SHIFT - SECTIONS_SHIFT) + +#define FLAGS_USED_SHIFT (NODES_SHIFT + ZONES_SHIFT + SECTIONS_SHIFT)#define ZONETABLE_SHIFT (NODES_SHIFT + ZONES_SHIFT)#define PGFLAGS_ZONETABLE_SHIFT (FLAGS_SHIFT - ZONETABLE_SHIFT) -#if NODES_SHIFT +ZONES_SHIFT >FLAGS_TOTAL_SHIFT -#error NODES_SHIFT+ZONES_SHIFT > FLAGS_TOTAL_SHIFT +#define ZONETABLE (section, node, zone) \ + ((node << ZONES_SHIFT) | zone) + +#else + +/* SECTION:ZONE */ +#define PGFLAGS_SECTIONS_SHIFT (FLAGS_SHIFT - SECTIONS_SHIFT) +#define PGFLAGS_ZONES_SHIFT (PGFLAGS_SECTIONS_SHIFT - ZONES_SHIFT) + +#define FLAGS_USED_SHIFT (SECTIONS_SHIFT + ZONES_SHIFT) + +#define ZONETABLE_SHIFT (SECTIONS_SHIFT + ZONES_SHIFT) +#define PGFLAGS_ZONETABLE_SHIFT (FLAGS_SHIFT - ZONETABLE_SHIFT) + +#define ZONETABLE (section, node, zone) \ + ((section << ZONES_SHIFT) | zone) + +#endif + +#else /* !CONFIG_NONLINEAR */ + +/* NODE:ZONE */ +#define PGFLAGS_NODES_SHIFT (FLAGS_SHIFT - NODES_SHIFT) +#define PGFLAGS_ZONES_SHIFT (PGFLAGS_NODES_SHIFT - ZONES_SHIFT) + +#define ZONETABLE_SHIFT (NODES_SHIFT + ZONES_SHIFT) +#define PGFLAGS_ZONETABLE_SHIFT (FLAGS_SHIFT - ZONETABLE_SHIFT) + +#define FLAGS_USED_SHIFT (NODES_SHIFT + ZONES_SHIFT) + +#endif /* !CONFIG_NONLINEAR */ + +#if FLAGS_USED_SHIFT >FLAGS_TOTAL_SHIFT +#error SECTIONS_SHIFT+NODES_SHIFT+ZONES_SHIFT > FLAGS_TOTAL_SHIFT#endif #define NODEZONE (node, zone) ((node << ZONES_SHIFT) | zone)#define ZONES_MASK (~((~0UL) << ZONES_SHIFT))#define NODES_MASK (~((~0UL) << NODES_SHIFT)) +#define SECTIONS_MASK (~((~0UL) << SECTIONS_SHIFT))#define ZONETABLE_MASK (~((~0UL) << ZONETABLE_SHIFT)) -#define PGFLAGS_MASK (~((~0UL) << PGFLAGS_ZONETABLE_SHIFT) +#define ZONETABLE_SIZE (1 << ZONETABLE_SHIFT) + +#define PGFLAGS_MASK (~((~0UL) << PGFLAGS_ZONETABLE_SHIFT))static inline unsigned long page_zonenum (struct page *page) {
@@ -405,13 +457,34 @@ static inline unsigned long page_zonenumelse return (page->flags >>PGFLAGS_ZONES_SHIFT ) &ZONES_MASK ; } +#ifdef PGFLAGS_NODES_SHIFT static inline unsigned long page_to_nid (struct page *page) { +#if NODES_SHIFT ==0 +return 0 ; +#else if (FLAGS_SHIFT == (PGFLAGS_NODES_SHIFT +NODES_SHIFT ))return (page->flags >>PGFLAGS_NODES_SHIFT );else return (page->flags >>PGFLAGS_NODES_SHIFT ) &NODES_MASK ; +#endif } +#else +static inline struct zone *page_zone (struct page *page); +static inline unsigned long page_to_nid (struct page *page) +{ +return page_zone (page)->zone_pgdat->node_id; +} +#endif +#ifdef PGFLAGS_SECTIONS_SHIFT +static inline unsigned long page_to_section (struct page *page) +{ +if (FLAGS_SHIFT == (PGFLAGS_SECTIONS_SHIFT +SECTIONS_SHIFT )) +return (page->flags >>PGFLAGS_SECTIONS_SHIFT ); +else +return (page->flags >>PGFLAGS_SECTIONS_SHIFT ) &SECTIONS_MASK ; +} +#endif struct zone ;extern struct zone *zone_table[];
@@ -425,13 +498,27 @@ static inline struct zone *page_zone(str ZONETABLE_MASK]; } -static inline void set_page_zone (struct page *page,unsigned long nodezone_num) +static inline void set_page_zone (struct page *page,unsigned long zone) +{ + page->flags &= ~(ZONES_MASK <<PGFLAGS_ZONES_SHIFT ); + page->flags |= zone <<PGFLAGS_ZONES_SHIFT ; +} +static inline void set_page_node (struct page *page,unsigned long node) { - page->flags &=PGFLAGS_MASK ; - page->flags |= nodezone_num <<PGFLAGS_ZONETABLE_SHIFT ; +#if defined(PGFLAGS_NODES_SHIFT ) &&NODES_SHIFT !=0 + page->flags &= ~(NODES_MASK <<PGFLAGS_NODES_SHIFT ); + page->flags |= node <<PGFLAGS_NODES_SHIFT ; +#endif +} +static inline void set_page_section (struct page *page,unsigned long section) +{ +#ifdef PGFLAGS_SECTIONS_SHIFT + page->flags &= ~(SECTIONS_MASK <<PGFLAGS_SECTIONS_SHIFT ); + page->flags |= section <<PGFLAGS_SECTIONS_SHIFT ; +#endif } -#ifndef CONFIG_DISCONTIGMEM +#ifdef CONFIG_FLATMEM /* The array of struct pages - for discontigmem use pgdat->lmem_map */ extern struct page *mem_map;#endif
include/linux/mmzone.h +136 -4
165 lines not on this page · raw message
include/linux/numa.h +1 -1
@@ -3,7 +3,7 @@#include <linux/config.h> -#ifdef CONFIG_DISCONTIGMEM +#ifndef CONFIG_FLATMEM #include <asm/numnodes.h> #endif
init/main.c +1 -0
@@ -480,6 +480,7 @@ asmlinkage void __init start_kernel(void {char * command_line;extern struct kernel_param __start___param[], __stop___param[]; +/* * Interrupts are still disabled. Do necessary setups, then * enable them
mm/bootmem.c +14 -1
@@ -255,6 +255,7 @@ found:static unsigned long __init free_all_bootmem_core (pg_data_t *pgdat) {struct page *page; +unsigned long pfn;bootmem_data_t *bdata = pgdat->bdata;unsigned long i, count, total =0 ;unsigned long idx;
@@ -265,15 +266,26 @@ static unsigned long __init free_all_boo count =0 ;/* first extant page of the node */ - page =virt_to_page (phys_to_virt (bdata->node_boot_start)); + pfn = bdata->node_boot_start >>PAGE_SHIFT ; idx = bdata->node_low_pfn - (bdata->node_boot_start >>PAGE_SHIFT ); map = bdata->node_bootmem_map;/* Check physaddr is O(LOG2(BITS_PER_LONG)) page aligned */ if (bdata->node_boot_start ==0 ||ffs (bdata->node_boot_start) -PAGE_SHIFT >ffs (BITS_PER_LONG )) gofast =1 ; + page =pfn_to_page (pfn);for (i =0 ; i < idx; ) {unsigned long v = ~map[i /BITS_PER_LONG ]; + +/* +* Makes use of the guarentee that *_mem_map will be +* contigious in sections aligned at MAX_ORDER. +* APW/XXX: we are making an assumption that our node_boot_start +* is aligned to BITS_PER_LONG ... is this valid/enforced. +*/ +if ((pfn & ((1 <<MAX_ORDER ) -1 )) ==0 ) + page =pfn_to_page (pfn); +if (gofast && v == ~0UL ) {int j;
@@ -302,6 +314,7 @@ static unsigned long __init free_all_boo i+=BITS_PER_LONG ; page +=BITS_PER_LONG ; } + pfn +=BITS_PER_LONG ; } total += count;
mm/Makefile +1 -1
@@ -15,6 +15,6 @@ obj-y := bootmem.o filemap.o mempool.o obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o obj-$(CONFIG_HUGETLBFS) += hugetlb.o obj-$(CONFIG_NUMA) += mempolicy.o +obj-$(CONFIG_NONLINEAR) += nonlinear.o obj-$(CONFIG_SHMEM) += shmem.o obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o -
mm/memory.c +1 -1
@@ -56,7 +56,7 @@#include <linux/swapops.h> #include <linux/elf.h> -#ifndef CONFIG_DISCONTIGMEM +#ifdef CONFIG_FLATMEM /* use the per-pgdat data instead for discontigmem - mbligh */ unsigned long max_mapnr;struct page *mem_map;
mm/nonlinear.c new file +137 -0
137 lines not on this page · raw message
mm/page_alloc.c +83 -4
163 lines not on this page · raw message
--
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>
Re: 150 nonlinear
Hi Andy,
I've been thinking about how we're going to merge up the code that uses Dave M's nonlinear with your new implementation.
There are two problems that are being solved: having a sparse layout requiring splitting up mem_map (solved by discontigmem and your nonlinear), and supporting non-linear phys to virt relationships (Dave M's implentation which does the mem_map split as well).
I think both Dave M. and I agree that your implementation is the way to go, mostly because it properly starts the separation of these two distinct problems.
So, I propose the following: your code should be referred to as something like CONFIG_SPARSEMEM. The code supporting non-linear p::v retains the CONFIG_NONLINEAR name.
Do you think your code is in a place where it's ready for wider testing on a few more architectures? In which case, would you like it held in the -mhp tree while it's waiting to get merged?
-- Dave
--
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>
Re: [Lhms-devel] Re: 150 nonlinear
Quoted 18 lines · Dave Hansen
Hi Andy,
I've been thinking about how we're going to merge up the code that uses Dave M's nonlinear with your new implementation.
There are two problems that are being solved: having a sparse layout requiring splitting up
mem_map(solved by discontigmem and your nonlinear), and supporting non-linear phys to virt relationships (Dave M's implentation which does themem_mapsplit as well).I think both Dave M. and I agree that your implementation is the way to go, mostly because it properly starts the separation of these two distinct problems.
So, I propose the following: your code should be referred to as something like
CONFIG_SPARSEMEM. The code supporting non-linearp::vretains theCONFIG_NONLINEARname.
Quoted 8 lines
Do you think your code is in a place where it's ready for wider testing on a few more architectures? In which case, would you like it held in the -mhp tree while it's waiting to get merged?
-- Dave
What do you consider as Dave M's nonlinear?
--Mika
--
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>
Re: [Lhms-devel] Re: 150 nonlinear
Quoted 1 line · Mika Penttila
What do you consider as Dave M's nonlinear?
This, basically:
http://sprucegoose.sr71.net/patches/2.6.9-rc3-mm3-mhp1/C-nonlinear-base.patch
There's a little there that isn't Dave M's direct work, but it's all in the spirit of his implementation.
-- Dave
--
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>
Re: [Lhms-devel] Re: 150 nonlinear
Quoted 7 lines · Dave Hansen
Quoted 3 lines · Mika Penttila
What do you consider as Dave M's nonlinear?
Quoted 12 lines
This, basically:
http://sprucegoose.sr71.net/patches/2.6.9-rc3-mm3-mhp1/C-nonlinear-base.patch
There's a little there that isn't Dave M's direct work, but it's all in the spirit of his implementation.
-- Dave
Ah, you mean Daniel Phillips's initial patch for nonlinear...
Ok, so what's the mem_map split? I see Andy renamed it section_mem_map and added NONLINEAR_OPTIMISE, how's that making a difference?
--Mika
--
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>
Re: [Lhms-devel] Re: 150 nonlinear
Quoted 1 line · Mika Penttila
Ah, you mean Daniel Phillips's initial patch for nonlinear...
No. Dan had a lovely idea, and a decent implementation, but Dave M completely reimplemented it as far as I know. That's why I've been referring to them as "implementations".
Quoted 2 lines
Ok, so what's the
mem_mapsplit? I see Andy renamed itsection_mem_mapand addedNONLINEAR_OPTIMISE, how's that making a difference?
I don't understand the question. Why do we need to split up mem_map?
-- Dave
--
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>
Re: [Lhms-devel] Re: 150 nonlinear
Quoted 13 lines · Dave Hansen
Quoted 3 lines · Mika Penttila
Ah, you mean Daniel Phillips's initial patch for nonlinear...
No. Dan had a lovely idea, and a decent implementation, but Dave M completely reimplemented it as far as I know. That's why I've been referring to them as "implementations".
I see ..ok.
Quoted 8 lines
Quoted 3 lines
Ok, so what's the
mem_mapsplit? I see Andy renamed itsection_mem_mapand addedNONLINEAR_OPTIMISE, how's that making a difference?I don't understand the question. Why do we need to split up
mem_map?
I do not understand the split either..but you said :
"There are two problems that are being solved: having a sparse layout requiring splitting up mem_map (solved by discontigmem and your nonlinear), and supporting non-linear phys to virt relationships (Dave M's implentation which does the mem_map split as well)."
so what's the split?
--Mika
--
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>
Re: [Lhms-devel] Re: 150 nonlinear
Quoted 7 lines · Mika Penttila
"There are two problems that are being solved: having a sparse layout requiring splitting up
mem_map(solved by discontigmem and your nonlinear), and supporting non-linear phys to virt relationships (Dave M's implentation which does themem_mapsplit as well)."so what's the split?
So, mem_map is normally laid out so that, if you have 1GB of memory, the memory for 0x00000000 is at mem_map[0], and the memory for the last page (at 1GB - 1 page) is at mem_map[1<<30 / PAGE_SIZE - 1].
That's fine and dandy for most systems. But, imagine that you have some memory on a funky machine where you have 2GB of memory, but it is laid out like this:
0-1 GB - first 1 GB
1-100 GB - empty
100-101 GB - second 1 GB
Then, you'd need to have mem_map sized the same as a 101GB system on your dinky 2GB system (disregard the ia64 implementation).
The split I'm referring to is cutting mem_map[] up into pieces for each contiguous section of memory.
Make sense?
-- Dave
--
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>
Re: [Lhms-devel] Re: 150 nonlinear
Quoted 28 lines · Dave Hansen
Quoted 9 lines · Mika Penttila
"There are two problems that are being solved: having a sparse layout requiring splitting up
mem_map(solved by discontigmem and your nonlinear), and supporting non-linear phys to virt relationships (Dave M's implentation which does themem_mapsplit as well)."so what's the split?
So,
mem_mapis normally laid out so that, if you have 1GB of memory, the memory for0x00000000is at mem_map[0], and the memory for the last page (at 1GB - 1 page) is at mem_map[1<<30 /PAGE_SIZE- 1].That's fine and dandy for most systems. But, imagine that you have some memory on a funky machine where you have 2GB of memory, but it is laid out like this:
0-1 GB - first 1 GB1-100 GB - empty
100-101 GB - second 1 GBThen, you'd need to have
mem_mapsized the same as a 101GB system on your dinky 2GB system (disregard the ia64 implementation).
Quoted 10 lines
The split I'm referring to is cutting mem_map[] up into pieces for each contiguous section of memory.
Make sense?
-- Dave
Yes, I see Dave M's approarch is doing this, but isn't Andy's as well? What's the key differences between these two?
--Mika
--
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>
Re: [Lhms-devel] Re: 150 nonlinear
Taking poor Andy off the cc...
Quoted 2 lines · Mika Penttila
Yes, I see Dave M's approarch is doing this, but isn't Andy's as well? What's the key differences between these two?
Back to my first message:
Quoted 4 lines
There are two problems that are being solved: having a sparse layout requiring splitting up
mem_map(solved by discontigmem and your nonlinear), and supporting non-linear phys to virt relationships (Dave M's implentation which does themem_mapsplit as well).
Andy: split
Dave M: split + non-linear phys to virt
-- Dave
--
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>
Re: [Lhms-devel] Re: 150 nonlinear
Quoted 22 lines · Dave Hansen
Taking poor Andy off the cc...
Quoted 3 lines · Mika Penttila
Yes, I see Dave M's approarch is doing this, but isn't Andy's as well? What's the key differences between these two?
Back to my first message:
Quoted 6 lines
There are two problems that are being solved: having a sparse layout requiring splitting up
mem_map(solved by discontigmem and your nonlinear), and supporting non-linear phys to virt relationships (Dave M's implentation which does themem_mapsplit as well).Andy: split
Dave M: split + non-linear phys to virt
Quoted 10 lines
-- Dave
--
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>
So is it?
Andy: __pa and __va as before, nonlinear page_to_pfn and pfn_to_page Dave M : new nonlinear __pa and __va implementations and nonlinear page_to_pfn and pfn_to_page
--Mika
--
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>
Re: [Lhms-devel] Re: 150 nonlinear
Quoted 3 lines · Mika Penttila
Andy: __pa and __va as before, nonlinear page_to_pfn and pfn_to_page Dave M : new nonlinear __pa and __va implementations and nonlinear
page_to_pfnandpfn_to_page
Yes, basically. Those are the most visible high-level-API functions that get changed.
-- Dave
--
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>
Re: [Lhms-devel] Re: 150 nonlinear
Quoted 8 lines · Dave Hansen
Quoted 4 lines · Mika Penttila
Andy: __pa and __va as before, nonlinear page_to_pfn and pfn_to_page Dave M : new nonlinear __pa and __va implementations and nonlinear page_to_pfn and pfn_to_page
Quoted 7 lines
Yes, basically. Those are the most visible high-level-API functions that get changed.
-- Dave
great..thanks!
--Mika
--
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>
Re: 150 nonlinear
In reply to Dave HansenQuoted 12 lines · Dave Hansen
I've been thinking about how we're going to merge up the code that uses Dave M's nonlinear with your new implementation.
There are two problems that are being solved: having a sparse layout requiring splitting up
mem_map(solved by discontigmem and your nonlinear), and supporting non-linear phys to virt relationships (Dave M's implentation which does themem_mapsplit as well).I think both Dave M. and I agree that your implementation is the way to go, mostly because it properly starts the separation of these two distinct problems.
Quoted 7 lines
So, I propose the following: your code should be referred to as something like
CONFIG_SPARSEMEM. The code supporting non-linearp::vretains theCONFIG_NONLINEARname.Do you think your code is in a place where it's ready for wider testing on a few more architectures? In which case, would you like it held in the -mhp tree while it's waiting to get merged?
Ok. Meant to get back to you sooner, trouble getting test runs through on the new version. Anyhow, yes thats fine with me. I'll send out a new version here today renamed to CONFIG_SPARSEMEM. This also has a few fixes as a result of futher testing. -mhp seems as good a place as any for the moment.
-apw
--
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>
160 nonlinear i386
In reply to Andy WhitcroftCONFIG_NONLINEAR for i386
Revision: $Rev$
diffstat 160-nonlinear-i386
--- arch/i386/Kconfig | 22 ++++++--- arch/i386/kernel/numaq.c | 5 ++ arch/i386/kernel/setup.c | 7 ++ arch/i386/kernel/srat.c | 5 ++ arch/i386/mm/Makefile | 2 arch/i386/mm/discontig.c | 97 +++++++++++++++++++++++---------------- arch/i386/mm/init.c | 19 ++++--- include/asm-i386/mmzone.h | 110 ++++++++++++++++++++++++++++++++++----------- include/asm-i386/page.h | 4 - include/asm-i386/pgtable.h | 4 - 10 files changed, 189 insertions(+), 86 deletions(-)
arch/i386/Kconfig +17 -5
@@ -68,7 +68,7 @@ config X86_VOYAGER config X86_NUMAQ bool "NUMAQ (IBM/Sequent)" - select DISCONTIGMEM + #select DISCONTIGMEM select NUMA help This option is used for getting Linux to run on a (IBM/Sequent) NUMA
@@ -738,16 +738,28 @@ comment "NUMA (NUMA-Q) requires SMP, 64G comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI" depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI) -config DISCONTIGMEM - bool - depends on NUMA - default y config HAVE_ARCH_BOOTMEM_NODE bool depends on NUMA default y +choice + prompt "Memory model" + default NONLINEAR if (X86_NUMAQ || X86_SUMMIT) + default FLATMEM + +config DISCONTIGMEM + bool "Discontigious Memory" + +config NONLINEAR + bool "Nonlinear Memory" + +config FLATMEM + bool "Flat Memory" + +endchoice + config HIGHPTE bool "Allocate 3rd-level pagetables from highmem" depends on HIGHMEM4G || HIGHMEM64G
arch/i386/kernel/numaq.c +5 -0
@@ -60,6 +60,11 @@ static void __init smp_dump_qct(void) eq->hi_shrd_mem_start - eq->priv_mem_size); node_end_pfn[node] =MB_TO_PAGES ( eq->hi_shrd_mem_start + eq->hi_shrd_mem_size); +#ifdef CONFIG_NONLINEAR +nonlinear_add (node, node_start_pfn[node], + node_end_pfn[node]); +#endif + } } }
arch/i386/kernel/setup.c +5 -2
@@ -39,6 +39,7 @@#include <linux/efi.h> #include <linux/init.h> #include <linux/edd.h> +#include <linux/mmzone.h> #include <video/edid.h> #include <asm/e820.h> #include <asm/mpspec.h>
@@ -1014,7 +1015,7 @@ static void __init reserve_ebda_region(vreserve_bootmem (addr,PAGE_SIZE ); } -#ifndef CONFIG_DISCONTIGMEM +#ifdef CONFIG_FLATMEM void __init setup_bootmem_allocator (void );static unsigned long __init setup_memory (void ) {
@@ -1042,7 +1043,9 @@ static unsigned long __init setup_memorysetup_bootmem_allocator (); return max_low_pfn; } -#endif /* !CONFIG_DISCONTIGMEM */ +#else +unsigned long __init setup_memory (void ); +#endif /* CONFIG_FLATMEM */ void __init setup_bootmem_allocator (void ) {
arch/i386/kernel/srat.c +5 -0
@@ -261,6 +261,11 @@ static int __init acpi20_parse_srat(stru j, node_memory_chunk[j].nid, node_memory_chunk[j].start_pfn, node_memory_chunk[j].end_pfn); +#ifdef CONFIG_NONLINEAR +nonlinear_add (node_memory_chunk[j].nid, + node_memory_chunk[j].start_pfn, + node_memory_chunk[j].end_pfn); +#endif /* CONFIG_NONLINEAR */ }/*calculate node_start_pfn/node_end_pfn arrays*/
arch/i386/mm/discontig.c +57 -40
165 lines not on this page · raw message
arch/i386/mm/init.c +11 -8
@@ -274,7 +274,7 @@ void __init one_highpage_init(struct pagSetPageReserved (page); } -#ifndef CONFIG_DISCONTIGMEM +#ifdef CONFIG_FLATMEM void __init set_highmem_pages_init (int bad_ppro) {int pfn;
@@ -284,7 +284,7 @@ void __init set_highmem_pages_init(int b }#else extern void set_highmem_pages_init (int ); -#endif /* !CONFIG_DISCONTIGMEM */ +#endif /* CONFIG_FLATMEM */ #else #define kmap_init () do { } while (0)
@@ -295,7 +295,7 @@ extern void set_highmem_pages_init(int);unsigned long long __PAGE_KERNEL = _PAGE_KERNEL;unsigned long long __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC; -#ifndef CONFIG_DISCONTIGMEM +#ifdef CONFIG_FLATMEM #define remap_numa_kva () do {} while (0)#else extern void __init remap_numa_kva (void );
@@ -388,7 +388,7 @@ void zap_low_mappings (void)flush_tlb_all (); } -#ifndef CONFIG_DISCONTIGMEM +#ifdef CONFIG_FLATMEM void __init zone_sizes_init (void ) {unsigned long zones_size[MAX_NR_ZONES ] = {0 ,0 ,0 };
@@ -411,7 +411,7 @@ void __init zone_sizes_init(void) }#else extern void zone_sizes_init (void ); -#endif /* !CONFIG_DISCONTIGMEM */ +#endif /* CONFIG_FLATMEM */ static int disable_nx__initdata =0 ;u64 __supported_pte_mask = ~_PAGE_NX;
@@ -516,6 +516,9 @@ void __init paging_init(void)__flush_tlb_all ();kmap_init (); +#ifdef CONFIG_NONLINEAR +nonlinear_allocate (); +#endif zone_sizes_init (); }
@@ -545,7 +548,7 @@ void __init test_wp_bit(void) } } -#ifndef CONFIG_DISCONTIGMEM +#ifdef CONFIG_FLATMEM static void __init set_max_mapnr_init (void ) {#ifdef CONFIG_HIGHMEM
@@ -559,7 +562,7 @@ static void __init set_max_mapnr_init(vo#else #define __free_all_bootmem () free_all_bootmem_node(NODE_DATA(0))extern void set_max_mapnr_init (void ); -#endif /* !CONFIG_DISCONTIGMEM */ +#endif /* CONFIG_FLATMEM */ static struct kcore_list kcore_mem, kcore_vmalloc;
@@ -570,7 +573,7 @@ void __init mem_init(void)int tmp;int bad_ppro; -#ifndef CONFIG_DISCONTIGMEM +#ifdef CONFIG_FLATMEM if (!mem_map)BUG ();#endif
arch/i386/mm/Makefile +1 -1
@@ -4,7 +4,7 @@ obj-y := init.o pgtable.o fault.o ioremap.o extable.o pageattr.o mmap.o -obj-$(CONFIG_DISCONTIGMEM) += discontig.o +obj-$(CONFIG_NUMA) += discontig.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_HIGHMEM) += highmem.o obj-$(CONFIG_BOOT_IOREMAP) += boot_ioremap.o
include/asm-i386/mmzone.h +84 -26
138 lines not on this page · raw message
include/asm-i386/page.h +2 -2
@@ -133,11 +133,11 @@ extern int sysctl_legacy_va_layout;#define __pa (x) ((unsigned long)(x)-PAGE_OFFSET)#define __va (x) ((void *)((unsigned long)(x)+PAGE_OFFSET))#define pfn_to_kaddr (pfn) __va((pfn) << PAGE_SHIFT) -#ifndef CONFIG_DISCONTIGMEM +#ifdef CONFIG_FLATMEM #define pfn_to_page (pfn) (mem_map + (pfn))#define page_to_pfn (page) ((unsigned long)((page) - mem_map))#define pfn_valid (pfn) ((pfn) < max_mapnr) -#endif /* !CONFIG_DISCONTIGMEM */ +#endif /* CONFIG_FLATMEM */ #define virt_to_page (kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)#define virt_addr_valid (kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
include/asm-i386/pgtable.h +2 -2
@@ -400,9 +400,9 @@ extern pte_t *lookup_address(unsigned lo#endif /* !__ASSEMBLY__ */ -#ifndef CONFIG_DISCONTIGMEM +#ifdef CONFIG_FLATMEM #define kern_addr_valid (addr) (1) -#endif /* !CONFIG_DISCONTIGMEM */ +#endif /* CONFIG_FLATMEM */ #define io_remap_page_range remap_page_range
--
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>
170 nonlinear ppc64
In reply to Andy WhitcroftCONFIG_NONLINEAR for ppc64.
Revision: $Rev$
diffstat 170-nonlinear-ppc64
--- arch/ppc64/Kconfig | 19 +++++++++++++++++-- arch/ppc64/mm/Makefile | 2 +- arch/ppc64/mm/init.c | 8 ++++---- arch/ppc64/mm/numa.c | 13 +++++++++++++ include/asm-ppc64/mmzone.h | 40 ++++++++++++++++++++++++++++++++++------ include/asm-ppc64/page.h | 4 +++- 6 files changed, 72 insertions(+), 14 deletions(-)
arch/ppc64/Kconfig +17 -2
@@ -180,13 +180,28 @@ config HMT bool "Hardware multithreading" depends on SMP && PPC_PSERIES + +choice + prompt "Memory model" + default NONLINEAR if (PPC_PSERIES) + default FLATMEM + config DISCONTIGMEM - bool "Discontiguous Memory Support" + bool "Discontigious Memory" + depends on SMP && PPC_PSERIES + +config NONLINEAR + bool "Nonlinear Memory" depends on SMP && PPC_PSERIES +config FLATMEM + bool "Flat Memory" + +endchoice + config NUMA bool "NUMA support" - depends on DISCONTIGMEM + #depends on DISCONTIGMEM config SCHED_SMT bool "SMT (Hyperthreading) scheduler support"
arch/ppc64/mm/init.c +4 -4
@@ -597,7 +597,7 @@ EXPORT_SYMBOL(page_is_ram);* Initialize the bootmem system and give it all the memory we * have available. */ -#ifndef CONFIG_DISCONTIGMEM +#ifdef CONFIG_FLATMEM void __init do_init_bootmem (void ) {unsigned long i;
@@ -695,7 +695,7 @@ module_init(setup_kcore);void __init mem_init (void ) { -#ifdef CONFIG_DISCONTIGMEM +#if defined(CONFIG_DISCONTIGMEM ) || defined(CONFIG_NONLINEAR )int nid;#endif pg_data_t *pgdat;
@@ -706,7 +706,7 @@ void __init mem_init(void) num_physpages = max_low_pfn;/* RAM is assumed contiguous */ high_memory = (void *)__va (max_low_pfn *PAGE_SIZE ); -#ifdef CONFIG_DISCONTIGMEM +#if defined(CONFIG_DISCONTIGMEM ) || defined(CONFIG_NONLINEAR )for (nid =0 ; nid < numnodes; nid++) {if (NODE_DATA (nid)->node_spanned_pages !=0 ) {printk ("freeing bootmem node %x\n" , nid);
@@ -721,7 +721,7 @@ void __init mem_init(void)for_each_pgdat (pgdat) {for (i =0 ; i < pgdat->node_spanned_pages; i++) { - page = pgdat->node_mem_map + i; + page =pfn_to_page (i);if (PageReserved (page)) reservedpages++; }
arch/ppc64/mm/Makefile +1 -1
@@ -6,6 +6,6 @@ EXTRA_CFLAGS += -mno-minimal-toc obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \ slb_low.o slb.o stab.o mmap.o -obj-$(CONFIG_DISCONTIGMEM) += numa.o +obj-$(CONFIG_NUMA) += numa.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_PPC_MULTIPLATFORM) += hash_native.o
arch/ppc64/mm/numa.c +13 -0
@@ -304,9 +304,13 @@ new_range: size /PAGE_SIZE ; } +/* XXX: think this is discontig ... */ for (i = start ; i < (start+size); i +=MEMORY_INCREMENT ) numa_memory_lookup_table[i >>MEMORY_INCREMENT_SHIFT ] = numa_domain; +#ifdef CONFIG_NONLINEAR +nonlinear_add (numa_domain, start, start + size); +#endif ranges--;if (ranges)
@@ -346,10 +350,15 @@ static void __init setup_nonnuma(void) init_node_data[0 ].node_start_pfn =0 ; init_node_data[0 ].node_spanned_pages =lmb_end_of_DRAM () /PAGE_SIZE ; +/* APW: this is discontig? */ for (i =0 ; i < top_of_ram; i +=MEMORY_INCREMENT ) numa_memory_lookup_table[i >>MEMORY_INCREMENT_SHIFT ] =0 ; node0_io_hole_size = top_of_ram - total_ram; + +#ifdef CONFIG_NONLINEAR +nonlinear_add (0 ,0 , init_node_data[0 ].node_spanned_pages); +#endif }static void __init dump_numa_topology (void )
@@ -567,6 +576,10 @@ void __init paging_init(void)memset (zones_size,0 ,sizeof (zones_size));memset (zholes_size,0 ,sizeof (zholes_size)); +#ifdef CONFIG_NONLINEAR +nonlinear_allocate (); +#endif +for (nid =0 ; nid < numnodes; nid++) {unsigned long start_pfn;unsigned long end_pfn;
include/asm-ppc64/mmzone.h +34 -6
@@ -10,9 +10,13 @@#include <linux/config.h> #include <asm/smp.h> -#ifdef CONFIG_DISCONTIGMEM +#if defined(CONFIG_DISCONTIGMEM ) || defined(CONFIG_NONLINEAR )extern struct pglist_data *node_data[]; +/* +* Return a pointer to the node data for node n. +*/ +#define NODE_DATA (nid) (node_data[nid])/* * Following are specific to this numa platform.
@@ -27,6 +31,10 @@ extern int nr_cpus_in_node[];#define MEMORY_INCREMENT_SHIFT 24#define MEMORY_INCREMENT (1UL << MEMORY_INCREMENT_SHIFT) +#endif /* !CONFIG_DISCONTIGMEM || !CONFIG_NONLINEAR */ + +#ifdef CONFIG_DISCONTIGMEM +/* NUMA debugging, will not work on a DLPAR machine */ #undef DEBUG_NUMA
@@ -49,11 +57,6 @@ static inline int pa_to_nid(unsigned lon#define pfn_to_nid (pfn) pa_to_nid((pfn) << PAGE_SHIFT) -/* -* Return a pointer to the node data for node n. -*/ -#define NODE_DATA (nid) (node_data[nid]) -#define node_localnr (pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn)/*
@@ -91,4 +94,29 @@ static inline int pa_to_nid(unsigned lon#define discontigmem_pfn_valid (pfn) ((pfn) < num_physpages)#endif /* CONFIG_DISCONTIGMEM */ + +#ifdef CONFIG_NONLINEAR + +/* generic non-linear memory support: +* +* 1) we will not split memory into more chunks than will fit into the +* flags field of the struct page +*/ + +/* +* SECTION_SIZE_BITS 2^N: how big each section will be +* MAX_PHYSADDR_BITS 2^N: how much physical address space we have +* MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space +*/ +#define SECTION_SIZE_BITS 24 +#define MAX_PHYSADDR_BITS 38 +#define MAX_PHYSMEM_BITS 36 + +#define pa_to_nid (pa) \ +({ \ + pfn_to_nid(pa >> PAGE_SHIFT); \ +}) + +#endif /* CONFIG_NONLINEAR */ +#endif /* _ASM_MMZONE_H_ */
include/asm-ppc64/page.h +3 -1
@@ -222,7 +222,9 @@ extern int page_is_ram(unsigned long pfn#define page_to_pfn (page) discontigmem_page_to_pfn(page)#define pfn_to_page (pfn) discontigmem_pfn_to_page(pfn)#define pfn_valid (pfn) discontigmem_pfn_valid(pfn) -#else +#endif +/* XXX/APW: why is NONLINEAR not here */ +#ifdef CONFIG_FLATMEM #define pfn_to_page (pfn) (mem_map + (pfn))#define page_to_pfn (page) ((unsigned long)((page) - mem_map))#define pfn_valid (pfn) ((pfn) < max_mapnr)
--
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>
Hello, Andy,
What version of kernel are you using?
I recommend linux-2.6.9-rc4-mm1 for your purpose, as it has eliminated bitmaps for free pages to simplify managing buddy allocator. This may help you.
Quoted 43 lines
Following this email will be a series of patches which provide a sample implementation of a simplified
CONFIG_NONLINEARmemory model. The first two cleanup general infrastructure to minimise code duplication. The third introduces an allocator for the numa remap space on i386. The fourth generalises the page flags code to allow the reuse of the NODEZONE bits. The final three are the actual meat of the implementation for both i386 and ppc64.050-bootmem-use-NODE_DATA
060-refactor-setup_memory-i386
080-alloc_remap-i386
100-cleanup-node-zone
150-nonlinear
160-nonlinear-i386
170-nonlinear-ppc64As has been observed the
CONFIG_DISCONTIGMEMimplementation is inefficient space-wise where a system has a sparse intra-node memory configuration. For example we have systems where node 0 has a 1GB hole within it. UnderCONFIG_DISCONTIGMEMthis results in the struct page's for this area being allocated fromZONE_NORMALand never used; this is particularly problematic on these 32bit systems as we are already under severe pressure in this zone.The generalised
CONFIG_NONLINEARmemory model described at OLS seemed provide more than enough decriptive power to address this issue but provided far more functionality that was required. Particularly it breaks the identity V=P+c to allow compression of the kernel address space, which is not required on these smaller systems.This patch set is implemented as a proof-of-concept to show that a simplified
CONFIG_NONLINEARbased implementation could provide sufficient flexibility to solve the problems for these systems.In the longer term I'd like to see a single
CONFIG_NONLINEARimplementation which allowed these various features to be stacked in combination as required.Thoughts?
-apw
Quoted 10 lines
-------------------------------------------------------
This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more
http://productguide.itmanagersjournal.com/guidepromo.tmpl
_______________________________________________
Lhms-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/lhms-devel
--
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 4 lines · Hirokazu Takahashi
What version of kernel are you using?
I recommend linux-2.6.9-rc4-mm1 for your purpose, as it has eliminated bitmaps for free pages to simplify managing buddy allocator. This may help you.
Doh, 2.6.9-rc4. It was the removal of the bitmaps which stopped me porting to there. I didn't want to do the extra work until it was decided if they are going for good :).
-apw
--
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>
Hi,
Quoted 6 lines · Andy Whitcroft
The generalised
CONFIG_NONLINEARmemory model described at OLS seemed provide more than enough decriptive power to address this issue but provided far more functionality that was required. Particularly it breaks the identity V=P+c to allow compression of the kernel address space, which is not required on these smaller systems.
We have *future* issue to hotplug kernel memory and kernel's virtual address renaming will be used for it.
As you say, if kernel memory is not remaped, keeping V=P+c looks good. But our current direction is to enable kernel-memory-hotplug, which needs kernel's virtual memory renaming, I think.
NONLINEAR_OPTIMISED looks a bit complicated.
Can replace them with some other name ? Hmm...NONLINEAR_NOREMAP ?
Quoted 4 lines
This patch set is implemented as a proof-of-concept to show that a simplified
CONFIG_NONLINEARbased implementation could provide sufficient flexibility to solve the problems for these systems.
Very interesting. But I'm not sure whether we can use more page->flags bit :[. I recommend you not to use more page->flags bits.
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>
Quoted 5 lines · Hiroyuki KAMEZAWA
We have *future* issue to hotplug kernel memory and kernel's virtual address renaming will be used for it.
As you say, if kernel memory is not remaped, keeping V=P+c looks good. But our current direction is to enable kernel-memory-hotplug, which needs kernel's virtual memory renaming, I think.
Yes, I think its very likely that memory hot-plug requires us to break V=P+c in a lot of cases - though perhaps not all. Indeed it was that work that started me thinking about using a simplified form to solve other problems for my 'crippled' 32bit systems.
What I am trying to say in my comments to this patch is that although generalised NONLINEAR will need and should provide this remap, that there are a class of systems and problem which don't need it (and the costs associated with it). I'd like to see them supported as a sub-option to NONLINEAR... ie as an nonlinear option to maintain V=P+c.
In that this style of layout would be one of those that nonlinear offers.
Quoted 2 lines
NONLINEAR_OPTIMISEDlooks a bit complicated.
Can replace them with some other name ? Hmm...NONLINEAR_NOREMAP ?
Yes, that is a dumb name, as later I would also see the option to keep V=P+c as an optimisation too. I'll rename it.
Quoted 6 lines
Quoted 4 lines
This patch set is implemented as a proof-of-concept to show that a simplified
CONFIG_NONLINEARbased implementation could provide sufficient flexibility to solve the problems for these systems.Very interesting. But I'm not sure whether we can use more
page->flagsbit :[. I recommend you not to use morepage->flagsbits.
It should not use anymore flags bits. You probabally got that impression as I replace the MAX_NODES_SHIFT (at 6) with a FLAGS_TOTAL_SHIFT (at 8) in 100-cleanup-node-zone. What this is doing is replacing the MAX_NODES_SHIFT and MAX_ZONE_SHIFT (at 2) as a upper bound on the number of bits available, 8 in total. When the nonlinear patch is layered on top we then have NODES, ZONES and SECTIONS competing for space flags, but they cannot consume more than these 8 bits. I then choose to drop the NODE and replace it with SECTION to maintain the size constraint. Obviously on the 64bit systems there is almost no limit and all three are stored.
Thanks for looking.
-apw
--
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>