Skip to contentSkip to conversation

discontig update for linux-ia64-2.5 bk tree

RFC/PATCH Jesse Barnes 2 participants 6 messages Jun 18, 2003 – Jun 19, 2003

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

This patch rewrites part of the discontig code in 2.5 (based on Jack and Kimi's work) to achieve a few things:

o fix bugs so that sn2 will work
o allow the virtual mem map to be used along with discontigmem
o allow generic kernels to work across all platforms

There are a few hunks that remove #ifdef CONFIG_VIRTUAL_MEMMAP lines, but maybe that config option should be removed altogether and made the default? It would be nice to do that for CONFIG_DISCONTIGMEM too, but that would mean touching other architectures, so is less likely to happen. There's also still an issue with CONFIG_FORCE_MAX_ZONEORDER.

I'd appreciate any feedback (testing, comments) that you can provide.

Here's the diffstat:

 arch/ia64/Kconfig            |   40 -----
 arch/ia64/kernel/setup.c     |   35 ++---
 arch/ia64/mm/discontig.c     |  297 +++++++++++++++++++------------------------
 arch/ia64/mm/init.c          |  183 ++++++++++++--------------
 include/asm-ia64/mmzone.h    |  144 +++-----------------
 include/asm-ia64/nodedata.h  |   39 +----
 include/asm-ia64/numa.h      |   16 ++
 include/asm-ia64/page.h      |   14 --
 include/asm-ia64/pgtable.h   |    4
 include/asm-ia64/processor.h |    2
 include/linux/mm.h           |    4
 mm/bootmem.c                 |   36 +++--
 mm/memory.c                  |    2
 mm/page_alloc.c              |    9 -
 14 files changed, 327 insertions(+), 498 deletions(-)

Thanks,
Jesse

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas:

#	           ChangeSet	1.1143  -> 1.1144 
#	  include/linux/mm.h	1.118   -> 1.119  
#	     mm/page_alloc.c	1.154   -> 1.155  

# include/asm-ia64/page.h 1.19 -> 1.20
# arch/ia64/kernel/setup.c 1.51 -> 1.52
# include/asm-ia64/pgtable.h 1.26 -> 1.27
# mm/bootmem.c 1.15 -> 1.16
# include/asm-ia64/numa.h 1.5 -> 1.6
# include/asm-ia64/processor.h 1.46 -> 1.47
# arch/ia64/mm/init.c 1.42 -> 1.43
# mm/memory.c 1.127 -> 1.128
# include/asm-ia64/nodedata.h 1.3 -> 1.4
# arch/ia64/mm/discontig.c 1.4 -> 1.5
# arch/ia64/Kconfig 1.28 -> 1.29
# include/asm-ia64/mmzone.h 1.4 -> 1.5
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/06/17 [email protected] 1.1144

# allow discontig to work in a generic way along with virtual memmap
# --------------------------------------------
#
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Tue Jun 17 14:45:16 2003
+++ b/arch/ia64/Kconfig	Tue Jun 17 14:45:16 2003
@@ -245,8 +245,7 @@

config VIRTUAL_MEM_MAP
bool "Enable Virtual Mem Map"
- depends on !NUMA

-	default y if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
+	default y if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_SGI_SN2

help
Say Y to compile the kernel with support for a virtual mem map. This is an alternate method of supporting large holes in the
@@ -259,8 +258,8 @@
are unsure, say Y.

config IA64_MCA
- bool "Enable IA-64 Machine Check Abort" if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
- default y if IA64_SGI_SN2
+ bool "Enable IA-64 Machine Check Abort"
+ default y if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_SGI_SN2
help
Say Y here to enable machine check support for IA-64. If you're unsure, answer Y.
@@ -292,14 +291,6 @@
depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_SGI_SN2 default y

-config IA64_SGI_SN_DEBUG
- bool "Enable extra debugging code"
- depends on IA64_SGI_SN2
- help

-	  Turns on extra debugging code in the SGI SN (Scalable NUMA) platform
-	  for IA-64.  Unless you are debugging problems on an SGI SN IA-64 box,
-	  say N.

-
config IA64_SGI_SN_SIM
bool "Enable SGI Medusa Simulator Support"
depends on IA64_SGI_SN2
@@ -307,29 +298,6 @@
If you are compiling a kernel that will run under SGI's IA-64 simulator (Medusa) then say Y, otherwise say N.

-config IA64_SGI_AUTOTEST
- bool "Enable autotest (llsc). Option to run cache test instead of booting"
- depends on IA64_SGI_SN2
- help

-	  Build a kernel used for hardware validation. If you include the
-	  keyword "autotest" on the boot command line, the kernel does NOT boot.
-	  Instead, it starts all cpus and runs cache coherency tests instead.

-
- If unsure, say N.
-
-config SERIAL_SGI_L1_PROTOCOL
- bool "Enable protocol mode for the L1 console"
- depends on IA64_SGI_SN2
- help

-	  Uses protocol mode instead of raw mode for the level 1 console on the
-	  SGI SN (Scalable NUMA) platform for IA-64.  If you are compiling for
-	  an SGI SN box then Y is the recommended value, otherwise say N.

-
-config PERCPU_IRQ
- bool
- depends on IA64_SGI_SN2
- default y
-
# On IA-64, we always want an ELF /proc/kcore.
config KCORE_ELF
bool
@@ -355,7 +323,7 @@

config FORCE_MAX_ZONEORDER
int
- default "18"
+ default "11"

config HUGETLB_PAGE
bool "IA-64 Huge TLB Page Support"

arch/ia64/kernel/setup.c +18 -17
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
@@ -137,7 +137,7 @@
 call_pernode_memory (unsigned long start, unsigned long end, void *arg)
 {
 	unsigned long rs, re;
-	void (*func)(unsigned long, unsigned long, int, int);
+	void (*func)(unsigned long, unsigned long, int);
 	int i;
 
 	start = PAGE_ALIGN(start);
@@ -148,22 +148,21 @@
 	func = arg;
 
 	if (!num_memblks) {
-		/*
-		 * This machine doesn't have SRAT, so call func with
-		 * nid=0, bank=0.
-		 */
+		/* No SRAT table, to assume one node (node 0) */
 		if (start < end)
-			(*func)(start, end - start, 0, 0);
+			(*func)(start, end, 0);
 		return;
 	}
 
 	for (i = 0; i < num_memblks; i++) {
-		rs = max(start, node_memblk[i].start_paddr);
-		re = min(end, node_memblk[i].start_paddr+node_memblk[i].size);
+		rs = max(__pa(start), node_memblk[i].start_paddr);
+		re = min(__pa(end), node_memblk[i].start_paddr+node_memblk[i].size);
 
 		if (rs < re)
-			(*func)(rs, re-rs, node_memblk[i].nid,
-				node_memblk[i].bank);
+			(*func)((unsigned long)__va(rs), (unsigned long)__va(re), node_memblk[i].nid);
+
+		if ((unsigned long)__va(re) == end)
+			break;
 	}
 }
 
@@ -179,7 +178,7 @@
 filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
 {
 	unsigned long range_start, range_end, prev_start;
-	void (*func)(unsigned long, unsigned long);
+	void (*func)(unsigned long, unsigned long, int);
 	int i;
 
 #if IGNORE_PFN0
@@ -201,9 +200,9 @@
 
 		if (range_start < range_end)
 #ifdef CONFIG_DISCONTIGMEM
-			call_pernode_memory(__pa(range_start), __pa(range_end), func);
+			call_pernode_memory(range_start, range_end, func);
 #else
-			(*func)(__pa(range_start), range_end - range_start);
+			(*func)(range_start, range_end, 0);
 #endif
 
 		/* nothing more available in this segment */
@@ -703,24 +702,26 @@
 	 * get_free_pages() cannot be used before cpu_init() done.  BSP allocates
 	 * "NR_CPUS" pages for all CPUs to avoid that AP calls get_zeroed_page().
 	 */
+#ifndef CONFIG_DISCONTIGMEM
 	if (smp_processor_id() == 0) {
 		cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, PERCPU_PAGE_SIZE,
 					   __pa(MAX_DMA_ADDRESS));
 		for (cpu = 0; cpu < NR_CPUS; cpu++) {
-			memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
 			__per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start;
 			cpu_data += PERCPU_PAGE_SIZE;
 		}
+		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+			cpu_data = __per_cpu_offset[cpu] + __per_cpu_start;
+			memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
+		}
 	}
