From kanoj Thu Aug 10 01:02:52 2000
Received: (from kanoj@localhost)
	by google.engr.sgi.com (SGI-8.9.3/8.9.3) id BAA23936;
	Thu, 10 Aug 2000 01:02:51 -0700 (PDT)
From: Kanoj Sarcar <kanoj>
Message-Id: <200008100802.BAA23936@google.engr.sgi.com>
Subject: [PATCH]test6: mem_map layout flexibility for DISCONTIGMEM
To: torvalds@transmeta.com
Date: Thu, 10 Aug 2000 01:02:51 -0700 (PDT)
Cc: kanoj (Kanoj Sarcar)
X-Mailer: ELM [version 2.5 PL2]
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Status: OR

Linus,

I sent this patch to you yesterday. This is the culmination of all the
previous patches that deleted pte_pagenr, MAP_NR and max_mapnr from the 
generic kernel, and is needed for ARM/mips64/ia64 DISCONTIGMEM code 
optimization. 

Did you get a conflict while applying the patch, and thus left it out
of test6? I applied the patch against test6, and it seems to apply fine.
Or were you planning to put the patch into test7? 

Let me know if you think the patch is too intrusive and thus not 2.4
material. Or if you want me to recode it in some way ...

I am appending the patch and the reasoning for its neccessity.

Thanks.

Kanoj

From kanoj Wed Aug  9 16:27:01 2000
Received: (from kanoj@localhost)
	by google.engr.sgi.com (SGI-8.9.3/8.9.3) id QAA28379;
	Wed, 9 Aug 2000 16:27:00 -0700 (PDT)
From: Kanoj Sarcar <kanoj>
Message-Id: <200008092327.QAA28379@google.engr.sgi.com>
Subject: [PATCH]test6-pre10: mem_map layout flexibility for DISCONTIGMEM
To: torvalds@transmeta.com
Date: Wed, 9 Aug 2000 16:27:00 -0700 (PDT)
Cc: kanoj (Kanoj Sarcar)
X-Mailer: ELM [version 2.5 PL2]
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Status: OR

Linus,

Thank you for patiently including all the recent changes I have been
sending to you (specially when I caused compile breakages :-(). 
Hopefully, this should be the last patch to the generic kernel for
DISCONTIGMEM, for now. 

This patch aims to give arch code flexibility in laying out its
mem_map array. This will greatly help in simplifying virt_to_page
in some cases. For example, if the node size is 64Mb, the arch code
might decide to place the mem_map starting from 4Mb into the node. 

Then, for kernel direct mapped address v,

start_of_node = (((v)/64Mb)*64Mb)
start_of_mmap = start_of_node + 4Mb
index_of_page_in_node = (v - start_of_node) << PAGE_SHIFT
#define virt_to_page(v) (struct page *)start_of_mmap + index_of_page_in_node

Let me know if the patch looks okay or you want me to recode it.

Thanks.

Kanoj

--- linux-t6p10/mm/page_alloc.c	Wed Aug  9 15:42:01 2000
+++ linux-discontig/mm/page_alloc.c	Wed Aug  9 15:50:13 2000
@@ -532,9 +532,9 @@
  */
 void __init free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap,
 	unsigned long *zones_size, unsigned long zone_start_paddr, 
-	unsigned long *zholes_size)
+	unsigned long *zholes_size, struct page *lmem_map)
 {
-	struct page *p, *lmem_map;
+	struct page *p;
 	unsigned long i, j;
 	unsigned long map_size;
 	unsigned long totalpages, offset, realtotalpages;
@@ -580,9 +580,11 @@
 	 * boundary, so that MAP_NR works.
 	 */
 	map_size = (totalpages + 1)*sizeof(struct page);
-	lmem_map = (struct page *) alloc_bootmem_node(nid, map_size);
-	lmem_map = (struct page *)(PAGE_OFFSET + 
+	if (lmem_map == (struct page *)0) {
+		lmem_map = (struct page *) alloc_bootmem_node(nid, map_size);
+		lmem_map = (struct page *)(PAGE_OFFSET + 
 			MAP_ALIGN((unsigned long)lmem_map - PAGE_OFFSET));
+	}
 	*gmap = pgdat->node_mem_map = lmem_map;
 	pgdat->node_size = totalpages;
 	pgdat->node_start_paddr = zone_start_paddr;
@@ -664,7 +666,7 @@
 
 void __init free_area_init(unsigned long *zones_size)
 {
-	free_area_init_core(0, NODE_DATA(0), &mem_map, zones_size, 0, 0);
+	free_area_init_core(0, NODE_DATA(0), &mem_map, zones_size, 0, 0, 0);
 }
 
 static int __init setup_mem_frac(char *str)
--- linux-t6p10/include/linux/mmzone.h	Thu Jul 27 17:02:02 2000
+++ linux-discontig/include/linux/mmzone.h	Wed Aug  9 15:54:11 2000
@@ -99,9 +99,11 @@
  * The following two are not meant for general usage. They are here as
  * prototypes for the discontig memory code.
  */
+struct page;
 extern void show_free_areas_core(int);
 extern void free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap,
-  unsigned long *zones_size, unsigned long paddr, unsigned long *zholes_size);
+  unsigned long *zones_size, unsigned long paddr, unsigned long *zholes_size,
+  struct page *pmap);
 
 #ifndef CONFIG_DISCONTIGMEM
 
--- linux-t6p10/mm/numa.c	Wed Aug  9 15:42:01 2000
+++ linux-discontig/mm/numa.c	Wed Aug  9 15:55:15 2000
@@ -21,12 +21,12 @@
  * at a considerably higher value than 0. Examples are Super-H, ARM, m68k.
  * Should be invoked with paramters (0, 0, unsigned long *[], start_paddr).
  */
-void __init free_area_init_node(int nid, pg_data_t *pgdat, 
+void __init free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
 	unsigned long *zones_size, unsigned long zone_start_paddr, 
 	unsigned long *zholes_size)
 {
 	free_area_init_core(0, NODE_DATA(0), &mem_map, zones_size, 
-						zone_start_paddr, zholes_size);
+				zone_start_paddr, zholes_size, pmap);
 }
 
 #endif /* !CONFIG_DISCONTIGMEM */
@@ -55,7 +55,7 @@
 /*
  * Nodes can be initialized parallely, in no particular order.
  */
-void __init free_area_init_node(int nid, pg_data_t *pgdat, 
+void __init free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
 	unsigned long *zones_size, unsigned long zone_start_paddr, 
 	unsigned long *zholes_size)
 {
@@ -66,7 +66,7 @@
 		mem_map = (mem_map_t *)PAGE_OFFSET;
 
 	free_area_init_core(nid, pgdat, &discard, zones_size, zone_start_paddr,
-						zholes_size);
+					zholes_size, pmap);
 	pgdat->node_id = nid;
 
 	/*
--- linux-t6p10/include/linux/mm.h	Wed Aug  9 15:42:01 2000
+++ linux-discontig/include/linux/mm.h	Wed Aug  9 15:56:29 2000
@@ -375,7 +375,7 @@
 extern int check_pgt_cache(void);
 
 extern void free_area_init(unsigned long * zones_size);
-extern void free_area_init_node(int nid, pg_data_t *pgdat, 
+extern void free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
 	unsigned long * zones_size, unsigned long zone_start_paddr, 
 	unsigned long *zholes_size);
 extern void mem_init(void);
--- linux-t6p10/arch/arm/mm/init.c	Wed Aug  9 15:41:59 2000
+++ linux-discontig/arch/arm/mm/init.c	Wed Aug  9 15:56:37 2000
@@ -523,7 +523,7 @@
 			zhole_size[0] -= mi->bank[i].size >> PAGE_SHIFT;
 		}
 
-		free_area_init_node(node, pgdat, zone_size,
+		free_area_init_node(node, pgdat, 0, zone_size,
 				bdata->node_boot_start, zhole_size);
 	}
 
--- linux-t6p10/arch/mips64/sgi-ip27/ip27-memory.c	Wed Aug  9 15:42:00 2000
+++ linux-discontig/arch/mips64/sgi-ip27/ip27-memory.c	Wed Aug  9 15:56:43 2000
@@ -242,7 +242,7 @@
 		pfn_t end_pfn = node_getmaxclick(node);
 
 		zones_size[ZONE_DMA] = end_pfn + 1 - start_pfn;
-		free_area_init_node(node, NODE_DATA(node), zones_size, 
+		free_area_init_node(node, NODE_DATA(node), 0, zones_size, 
 						start_pfn << PAGE_SHIFT, 0);
 		if ((PLAT_NODE_DATA_STARTNR(node) + 
 					PLAT_NODE_DATA_SIZE(node)) > pagenr)
--- linux-t6p10/arch/sh/mm/init.c	Wed Aug  9 15:42:00 2000
+++ linux-discontig/arch/sh/mm/init.c	Wed Aug  9 15:56:49 2000
@@ -227,7 +227,7 @@
 			zones_size[ZONE_DMA] = max_dma - start_pfn;
 			zones_size[ZONE_NORMAL] = low - max_dma;
 		}
-		free_area_init_node(0, 0, zones_size, __MEMORY_START, 0);
+		free_area_init_node(0, 0, 0, zones_size, __MEMORY_START, 0);
  	}
 }
 
--- linux-t6p10/arch/sparc64/mm/init.c	Wed Aug  9 15:42:00 2000
+++ linux-discontig/arch/sparc64/mm/init.c	Wed Aug  9 15:56:56 2000
@@ -1029,7 +1029,7 @@
 		zones_size[ZONE_DMA] = npages;
 		zholes_size[ZONE_DMA] = npages - pages_avail;
 
-		free_area_init_node(0, NULL, zones_size,
+		free_area_init_node(0, NULL, NULL, zones_size,
 				    phys_base, zholes_size);
 	}
 