+#endif
 	cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 #else /* !CONFIG_SMP */
 	cpu_data = __phys_per_cpu_start;
 #endif /* !CONFIG_SMP */
 
 	cpu_info = cpu_data + ((char *) &__get_cpu_var(cpu_info) - __per_cpu_start);
-#ifdef CONFIG_NUMA
-	cpu_info->node_data = get_node_data_ptr();
-#endif
 
 	get_max_cacheline_size();
 
arch/ia64/mm/discontig.c +133 -164

404 lines not on this page · raw message

arch/ia64/mm/init.c +85 -98

278 lines not on this page · raw message

include/asm-ia64/mmzone.h +22 -122

179 lines not on this page · raw message

include/asm-ia64/nodedata.h +9 -30
diff -Nru a/include/asm-ia64/nodedata.h b/include/asm-ia64/nodedata.h
@@ -13,7 +13,7 @@
 #ifndef _ASM_IA64_NODEDATA_H
 #define _ASM_IA64_NODEDATA_H
 
-
+#include <asm/percpu.h>
 #include <asm/mmzone.h>
 
 /*
@@ -22,15 +22,17 @@
 
 struct pglist_data;
 struct ia64_node_data {
-	short			active_cpu_count;
 	short			node;
+	short			active_cpu_count;
+	/*
+	 * The fields are read-only (after boot). They contain pointers to various structures
+	 * located on other nodes. Ths data is replicated on each node in order to reduce
+	 * off-node references.
+	 */
         struct pglist_data	*pg_data_ptrs[NR_NODES];
-	struct page		*bank_mem_map_base[NR_BANKS];
 	struct ia64_node_data	*node_data_ptrs[NR_NODES];
-	short			node_id_map[NR_BANKS];
 };
 
-
 /*
  * Return a pointer to the node_data structure for the executing cpu.
  */
@@ -40,7 +42,8 @@
 /*
  * Return a pointer to the node_data structure for the specified node.
  */
-#define node_data(node)	(local_node_data->node_data_ptrs[node])
+#define node_data(node) (local_node_data->node_data_ptrs[node])
+#define NODE_DATA(nid) (local_node_data->pg_data_ptrs[nid])
 
 /*
  * Get a pointer to the node_id/node_data for the current cpu.
@@ -48,29 +51,5 @@
  */
 extern int boot_get_local_nodeid(void);
 extern struct ia64_node_data *get_node_data_ptr(void);
-
-/*
- * Given a node id, return a pointer to the pg_data_t for the node.
- * The following 2 macros are similar. 
- *
- * NODE_DATA 	- should be used in all code not related to system
- *		  initialization. It uses pernode data structures to minimize
- *		  offnode memory references. However, these structure are not 
- *		  present during boot. This macro can be used once cpu_init
- *		  completes.
- *
- * BOOT_NODE_DATA
- *		- should be used during system initialization 
- *		  prior to freeing __initdata. It does not depend on the percpu
- *		  area being present.
- *
- * NOTE:   The names of these macros are misleading but are difficult to change
- *	   since they are used in generic linux & on other architecures.
- */
-#define NODE_DATA(nid)		(local_node_data->pg_data_ptrs[nid])
-#define BOOT_NODE_DATA(nid)	boot_get_pg_data_ptr((long)(nid))
-
-struct pglist_data;
-extern struct pglist_data * __init boot_get_pg_data_ptr(long);
 
 #endif /* _ASM_IA64_NODEDATA_H */
include/asm-ia64/numa.h +15 -1
diff -Nru a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h
@@ -15,13 +15,21 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 # include <asm/mmzone.h>
-# define NR_MEMBLKS   (NR_BANKS)
 #else
 # define NR_NODES     (8)
 # define NR_MEMBLKS   (NR_NODES * 8)
 #endif
 
 #include <linux/cache.h>
+#include <linux/threads.h>
+#include <linux/smp.h>
+
+#define NODEMASK_WORDCOUNT       ((NR_NODES+(BITS_PER_LONG-1))/BITS_PER_LONG)
+
+#define NODE_MASK_NONE   { [0 ... ((NR_NODES+BITS_PER_LONG-1)/BITS_PER_LONG)-1] = 0 }
+
+typedef unsigned long   nodemask_t[NODEMASK_WORDCOUNT];
+                                                                                                                             
 extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned;
 extern volatile unsigned long node_to_cpu_mask[NR_NODES] __cacheline_aligned;
 
@@ -63,6 +71,12 @@
 extern int paddr_to_nid(unsigned long paddr);
 
 #define local_nodeid (cpu_to_node_map[smp_processor_id()])
+
+#else /* !CONFIG_NUMA */
+
+#define node_distance(from,to) 10
+#define paddr_to_nid(x) 0
+#define local_nodeid 0
 
 #endif /* CONFIG_NUMA */
 
include/asm-ia64/page.h +6 -8
diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h
@@ -93,18 +93,16 @@
 
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
-#ifndef CONFIG_DISCONTIGMEM
-# ifdef CONFIG_VIRTUAL_MEM_MAP
-   extern int ia64_pfn_valid (unsigned long pfn);
-#  define pfn_valid(pfn)	(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
-# else
-#  define pfn_valid(pfn)	((pfn) < max_mapnr)
-# endif
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+  extern int ia64_pfn_valid (unsigned long pfn);
+# define pfn_valid(pfn)	(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
+#else
+# define pfn_valid(pfn)	((pfn) < max_mapnr)
+#endif
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define page_to_pfn(page)	((unsigned long) (page - mem_map))
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
-#endif
 
 typedef union ia64_va {
 	struct {
include/asm-ia64/pgtable.h +0 -4
diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
@@ -174,7 +174,6 @@
 	return (addr & (local_cpu_data->unimpl_pa_mask)) == 0;
 }
 
-#ifndef CONFIG_DISCONTIGMEM
 /*
  * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel
  * memory.  For the return value to be meaningful, ADDR must be >=
@@ -190,7 +189,6 @@
  */
 #define kern_addr_valid(addr)	(1)
 
-#endif
 
 /*
  * Now come the defines and routines to manage and access the three-level
@@ -237,10 +235,8 @@
 #define pte_none(pte) 			(!pte_val(pte))
 #define pte_present(pte)		(pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
 #define pte_clear(pte)			(pte_val(*(pte)) = 0UL)
-#ifndef CONFIG_DISCONTIGMEM
 /* pte_page() returns the "struct page *" corresponding to the PTE: */
 #define pte_page(pte)			virt_to_page(((pte_val(pte) & _PFN_MASK) + PAGE_OFFSET))
-#endif
 
 #define pmd_none(pmd)			(!pmd_val(pmd))
 #define pmd_bad(pmd)			(!ia64_phys_addr_valid(pmd_val(pmd)))
include/asm-ia64/processor.h +2 -0
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
@@ -185,6 +185,8 @@
 #endif
 #ifdef CONFIG_NUMA
 	struct ia64_node_data *node_data;
+	int nodeid;
+	struct cpuinfo_ia64 *cpu_data[NR_CPUS];
 #endif
 };
 
include/linux/mm.h +0 -4
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
@@ -13,9 +13,7 @@
 #include <linux/rbtree.h>
 #include <linux/fs.h>
 
-#ifndef CONFIG_DISCONTIGMEM          /* Don't use mapnrs, do it properly */
 extern unsigned long max_mapnr;
-#endif
 
 extern unsigned long num_physpages;
 extern void * high_memory;
@@ -391,10 +389,8 @@
 #define VM_FAULT_MINOR	1
 #define VM_FAULT_MAJOR	2
 
-#ifndef CONFIG_DISCONTIGMEM
 /* The array of struct pages - for discontigmem use pgdat->lmem_map */
 extern struct page *mem_map;
-#endif 
 
 extern void show_free_areas(void);
 
mm/bootmem.c +27 -9
diff -Nru a/mm/bootmem.c b/mm/bootmem.c
@@ -48,8 +48,24 @@
 	bootmem_data_t *bdata = pgdat->bdata;
 	unsigned long mapsize = ((end - start)+7)/8;
 
-	pgdat->pgdat_next = pgdat_list;
-	pgdat_list = pgdat;
+
+	/*
+	 * sort pgdat_list so that the lowest one comes first,
+	 * which makes alloc_bootmem_low_pages work as desired.
+	 */
+	if (!pgdat_list || pgdat_list->node_start_pfn > pgdat->node_start_pfn) {
+		pgdat->pgdat_next = pgdat_list;
+		pgdat_list = pgdat;
+	} else {
+		pg_data_t *tmp = pgdat_list;
+		while (tmp->pgdat_next) {
+			if (tmp->pgdat_next->node_start_pfn > pgdat->node_start_pfn)
+				break;
+			tmp = tmp->pgdat_next;
+		}
+		pgdat->pgdat_next = tmp->pgdat_next;
+		tmp->pgdat_next = pgdat;
+	}
 
 	mapsize = (mapsize + (sizeof(long) - 1UL)) & ~(sizeof(long) - 1UL);
 	bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
@@ -115,6 +131,7 @@
 	if (end > bdata->node_low_pfn)
 		BUG();
 
+	/* Record last successful free */
 	if (addr < bdata->last_success)
 		bdata->last_success = addr;
 
@@ -251,32 +268,33 @@
 
 static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
 {
-	struct page *page = pgdat->node_mem_map;
+	struct page *page;
 	bootmem_data_t *bdata = pgdat->bdata;
 	unsigned long i, count, total = 0;
 	unsigned long idx;
-	unsigned long *map; 
+	unsigned long *map;
 
 	if (!bdata->node_bootmem_map) BUG();
 
 	count = 0;
+	page = virt_to_page(phys_to_virt(bdata->node_boot_start));
 	idx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT);
+
 	map = bdata->node_bootmem_map;
 	for (i = 0; i < idx; ) {
 		unsigned long v = ~map[i / BITS_PER_LONG];
 		if (v) {
 			unsigned long m;
-			for (m = 1; m && i < idx; m<<=1, page++, i++) {
+			for (m = 1; m && i < idx; m<<=1, i++) {
 				if (v & m) {
 					count++;
-					ClearPageReserved(page);
-					set_page_count(page, 1);
-					__free_page(page);
+					ClearPageReserved(page+i);
+					set_page_count(page+i, 1);
+					__free_page(page+i);
 				}
 			}
 		} else {
 			i+=BITS_PER_LONG;
-			page += BITS_PER_LONG;
 		}
 	}
 	total += count;
mm/memory.c +0 -2
diff -Nru a/mm/memory.c b/mm/memory.c
@@ -55,11 +55,9 @@
 
 #include <linux/swapops.h>
 
-#ifndef CONFIG_DISCONTIGMEM
 /* use the per-pgdat data instead for discontigmem - mbligh */
 unsigned long max_mapnr;
 struct page *mem_map;
-#endif
 
 unsigned long num_physpages;
 void * high_memory;
mm/page_alloc.c +6 -3
diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c
@@ -57,12 +57,15 @@
  */
 static int bad_range(struct zone *zone, struct page *page)
 {
-	if (page_to_pfn(page) >= zone->zone_start_pfn + zone->spanned_pages)
+	if (page_to_pfn(page) >= zone->zone_start_pfn + zone->spanned_pages) {
 		return 1;
-	if (page_to_pfn(page) < zone->zone_start_pfn)
+	}
+	if (page_to_pfn(page) < zone->zone_start_pfn) {
 		return 1;
-	if (zone != page_zone(page))
+	}
+	if (zone != page_zone(page)) {
 		return 1;
+	}
 	return 0;
 }
 
#1 lore raw

Jesse,

Jesse> There are a few hunks that remove #ifdef CONFIG_VIRTUAL_MEMMAP lines, Jesse> but maybe that config option should be removed altogether and made the Jesse> default?

Why? I want the CONFIG_VIRTUAL_MEMMAP there, because it clearly identifies the code and if we ever have any doubts about its performance effects, we can easily try without virtual mem_map.

-	default y if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
+	default y if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_SGI_SN2

Looks like this should be changed to:

+ default y if !IA64_HP_SIM

Ditto for the other places.

Please declare as "extern":

+int filter_rsvd_memory(unsigned long start, unsigned long end, void *arg);

THanks,

	--david
#2 lore raw
In reply to Jesse Barnes
Quoted 9 lines · David Mosberger

Jesse,

Jesse> There are a few hunks that remove #ifdef CONFIG_VIRTUAL_MEMMAP lines, Jesse> but maybe that config option should be removed altogether and made the Jesse> default?

Why? I want the CONFIG_VIRTUAL_MEMMAP there, because it clearly identifies the code and if we ever have any doubts about its performance effects, we can easily try without virtual mem_map.

That's a good point, but I just figured that if it worked for everyone maybe we should make it unconditional. I don't mind either way though.

Quoted 8 lines
(quoted diff) +1 -1
-	default y if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
+	default y if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_SGI_SN2

Looks like this should be changed to:

(quoted diff) +1 -0
+	default y if !IA64_HP_SIM

Ditto for the other places.

Ok.

Quoted 5 lines

Please declare as "extern":

+int filter_rsvd_memory(unsigned long start, unsigned long end, void *arg);

THanks,

Ok. Thanks for looking at it.
Jesse

#3 lore raw
In reply to Jesse Barnes
Quoted 7 lines · David Mosberger
(quoted diff) +1 -1
-	default y if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
+	default y if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_SGI_SN2

Looks like this should be changed to:

(quoted diff) +1 -0
+	default y if !IA64_HP_SIM
Quoted 7 lines

Ditto for the other places.

Please declare as "extern":

+int filter_rsvd_memory(unsigned long start, unsigned long end, void *arg);

THanks,

Ok, here's another one that addresses those issues (and gets rid of the superfluous page_alloc.c change). We still need to fix the alignment of each node to conform to CONFIG_FORCE_MAX_ZONEORDER and simplify it so that we don't have to export max_mapnr and mem_map from memory.c and mm.h, but other than that, it's in good shape.

Thanks,
Jesse

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas:
# ChangeSet 1.1149 -> 1.1151
# include/linux/mm.h 1.118 -> 1.119
# include/asm-ia64/page.h 1.19 -> 1.20
# arch/ia64/kernel/setup.c 1.51 -> 1.52
# include/asm-ia64/pgtable.h 1.26 -> 1.27
# mm/bootmem.c 1.15 -> 1.16
# include/asm-ia64/numa.h 1.5 -> 1.6
# include/asm-ia64/processor.h 1.46 -> 1.47
# arch/ia64/mm/init.c 1.42 -> 1.43
# mm/memory.c 1.127 -> 1.128
# include/asm-ia64/nodedata.h 1.3 -> 1.4
# arch/ia64/mm/discontig.c 1.4 -> 1.5
# arch/ia64/Kconfig 1.29 -> 1.30
# include/asm-ia64/mmzone.h 1.4 -> 1.5
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/06/18 [email protected] 1.1150

# discontig update
# --------------------------------------------
# 03/06/18	[email protected]	1.1151
# export mem_map and max_mapnr for ia64
# --------------------------------------------
#
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Wed Jun 18 16:53:13 2003
+++ b/arch/ia64/Kconfig	Wed Jun 18 16:53:13 2003
@@ -245,8 +245,7 @@

config VIRTUAL_MEM_MAP
bool "Enable Virtual Mem Map"
- depends on !NUMA
- default y if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
+ default y if !IA64_HP_SIM
help
Say Y to compile the kernel with support for a virtual mem map. This is an alternate method of supporting large holes in the
@@ -259,8 +258,8 @@
are unsure, say Y.

config IA64_MCA
- bool "Enable IA-64 Machine Check Abort" if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
- default y if IA64_SGI_SN2
+ bool "Enable IA-64 Machine Check Abort"
+ default y if !IA64_HP_SIM
help
Say Y here to enable machine check support for IA-64. If you're unsure, answer Y.
@@ -292,43 +291,12 @@
depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_SGI_SN2 default y

-config IA64_SGI_SN_DEBUG
- bool "Enable extra debugging code"
- depends on IA64_SGI_SN2
- help

-	  Turns on extra debugging code in the SGI SN (Scalable NUMA) platform
-	  for IA-64.  Unless you are debugging problems on an SGI SN IA-64 box,
-	  say N.

-
config IA64_SGI_SN_SIM
bool "Enable SGI Medusa Simulator Support"
depends on IA64_SGI_SN2
help
If you are compiling a kernel that will run under SGI's IA-64 simulator (Medusa) then say Y, otherwise say N.
-
-config IA64_SGI_AUTOTEST
- bool "Enable autotest (llsc). Option to run cache test instead of booting"
- depends on IA64_SGI_SN2
- help

-	  Build a kernel used for hardware validation. If you include the
-	  keyword "autotest" on the boot command line, the kernel does NOT boot.
-	  Instead, it starts all cpus and runs cache coherency tests instead.

-
- If unsure, say N.
-
-config SERIAL_SGI_L1_PROTOCOL
- bool "Enable protocol mode for the L1 console"
- depends on IA64_SGI_SN2
- help

-	  Uses protocol mode instead of raw mode for the level 1 console on the
-	  SGI SN (Scalable NUMA) platform for IA-64.  If you are compiling for
-	  an SGI SN box then Y is the recommended value, otherwise say N.

-
-config PERCPU_IRQ
- bool
- depends on IA64_SGI_SN2
- default y

# On IA-64, we always want an ELF /proc/kcore.
config KCORE_ELF

arch/ia64/kernel/setup.c +18 -17
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
@@ -137,7 +137,7 @@
 call_pernode_memory (unsigned long start, unsigned long end, void *arg)
 {
 	unsigned long rs, re;
-	void (*func)(unsigned long, unsigned long, int, int);
+	void (*func)(unsigned long, unsigned long, int);
 	int i;
 
 	start = PAGE_ALIGN(start);
@@ -148,22 +148,21 @@
 	func = arg;
 
 	if (!num_memblks) {
-		/*
-		 * This machine doesn't have SRAT, so call func with
-		 * nid=0, bank=0.
-		 */
+		/* No SRAT table, to assume one node (node 0) */
 		if (start < end)
-			(*func)(start, end - start, 0, 0);
+			(*func)(start, end, 0);
 		return;
 	}
 
 	for (i = 0; i < num_memblks; i++) {
-		rs = max(start, node_memblk[i].start_paddr);
-		re = min(end, node_memblk[i].start_paddr+node_memblk[i].size);
+		rs = max(__pa(start), node_memblk[i].start_paddr);
+		re = min(__pa(end), node_memblk[i].start_paddr+node_memblk[i].size);
 
 		if (rs < re)
-			(*func)(rs, re-rs, node_memblk[i].nid,
-				node_memblk[i].bank);
+			(*func)((unsigned long)__va(rs), (unsigned long)__va(re), node_memblk[i].nid);
+
+		if ((unsigned long)__va(re) == end)
+			break;
 	}
 }
 
@@ -179,7 +178,7 @@
 filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
 {
 	unsigned long range_start, range_end, prev_start;
-	void (*func)(unsigned long, unsigned long);
+	void (*func)(unsigned long, unsigned long, int);
 	int i;
 
 #if IGNORE_PFN0
@@ -201,9 +200,9 @@
 
 		if (range_start < range_end)
 #ifdef CONFIG_DISCONTIGMEM
-			call_pernode_memory(__pa(range_start), __pa(range_end), func);
+			call_pernode_memory(range_start, range_end, func);
 #else
-			(*func)(__pa(range_start), range_end - range_start);
+			(*func)(range_start, range_end, 0);
 #endif
 
 		/* nothing more available in this segment */
@@ -703,24 +702,26 @@
 	 * get_free_pages() cannot be used before cpu_init() done.  BSP allocates
 	 * "NR_CPUS" pages for all CPUs to avoid that AP calls get_zeroed_page().
 	 */
+#ifndef CONFIG_DISCONTIGMEM
 	if (smp_processor_id() == 0) {
 		cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, PERCPU_PAGE_SIZE,
 					   __pa(MAX_DMA_ADDRESS));
 		for (cpu = 0; cpu < NR_CPUS; cpu++) {
-			memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
 			__per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start;
 			cpu_data += PERCPU_PAGE_SIZE;
 		}
+		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+			cpu_data = __per_cpu_offset[cpu] + __per_cpu_start;
+			memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
+		}
 	}
+#endif
 	cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 #else /* !CONFIG_SMP */
 	cpu_data = __phys_per_cpu_start;
 #endif /* !CONFIG_SMP */
 
 	cpu_info = cpu_data + ((char *) &__get_cpu_var(cpu_info) - __per_cpu_start);
-#ifdef CONFIG_NUMA
-	cpu_info->node_data = get_node_data_ptr();
-#endif
 
 	get_max_cacheline_size();
 
arch/ia64/mm/discontig.c +133 -164

404 lines not on this page · raw message

arch/ia64/mm/init.c +85 -98

278 lines not on this page · raw message

include/asm-ia64/mmzone.h +22 -122

179 lines not on this page · raw message

include/asm-ia64/nodedata.h +9 -30
diff -Nru a/include/asm-ia64/nodedata.h b/include/asm-ia64/nodedata.h
@@ -13,7 +13,7 @@
 #ifndef _ASM_IA64_NODEDATA_H
 #define _ASM_IA64_NODEDATA_H
 
-
+#include <asm/percpu.h>
 #include <asm/mmzone.h>
 
 /*
@@ -22,15 +22,17 @@
 
 struct pglist_data;
 struct ia64_node_data {
-	short			active_cpu_count;
 	short			node;
+	short			active_cpu_count;
+	/*
+	 * The fields are read-only (after boot). They contain pointers to various structures
+	 * located on other nodes. Ths data is replicated on each node in order to reduce
+	 * off-node references.
+	 */
         struct pglist_data	*pg_data_ptrs[NR_NODES];
-	struct page		*bank_mem_map_base[NR_BANKS];
 	struct ia64_node_data	*node_data_ptrs[NR_NODES];
-	short			node_id_map[NR_BANKS];
 };
 
-
 /*
  * Return a pointer to the node_data structure for the executing cpu.
  */
@@ -40,7 +42,8 @@
 /*
  * Return a pointer to the node_data structure for the specified node.
  */
-#define node_data(node)	(local_node_data->node_data_ptrs[node])
+#define node_data(node) (local_node_data->node_data_ptrs[node])
+#define NODE_DATA(nid) (local_node_data->pg_data_ptrs[nid])
 
 /*
  * Get a pointer to the node_id/node_data for the current cpu.
@@ -48,29 +51,5 @@
  */
 extern int boot_get_local_nodeid(void);
 extern struct ia64_node_data *get_node_data_ptr(void);
-
-/*
- * Given a node id, return a pointer to the pg_data_t for the node.
- * The following 2 macros are similar. 
- *
- * NODE_DATA 	- should be used in all code not related to system
- *		  initialization. It uses pernode data structures to minimize
- *		  offnode memory references. However, these structure are not 
- *		  present during boot. This macro can be used once cpu_init
- *		  completes.
- *
- * BOOT_NODE_DATA
- *		- should be used during system initialization 
- *		  prior to freeing __initdata. It does not depend on the percpu
- *		  area being present.
- *
- * NOTE:   The names of these macros are misleading but are difficult to change
- *	   since they are used in generic linux & on other architecures.
- */
-#define NODE_DATA(nid)		(local_node_data->pg_data_ptrs[nid])
-#define BOOT_NODE_DATA(nid)	boot_get_pg_data_ptr((long)(nid))
-
-struct pglist_data;
-extern struct pglist_data * __init boot_get_pg_data_ptr(long);
 
 #endif /* _ASM_IA64_NODEDATA_H */
include/asm-ia64/numa.h +15 -1
diff -Nru a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h
@@ -15,13 +15,21 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 # include <asm/mmzone.h>
-# define NR_MEMBLKS   (NR_BANKS)
 #else
 # define NR_NODES     (8)
 # define NR_MEMBLKS   (NR_NODES * 8)
 #endif
 
 #include <linux/cache.h>
+#include <linux/threads.h>
+#include <linux/smp.h>
+
+#define NODEMASK_WORDCOUNT       ((NR_NODES+(BITS_PER_LONG-1))/BITS_PER_LONG)
+
+#define NODE_MASK_NONE   { [0 ... ((NR_NODES+BITS_PER_LONG-1)/BITS_PER_LONG)-1] = 0 }
+
+typedef unsigned long   nodemask_t[NODEMASK_WORDCOUNT];
+                                                                                                                             
 extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned;
 extern volatile unsigned long node_to_cpu_mask[NR_NODES] __cacheline_aligned;
 
@@ -63,6 +71,12 @@
 extern int paddr_to_nid(unsigned long paddr);
 
 #define local_nodeid (cpu_to_node_map[smp_processor_id()])
+
+#else /* !CONFIG_NUMA */
+
+#define node_distance(from,to) 10
+#define paddr_to_nid(x) 0
+#define local_nodeid 0
 
 #endif /* CONFIG_NUMA */
 
include/asm-ia64/page.h +6 -8
diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h
@@ -93,18 +93,16 @@
 
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
-#ifndef CONFIG_DISCONTIGMEM
-# ifdef CONFIG_VIRTUAL_MEM_MAP
-   extern int ia64_pfn_valid (unsigned long pfn);
-#  define pfn_valid(pfn)	(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
-# else
-#  define pfn_valid(pfn)	((pfn) < max_mapnr)
-# endif
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+  extern int ia64_pfn_valid (unsigned long pfn);
+# define pfn_valid(pfn)	(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
+#else
+# define pfn_valid(pfn)	((pfn) < max_mapnr)
+#endif
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define page_to_pfn(page)	((unsigned long) (page - mem_map))
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
-#endif
 
 typedef union ia64_va {
 	struct {
include/asm-ia64/pgtable.h +0 -4
diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
@@ -174,7 +174,6 @@
 	return (addr & (local_cpu_data->unimpl_pa_mask)) == 0;
 }
 
-#ifndef CONFIG_DISCONTIGMEM
 /*
  * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel
  * memory.  For the return value to be meaningful, ADDR must be >=
@@ -190,7 +189,6 @@
  */
 #define kern_addr_valid(addr)	(1)
 
-#endif
 
 /*
  * Now come the defines and routines to manage and access the three-level
@@ -237,10 +235,8 @@
 #define pte_none(pte) 			(!pte_val(pte))
 #define pte_present(pte)		(pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
 #define pte_clear(pte)			(pte_val(*(pte)) = 0UL)
-#ifndef CONFIG_DISCONTIGMEM
 /* pte_page() returns the "struct page *" corresponding to the PTE: */
 #define pte_page(pte)			virt_to_page(((pte_val(pte) & _PFN_MASK) + PAGE_OFFSET))
-#endif
 
 #define pmd_none(pmd)			(!pmd_val(pmd))
 #define pmd_bad(pmd)			(!ia64_phys_addr_valid(pmd_val(pmd)))
include/asm-ia64/processor.h +2 -0
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
@@ -185,6 +185,8 @@
 #endif
 #ifdef CONFIG_NUMA
 	struct ia64_node_data *node_data;
+	int nodeid;
+	struct cpuinfo_ia64 *cpu_data[NR_CPUS];
 #endif
 };
 
include/linux/mm.h +2 -2
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
@@ -13,7 +13,7 @@
 #include <linux/rbtree.h>
 #include <linux/fs.h>
 
-#ifndef CONFIG_DISCONTIGMEM          /* Don't use mapnrs, do it properly */
+#if !defined(CONFIG_DISCONTIGMEM) || defined(CONFIG_IA64) /* Don't use mapnrs, do it properly */
 extern unsigned long max_mapnr;
 #endif
 
@@ -391,7 +391,7 @@
 #define VM_FAULT_MINOR	1
 #define VM_FAULT_MAJOR	2
 
-#ifndef CONFIG_DISCONTIGMEM
+#if !defined(CONFIG_DISCONTIGMEM) || defined(CONFIG_IA64)
 /* The array of struct pages - for discontigmem use pgdat->lmem_map */
 extern struct page *mem_map;
 #endif 
mm/bootmem.c +27 -9
diff -Nru a/mm/bootmem.c b/mm/bootmem.c
@@ -48,8 +48,24 @@
 	bootmem_data_t *bdata = pgdat->bdata;
 	unsigned long mapsize = ((end - start)+7)/8;
 
-	pgdat->pgdat_next = pgdat_list;
-	pgdat_list = pgdat;
+
+	/*
+	 * sort pgdat_list so that the lowest one comes first,
+	 * which makes alloc_bootmem_low_pages work as desired.
+	 */
+	if (!pgdat_list || pgdat_list->node_start_pfn > pgdat->node_start_pfn) {
+		pgdat->pgdat_next = pgdat_list;
+		pgdat_list = pgdat;
+	} else {
+		pg_data_t *tmp = pgdat_list;
+		while (tmp->pgdat_next) {
+			if (tmp->pgdat_next->node_start_pfn > pgdat->node_start_pfn)
+				break;
+			tmp = tmp->pgdat_next;
+		}
+		pgdat->pgdat_next = tmp->pgdat_next;
+		tmp->pgdat_next = pgdat;
+	}
 
 	mapsize = (mapsize + (sizeof(long) - 1UL)) & ~(sizeof(long) - 1UL);
 	bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
@@ -115,6 +131,7 @@
 	if (end > bdata->node_low_pfn)
 		BUG();
 
+	/* Record last successful free */
 	if (addr < bdata->last_success)
 		bdata->last_success = addr;
 
@@ -251,32 +268,33 @@
 
 static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
 {
-	struct page *page = pgdat->node_mem_map;
+	struct page *page;
 	bootmem_data_t *bdata = pgdat->bdata;
 	unsigned long i, count, total = 0;
 	unsigned long idx;
-	unsigned long *map; 
+	unsigned long *map;
 
 	if (!bdata->node_bootmem_map) BUG();
 
 	count = 0;
+	page = virt_to_page(phys_to_virt(bdata->node_boot_start));
 	idx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT);
+
 	map = bdata->node_bootmem_map;
 	for (i = 0; i < idx; ) {
 		unsigned long v = ~map[i / BITS_PER_LONG];
 		if (v) {
 			unsigned long m;
-			for (m = 1; m && i < idx; m<<=1, page++, i++) {
+			for (m = 1; m && i < idx; m<<=1, i++) {
 				if (v & m) {
 					count++;
-					ClearPageReserved(page);
-					set_page_count(page, 1);
-					__free_page(page);
+					ClearPageReserved(page+i);
+					set_page_count(page+i, 1);
+					__free_page(page+i);
 				}
 			}
 		} else {
 			i+=BITS_PER_LONG;
-			page += BITS_PER_LONG;
 		}
 	}
 	total += count;
mm/memory.c +1 -1
diff -Nru a/mm/memory.c b/mm/memory.c
@@ -55,7 +55,7 @@
 
 #include <linux/swapops.h>
 
-#ifndef CONFIG_DISCONTIGMEM
+#if !defined(CONFIG_DISCONTIGMEM) || defined(CONFIG_IA64) /* ia64 needs them for now - jbarnes */
 /* use the per-pgdat data instead for discontigmem - mbligh */
 unsigned long max_mapnr;
 struct page *mem_map;
#4 lore raw
In reply to Jesse Barnes

I missed this on first reading:

for (cpu = 0; cpu < NR_CPUS; cpu++) {
- memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
__per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; cpu_data += PERCPU_PAGE_SIZE;
}
+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ cpu_data = __per_cpu_offset[cpu] + __per_cpu_start;
+ memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
+ }

What's the point of this?

The patch still removes CONFIG_VIRTUAL_MEM_MAP.

Also, please note that I don't want to add any ia64 patches that create additional dependencies on core code (I'm trying to sync things such that ia64 builds out of the box). So before submitting ia64-specific changes, please make sure the core-code is ready for it.

	--david
#5 lore raw
In reply to Jesse Barnes
Quoted 12 lines · David Mosberger

I missed this on first reading:

arch/ia64/kernel/setup.c +4 -1
 		for (cpu = 0; cpu < NR_CPUS; cpu++) {
-			memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
 			__per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start;
 			cpu_data += PERCPU_PAGE_SIZE;
 		}
+		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+			cpu_data = __per_cpu_offset[cpu] + __per_cpu_start;
+			memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
+		}
Quoted 1 line

What's the point of this?

Arg, I saw that when I got my copy back (along with a couple of other things). I'll fix them up.

Quoted 1 line

The patch still removes CONFIG_VIRTUAL_MEM_MAP.

...

Quoted 4 lines

Also, please note that I don't want to add any ia64 patches that create additional dependencies on core code (I'm trying to sync things such that ia64 builds out of the box). So before submitting ia64-specific changes, please make sure the core-code is ready for it.

Ok. I'll try to get the bootmem changes in first.

Thanks,
Jesse