Skip to contentSkip to conversation

another discontig patch

PATCH Christoph Hellwig 7 participants 15 messages Jun 21, 2003 – Jul 21, 2003

Subsystems (2)
lore
Share & tools
lore
#0 lore raw
Quoted 10 lines · Jesse Barnes
(quoted diff) +2 -0
@@ -703,6 +702,8 @@
 	 * 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
+	/* for discontig machines, we do this in discontig.c */
 	if (smp_processor_id() = 0) {
 		cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, PERCPU_PAGE_SIZE,
 					   __pa(MAX_DMA_ADDRESS));

Review line 720

Quoted 8 lines
(quoted diff) +1 -0
@@ -712,15 +713,13 @@
 			cpu_data += PERCPU_PAGE_SIZE;
 		}
 	}
+#endif
 	cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 #else /* !CONFIG_SMP */
 	cpu_data = __phys_per_cpu_start;
 #endif /* !CONFIG_SMP */

Maybe this whole code should better be abstracted out then? Also the use of smp_processor_id() here is not preempt-safe but I 'm not sure whether preemption is already enabled at that point.

Review line 725

Quoted 5 lines
(quoted diff) +5 -0
+static struct ia64_node_data	*boot_node_data[NR_NODES] __initdata;
+static pg_data_t		*pg_data_ptr[NR_NODES] __initdata;
+static bootmem_data_t		bdata[NR_NODES] __initdata;
+static unsigned long		boot_pernode[NR_NODES] __initdata;
+static unsigned long		boot_pernodesize[NR_NODES] __initdata;

Maybe it's time for special pernode data like the percpu data? Okay, okay, not revelant for this patch yet...

Quoted 3 lines

struct page *zero_page_memmap_ptr; /* map entry for zero page */

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

Move this to a header?

Review

Quoted 10 lines
(quoted diff) +10 -0
+#if defined(CONFIG_VIRTUAL_MEM_MAP) && !defined(CONFIG_DISCONTIGMEM)
+  extern int ia64_pfn_valid (unsigned long pfn);
+# define pfn_valid(pfn)	(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
+#elif defined(CONFIG_VIRTUAL_MEM_MAP) && defined(CONFIG_DISCONTIGMEM)
+  extern int ia64_pfn_valid (unsigned long pfn);
+  extern unsigned long max_low_pfn;
+# define pfn_valid(pfn)	(((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
+#else
+# define pfn_valid(pfn)	((pfn) < max_mapnr)
+#endif

Hmm, this ifdef mess look ugly. Can't we use max_low_pfn for the !CONFIG_DISCONTIGMEM case, too and simp;ify it to something like:

#if defined(CONFIG_VIRTUAL_MEM_MAP)
extern int ia64_pfn_valid(unsigned long pfn);
#else

# define ia64_pfn_valid(pfn)	(1)
#endif

#define pfn_valid(pfn) (((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))

Review

Quoted 10 lines
(quoted diff) +10 -0
+
+#if defined(CONFIG_DISCONTIGMEM) && defined(CONFIG_VIRTUAL_MEM_MAP)
+  extern struct page *vmem_map;
+# define pfn_to_page(pfn)	(vmem_map + (pfn))
+# define page_to_pfn(page)	((unsigned long) (page - vmem_map))
+#else
+# define pfn_to_page(pfn)	(mem_map + (pfn))
+# define page_to_pfn(page)	((unsigned long) (page - mem_map))
+#endif /* CONFIG_DISCONTIGMEM && CONFIG_VIRTUAL_MEM_MAP */
+

Hmm, doesn't CONFIG_VIRTUAL_MEM_MAP && !CONFIG_DISCONTIGMEM need vmem_map also. Again, the ifdef mess is horrible :)

What about:

#ifndef CONFIG_VIRTUAL_MEM_MAP
#define vmem_map mem_map
#endif

#define pfn_to_page(pfn) (vmem_map + (pfn))
#define page_to_pfn(page) ((unsigned long) (page - vmem_map))

In fact I wonder what's so special about mem_map that the symbol can't be used for the vmalloc'ed version..

BTW, what about per-node memmaps for SN2 like it's done for NUMAQ?

Review

Quoted 5 lines

#ifdef CONFIG_NUMA

(quoted diff) +2 -0
 	struct ia64_node_data *node_data;
+	int nodeid;
+	struct cpuinfo_ia64 *cpu_data[NR_CPUS];
 #endif

Should the big array be before the nodeid field?

#1 lore raw
Quoted 5 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+static struct ia64_node_data	*boot_node_data[NR_NODES] __initdata;
+static pg_data_t		*pg_data_ptr[NR_NODES] __initdata;
+static bootmem_data_t		bdata[NR_NODES] __initdata;
+static unsigned long		boot_pernode[NR_NODES] __initdata;
+static unsigned long		boot_pernodesize[NR_NODES] __initdata;

The only use that I can *see* (without looking very hard) for pg_data_ptr is as pg_data_ptr[node]->bdata, for which you already have bdata[node], don't you? The fact that you have both pg_data_ptr and pg_data_ptrs, which seem to do the same thing, but one as initdata, and one not, is also rather confusing ...

memcpy(boot_node_data[0]->pg_data_ptrs, pg_data_ptr, sizeof(pg_data_ptr));

hmmm.

And aren't boot_pernode and boot_pernodesize really part of bdata? Seems like there's a lot of complexity in order to save a couple of pointer dereferences ... during boot ;-) But maybe I'm just misreading it ;-)

Quoted 7 lines

Maybe it's time for special pernode data like the percpu data? Okay, okay, not revelant for this patch yet...

# ifndef CONFIG_VIRTUAL_MEM_MAP
# define	vmem_map		mem_map
# endif
Quoted 7 lines
# define pfn_to_page(pfn)	(vmem_map + (pfn))
# define page_to_pfn(page)	((unsigned long) (page - vmem_map))

In fact I wonder what's so special about mem_map that the symbol can't be used for the vmalloc'ed version..

BTW, what about per-node memmaps for SN2 like it's done for NUMAQ?

I really don't see how you *can't* do that, and have it still work. If the mem_map is placed in node local memory, and not a size that happens to be a complete number of pages, even if you pack it down into a vmem_map, it's still not contiguous. So adding a pfn (physical page frame number) to the base of vmem_map can NOT give you the correct address.

Presumably this *is* working for you ... but I'm buggered if I know how ;-) Maybe I just need more coffee ;-)

Thanks,

M.

#2 lore raw
In reply to Christoph Hellwig

Thanks for looking at this, Christoph. Comments below.

Quoted 8 lines · Christoph Hellwig
Quoted 3 lines · Jesse Barnes

#else /* !CONFIG_SMP */
cpu_data = __phys_per_cpu_start;
#endif /* !CONFIG_SMP */

Maybe this whole code should better be abstracted out then? Also the use of smp_processor_id() here is not preempt-safe but I 'm not sure whether preemption is already enabled at that point.

I think we're ok preempt wise here, but you're right that it could probably be abstracted a bit. The issue is that we need to create per-node data structures containing each node's info before the per-cpu stuff is initialized, so we do it all before the bootmem allocator is even setup while we discover memory (see discontig.c:find_pernode_space() I think).

Quoted 8 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+static struct ia64_node_data	*boot_node_data[NR_NODES] __initdata;
+static pg_data_t		*pg_data_ptr[NR_NODES] __initdata;
+static bootmem_data_t		bdata[NR_NODES] __initdata;
+static unsigned long		boot_pernode[NR_NODES] __initdata;
+static unsigned long		boot_pernodesize[NR_NODES] __initdata;

Maybe it's time for special pernode data like the percpu data? Okay, okay, not revelant for this patch yet...

It's already there. It's really necessary to get decent performance, and you have to watch out for cache aliasing effects.

Quoted 3 lines
Quoted 1 line

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

Move this to a header?

Yeah, maybe it should be in asm/page.h? Or maybe we need an asm/discontig.h?

Quoted 5 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+# define pfn_valid(pfn)	((pfn) < max_mapnr)
+#endif

Hmm, this ifdef mess look ugly. Can't we use max_low_pfn for the !CONFIG_DISCONTIGMEM case, too and simp;ify it to something like:

Agreed, no question. I think this could use some additional cleanup.

Quoted 8 lines

#if defined(CONFIG_VIRTUAL_MEM_MAP)
extern int ia64_pfn_valid(unsigned long pfn);
#else

# define ia64_pfn_valid(pfn)	(1)
#endif

#define pfn_valid(pfn) (((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))

Quoted 10 lines

Review

Quoted 10 lines
(quoted diff) +10 -0
+
+#if defined(CONFIG_DISCONTIGMEM) && defined(CONFIG_VIRTUAL_MEM_MAP)
+  extern struct page *vmem_map;
+# define pfn_to_page(pfn)	(vmem_map + (pfn))
+# define page_to_pfn(page)	((unsigned long) (page - vmem_map))
+#else
+# define pfn_to_page(pfn)	(mem_map + (pfn))
+# define page_to_pfn(page)	((unsigned long) (page - mem_map))
+#endif /* CONFIG_DISCONTIGMEM && CONFIG_VIRTUAL_MEM_MAP */
+

Though I'm not sure if this is the right way to do it... If discontig on ia64 is going to depend on virtual mem map, then making this one #ifdef somehow is probably best.

Quoted 9 lines

Hmm, doesn't CONFIG_VIRTUAL_MEM_MAP && !CONFIG_DISCONTIGMEM need vmem_map also. Again, the ifdef mess is horrible :)

What about:

#ifndef CONFIG_VIRTUAL_MEM_MAP
#define vmem_map mem_map
#endif

Quoted 5 lines

#define pfn_to_page(pfn) (vmem_map + (pfn))
#define page_to_pfn(page) ((unsigned long) (page - vmem_map))

In fact I wonder what's so special about mem_map that the symbol can't be used for the vmalloc'ed version..

Don't know, I'll have to look some more.

Quoted 1 line

BTW, what about per-node memmaps for SN2 like it's done for NUMAQ?

AFAIK, the per-node memmaps index into the big virtual memmap, but I'd have to look at it some more. If we made per-node memory maps, then we probably wouldn't need to use the virtual mem map, except that it makes dealing with holes a bit easier (since on sn2 even memory within a node isn't contiguous, and there are big holes between nodes).

Quoted 7 lines

Review

Quoted 5 lines

#ifdef CONFIG_NUMA

(quoted diff) +2 -0
 	struct ia64_node_data *node_data;
+	int nodeid;
+	struct cpuinfo_ia64 *cpu_data[NR_CPUS];
 #endif

Should the big array be before the nodeid field?

Good catch, probably not. :)

Thanks,
Jesse

#3 lore raw
In reply to Christoph Hellwig
Quoted 11 lines · Martin J. Bligh
Quoted 5 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+static struct ia64_node_data	*boot_node_data[NR_NODES] __initdata;
+static pg_data_t		*pg_data_ptr[NR_NODES] __initdata;
+static bootmem_data_t		bdata[NR_NODES] __initdata;
+static unsigned long		boot_pernode[NR_NODES] __initdata;
+static unsigned long		boot_pernodesize[NR_NODES] __initdata;

The only use that I can *see* (without looking very hard) for pg_data_ptr is as pg_data_ptr[node]->bdata, for which you already have bdata[node], don't you? The fact that you have both pg_data_ptr and pg_data_ptrs, which seem to do the same thing, but one as initdata, and one not, is also rather confusing ...

Yeah, that's one thing that I keep meaning to remove, but didn't in the initial versions to keep the 2.4 and 2.5 patches as close as possible.

Quoted 8 lines

memcpy(boot_node_data[0]->pg_data_ptrs, pg_data_ptr, sizeof(pg_data_ptr));

hmmm.

And aren't boot_pernode and boot_pernodesize really part of bdata? Seems like there's a lot of complexity in order to save a couple of pointer dereferences ... during boot ;-) But maybe I'm just misreading it ;-)

Well, there's definitely some pointer magic going on here, but I think we use that stuff once the system is up as well, though from a different pointer.

Quoted 23 lines
Quoted 8 lines

Maybe it's time for special pernode data like the percpu data? Okay, okay, not revelant for this patch yet...

# ifndef CONFIG_VIRTUAL_MEM_MAP
# define	vmem_map		mem_map
# endif
Quoted 7 lines
# define pfn_to_page(pfn)	(vmem_map + (pfn))
# define page_to_pfn(page)	((unsigned long) (page - vmem_map))

In fact I wonder what's so special about mem_map that the symbol can't be used for the vmalloc'ed version..

BTW, what about per-node memmaps for SN2 like it's done for NUMAQ?

I really don't see how you *can't* do that, and have it still work. If the mem_map is placed in node local memory, and not a size that happens to be a complete number of pages, even if you pack it down into a vmem_map, it's still not contiguous. So adding a pfn (physical page frame number) to the base of vmem_map can NOT give you the correct address.

Quoted 2 lines

Presumably this *is* working for you ... but I'm buggered if I know how ;-) Maybe I just need more coffee ;-)

No, there are some mixed metaphors here for sure (at least, as far as I understand it!) :). You can find stuff either using the global vmemmap or the per-node maps I think, but honestly, I'm still coming up to speed on this code myself, Jack and Kimi are the real experts.

Thanks,
Jesse

#4 lore raw
In reply to Christoph Hellwig
Quoted 12 lines
Quoted 11 lines
Quoted 5 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+static struct ia64_node_data	*boot_node_data[NR_NODES] __initdata;
+static pg_data_t		*pg_data_ptr[NR_NODES] __initdata;
+static bootmem_data_t		bdata[NR_NODES] __initdata;
+static unsigned long		boot_pernode[NR_NODES] __initdata;
+static unsigned long		boot_pernodesize[NR_NODES] __initdata;

The only use that I can *see* (without looking very hard) for pg_data_ptr is as pg_data_ptr[node]->bdata, for which you already have bdata[node], don't you? The fact that you have both pg_data_ptr and pg_data_ptrs, which seem to do the same thing, but one as initdata, and one not, is also rather confusing ...

Quoted 2 lines

Yeah, that's one thing that I keep meaning to remove, but didn't in the initial versions to keep the 2.4 and 2.5 patches as close as possible.

OK, I don't think it's something you're introducing with your patch, so it's probably best done separately anyway - you seem to be making the current situation better in general ;-)

Quoted 9 lines
Quoted 9 lines
Quoted 1 line

BTW, what about per-node memmaps for SN2 like it's done for NUMAQ?

I really don't see how you *can't* do that, and have it still work. If the mem_map is placed in node local memory, and not a size that happens to be a complete number of pages, even if you pack it down into a vmem_map, it's still not contiguous. So adding a pfn (physical page frame number) to the base of vmem_map can NOT give you the correct address.

Quoted 7 lines
Quoted 2 lines

Presumably this *is* working for you ... but I'm buggered if I know how ;-) Maybe I just need more coffee ;-)

No, there are some mixed metaphors here for sure (at least, as far as I understand it!) :). You can find stuff either using the global vmemmap or the per-node maps I think, but honestly, I'm still coming up to speed on this code myself, Jack and Kimi are the real experts.

OK. Am I mistaken in thinking that the point of vmem_map is to skip over physical holes in RAM? If not, then disregard the following ;-) Perhaps it's just about node locality of the struct pages, but that seems odd?

Maybe if the start end of memory areas are always hitting boundaries aligned on PAGE_SIZE number of pages, (ie 16MB for 4K pages), then your mem_map is always page aligned because it's in (sizeof (struct page) * PAGE_SIZE) chunks. If you (plural) are relying on that, then I think it needs a huge stinking comment - isn't terribly obvious to innocent bystanders ;-)

Whilst that would enable you to make the array node_local, you still can't just add a pfn to the base as an offset anyway, which is what it looks like you were doing - that assumes it's all contig. eg this:

pfn_to_page(pfn) (vmem_map + (pfn))

Unless you somehow warped the definition of pfn into a contiguous version of the space, in which case, I think people's heads may explode ... we've always had pfn = phys_addr / PAGE_SIZE as an identity.

M.

#5 lore raw
In reply to Christoph Hellwig
Quoted 2 lines · someone
Quoted 2 lines
# define pfn_to_page(pfn)	(vmem_map + (pfn))
# define page_to_pfn(page)	((unsigned long) (page - vmem_map))
Quoted 8 lines · Martin J. Bligh

I really don't see how you *can't* do that, and have it still work. If the mem_map is placed in node local memory, and not a size that happens to be a complete number of pages, even if you pack it down into a vmem_map, it's still not contiguous. So adding a pfn (physical page frame number) to the base of vmem_map can NOT give you the correct address.
Presumably this *is* working for you ... but I'm buggered if I know how ;-) Maybe I just need more coffee ;-)

It's a sparse array. The interstices between nodes are padded with empty virtualspace in order to cheapen the indexing operation. i.e. the nodes' local mem_map's are virtually positioned according to the range of pfns they span. If 32-bit weren't as pressed for virtualspace it could do likewise.

-- wli

#6 lore raw
In reply to Christoph Hellwig

Sorry it took so long for me to reply to this, but I've been on vacation for the past 3 weeks. Here's a new discontig patch that incorporates some of the feeback from this thread. Comments and/or integration into 2.6 appreciated.

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.1396 -> 1.1397
# include/asm-ia64/page.h 1.19 -> 1.20
# arch/ia64/kernel/setup.c 1.53 -> 1.54
# include/asm-ia64/pgtable.h 1.28 -> 1.29
# mm/bootmem.c 1.18 -> 1.19
# include/asm-ia64/numa.h 1.5 -> 1.6
# include/asm-ia64/processor.h 1.48 -> 1.49
# arch/ia64/mm/init.c 1.46 -> 1.47
# include/asm-ia64/nodedata.h 1.3 -> 1.4
# arch/ia64/mm/discontig.c 1.4 -> 1.5
# arch/ia64/Kconfig 1.38 -> 1.39
# drivers/acpi/Kconfig 1.12 -> 1.13
# include/asm-ia64/mmzone.h 1.4 -> 1.5
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/07/16 [email protected] 1.1397

# discontig update
# --------------------------------------------
#
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Wed Jul 16 12:28:28 2003
+++ b/arch/ia64/Kconfig	Wed Jul 16 12:28:28 2003
@@ -210,8 +210,8 @@
 	  system with an A0 or A1 stepping CPU.

config NUMA
- bool "Enable NUMA support" if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
- default y if IA64_SGI_SN2
+ bool
+ default y if IA64_SGI_SN2 || IA64_GENERIC
help
Say Y to compile the kernel to support NUMA (Non-Uniform Memory Access). This option is for configuring high-end multiprocessor
@@ -235,8 +235,7 @@

config DISCONTIGMEM
bool
- depends on IA64_SGI_SN2 || (IA64_GENERIC || IA64_DIG || IA64_HP_ZX1) && NUMA
- default y
+ default y if IA64_SGI_SN2 || IA64_GENERIC
help
Say Y to support efficient handling of discontiguous physical memory, for architectures which are either NUMA (Non-Uniform Memory Access)
@@ -245,8 +244,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 +257,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 +290,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 +15 -13
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
@@ -138,7 +138,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);
@@ -149,22 +149,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;
 	}
 }
 
@@ -180,7 +179,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
@@ -202,9 +201,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,6 +702,8 @@
 	 * 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
+	/* for discontig machines, we do this in discontig.c */
 	if (smp_processor_id() = 0) {
 		cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, PERCPU_PAGE_SIZE,
 					   __pa(MAX_DMA_ADDRESS));
@@ -714,6 +715,7 @@
 			per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
 		}
 	}
+#endif
 	cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 #else /* !CONFIG_SMP */
 	cpu_data = __phys_per_cpu_start;
arch/ia64/mm/discontig.c +132 -164

403 lines not on this page · raw message

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

248 lines not on this page · raw message

drivers/acpi/Kconfig +1 -1
diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
@@ -133,7 +133,7 @@
 
 config ACPI_NUMA
 	bool "NUMA support" if NUMA && (IA64 && !IA64_HP_SIM || X86 && ACPI && !ACPI_HT_ONLY && !X86_64)
-	default y if IA64 && IA64_SGI_SN
+	default y if IA64_GENERIC || IA64_SGI_SN2
 
 config ACPI_ASUS
         tristate "ASUS/Medion Laptop Extras"
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 +19 -11
diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h
@@ -93,18 +93,26 @@
 
 #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
-#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)
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+extern int ia64_pfn_valid(unsigned long pfn);
+#else
+#define ia64_pfn_valid(pfn) (1)
+#endif
+
+extern unsigned long max_low_pfn;
+#define pfn_valid(pfn) (((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
+
+#if defined(CONFIG_VIRTUAL_MEM_MAP) && !defined(CONFIG_DISCONTIGMEM)
+#define vmem_map mem_map
+#else
+extern struct page *vmem_map;
 #endif
+
+#define pfn_to_page(pfn)	(vmem_map + (pfn))
+#define page_to_pfn(page)	((unsigned long) (page - vmem_map))
+
+#define virt_to_page(kaddr)	(pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 
 typedef union ia64_va {
 	struct {
include/asm-ia64/pgtable.h +0 -1
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
@@ -241,10 +239,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)))
@@ -416,6 +412,7 @@

extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern void paging_init (void);
+extern int filter_rsvd_memory(unsigned long start, unsigned long end, void *arg);

/*
* Note: The macros below rely on the fact that MAX_SWAPFILES_SHIFT <= number of

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;
+	struct cpuinfo_ia64 *cpu_data[NR_CPUS];
+	int nodeid;
 #endif
 };
 
mm/bootmem.c +24 -8
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);
@@ -251,7 +267,7 @@
 
 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;
@@ -260,23 +276,23 @@
 	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;
#7 lore raw
In reply to Christoph Hellwig

Review line 217

Quoted 11 lines · Jesse Barnes
(quoted diff) +2 -2
@@ -210,8 +210,8 @@
 	  system with an A0 or A1 stepping CPU.
 
 config NUMA
-	bool "Enable NUMA support" if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
-	default y if IA64_SGI_SN2
+	bool
+	default y if IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
 	  Access).  This option is for configuring high-end multiprocessor

If you're removing the question, you can remove the helptext too.

Review line 241

Quoted 10 lines
(quoted diff) +1 -2
@@ -235,8 +235,7 @@
 
 config DISCONTIGMEM
 	bool
-	depends on IA64_SGI_SN2 || (IA64_GENERIC || IA64_DIG || IA64_HP_ZX1) && NUMA
-	default y
+	default y if IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  Say Y to support efficient handling of discontiguous physical memory,
 	  for architectures which are either NUMA (Non-Uniform Memory Access)

This one already shouldn't have helptext ;-)

Quoted 2 lines

- * on a BANKSIZE boundary. Multiple banks per node is not supported.
+ * on a GRANULE boundary. Multiple banks per node is not supported.

Multiple banks *are* not supported ;-) The feature of multiple banks *is* not supported.

Review line 31

Quoted 12 lines
(quoted diff) +6 -1
@@ -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.
+	 */

Can you wrap comments at 80 columns? It makes them much easier to read.

Signature · 3 lines
"It's not Hollywood.  War is real, war is primarily not about defeat or
victory, it is about death.  I've seen thousands and thousands of dead bodies.
Do you think I want to have an academic debate on this subject?" -- Robert Fisk
#8 lore raw
In reply to Christoph Hellwig

Thanks for looking at it. Here's another one that fixes that stuff up.

Quoted 22 lines · Matthew Wilcox

Review

Quoted 4 lines
(quoted diff) +1 -0
+	default y if IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
 	  Access).  This option is for configuring high-end multiprocessor

If you're removing the question, you can remove the helptext too.

Review

Quoted 4 lines
(quoted diff) +1 -0
+	default y if IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  Say Y to support efficient handling of discontiguous physical memory,
 	  for architectures which are either NUMA (Non-Uniform Memory Access)

This one already shouldn't have helptext ;-)

Quoted 2 lines

- * on a BANKSIZE boundary. Multiple banks per node is not supported.
+ * on a GRANULE boundary. Multiple banks per node is not supported.

Multiple banks *are* not supported ;-) The feature of multiple banks *is* not supported.

Quoted 2 lines
(quoted diff) +0 -0
@@ -22,15 +22,17 @@
 
Quoted 12 lines

Review line 31

Quoted 10 lines
(quoted diff) +6 -1
 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.
+	 */

Can you wrap comments at 80 columns? It makes them much easier to read.

I prefer it that way too, but David likes 100 columns, AFAICT. :) Fixed anyway.

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.1396 -> 1.1398
# include/asm-ia64/page.h 1.19 -> 1.20
# arch/ia64/kernel/setup.c 1.53 -> 1.54
# include/asm-ia64/pgtable.h 1.28 -> 1.29
# mm/bootmem.c 1.18 -> 1.19
# include/asm-ia64/numa.h 1.5 -> 1.6
# include/asm-ia64/processor.h 1.48 -> 1.49
# arch/ia64/mm/init.c 1.46 -> 1.47
# include/asm-ia64/nodedata.h 1.3 -> 1.5
# arch/ia64/mm/discontig.c 1.4 -> 1.6
# arch/ia64/Kconfig 1.38 -> 1.40
# drivers/acpi/Kconfig 1.12 -> 1.13
# include/asm-ia64/mmzone.h 1.4 -> 1.5
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/07/16 [email protected] 1.1397

# discontig update
# --------------------------------------------
# 03/07/16	[email protected]	1.1398
# more discontig stuff
# --------------------------------------------
#
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Wed Jul 16 12:50:02 2003
+++ b/arch/ia64/Kconfig	Wed Jul 16 12:50:02 2003
@@ -210,12 +210,8 @@
 	  system with an A0 or A1 stepping CPU.

config NUMA
- bool "Enable NUMA support" if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
- default y if IA64_SGI_SN2
- help

-	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
-	  Access).  This option is for configuring high-end multiprocessor
-	  server systems.  If in doubt, say N.

+ bool
+ default y if IA64_SGI_SN2 || IA64_GENERIC

choice
prompt "Maximum Memory per NUMA Node" if NUMA && IA64_DIG
@@ -235,18 +231,11 @@

config DISCONTIGMEM
bool
- depends on IA64_SGI_SN2 || (IA64_GENERIC || IA64_DIG || IA64_HP_ZX1) && NUMA
- default y
- help

-	  Say Y to support efficient handling of discontiguous physical memory,
-	  for architectures which are either NUMA (Non-Uniform Memory Access)
-	  or have huge holes in the physical address space for other reasons.
-	  See <file:Documentation/vm/numa> for more.

+ default y if IA64_SGI_SN2 || IA64_GENERIC

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 +248,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 +281,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 +15 -13
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
@@ -138,7 +138,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);
@@ -149,22 +149,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;
 	}
 }
 
@@ -180,7 +179,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
@@ -202,9 +201,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,6 +702,8 @@
 	 * 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
+	/* for discontig machines, we do this in discontig.c */
 	if (smp_processor_id() = 0) {
 		cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, PERCPU_PAGE_SIZE,
 					   __pa(MAX_DMA_ADDRESS));
@@ -714,6 +715,7 @@
 			per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
 		}
 	}
+#endif
 	cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 #else /* !CONFIG_SMP */
 	cpu_data = __phys_per_cpu_start;
arch/ia64/mm/discontig.c +132 -164

403 lines not on this page · raw message

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

248 lines not on this page · raw message

drivers/acpi/Kconfig +1 -1
diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
@@ -133,7 +133,7 @@
 
 config ACPI_NUMA
 	bool "NUMA support" if NUMA && (IA64 && !IA64_HP_SIM || X86 && ACPI && !ACPI_HT_ONLY && !X86_64)
-	default y if IA64 && IA64_SGI_SN
+	default y if IA64_GENERIC || IA64_SGI_SN2
 
 config ACPI_ASUS
         tristate "ASUS/Medion Laptop Extras"
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 +19 -11
diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h
@@ -93,18 +93,26 @@
 
 #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
-#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)
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+extern int ia64_pfn_valid(unsigned long pfn);
+#else
+#define ia64_pfn_valid(pfn) (1)
+#endif
+
+extern unsigned long max_low_pfn;
+#define pfn_valid(pfn) (((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
+
+#if defined(CONFIG_VIRTUAL_MEM_MAP) && !defined(CONFIG_DISCONTIGMEM)
+#define vmem_map mem_map
+#else
+extern struct page *vmem_map;
 #endif
+
+#define pfn_to_page(pfn)	(vmem_map + (pfn))
+#define page_to_pfn(page)	((unsigned long) (page - vmem_map))
+
+#define virt_to_page(kaddr)	(pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 
 typedef union ia64_va {
 	struct {
include/asm-ia64/pgtable.h +0 -1
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
@@ -241,10 +239,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)))
@@ -416,6 +412,7 @@

extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern void paging_init (void);
+extern int filter_rsvd_memory(unsigned long start, unsigned long end, void *arg);

/*
* Note: The macros below rely on the fact that MAX_SWAPFILES_SHIFT <= number of

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;
+	struct cpuinfo_ia64 *cpu_data[NR_CPUS];
+	int nodeid;
 #endif
 };
 
mm/bootmem.c +24 -8
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);
@@ -251,7 +267,7 @@
 
 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;
@@ -260,23 +276,23 @@
 	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;
#9 lore raw
In reply to Christoph Hellwig
Quoted 4 lines · Matthew Wilcox
Quoted 3 lines · Jesse Barnes
(quoted diff) +0 -0
@@ -210,8 +210,8 @@
 	  system with an A0 or A1 stepping CPU.
 
Quoted 8 lines

Review line 217

Quoted 8 lines
(quoted diff) +2 -2
 config NUMA
-	bool "Enable NUMA support" if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
-	default y if IA64_SGI_SN2
+	bool
+	default y if IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
 	  Access).  This option is for configuring high-end multiprocessor

There are other NUMA machines around which are not from SGI and are IA64_DIG. You excluded them on purpose? I hope not...

Quoted 4 lines

If you're removing the question, you can remove the helptext too.

Quoted 2 lines
(quoted diff) +0 -0
@@ -235,8 +235,7 @@
 
Quoted 8 lines

Review

Quoted 8 lines
(quoted diff) +0 -1
 config DISCONTIGMEM
 	bool
-	depends on IA64_SGI_SN2 || (IA64_GENERIC || IA64_DIG || IA64_HP_ZX1) &&

NUMA - default y

(quoted diff) +1 -0
+	default y if IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  Say Y to support efficient handling of discontiguous physical memory,
 	  for architectures which are either NUMA (Non-Uniform Memory Access)

Same comment as above. NEC TX7 is an IA64_DIG platform.

Erich

#10 lore raw
In reply to Christoph Hellwig
Quoted 21 lines · Erich Focht
Quoted 4 lines · Matthew Wilcox
Quoted 3 lines · Jesse Barnes
(quoted diff) +0 -0
@@ -210,8 +210,8 @@
 	  system with an A0 or A1 stepping CPU.
 
Quoted 8 lines

Review line 217

Quoted 8 lines
(quoted diff) +2 -2
 config NUMA
-	bool "Enable NUMA support" if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
-	default y if IA64_SGI_SN2
+	bool
+	default y if IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
 	  Access).  This option is for configuring high-end multiprocessor

There are other NUMA machines around which are not from SGI and are IA64_DIG. You excluded them on purpose? I hope not...

Quoted 4 lines

If you're removing the question, you can remove the helptext too.

Quoted 2 lines
(quoted diff) +0 -0
@@ -235,8 +235,7 @@
 
Quoted 10 lines
Quoted 8 lines

Review

Quoted 8 lines
(quoted diff) +0 -1
 config DISCONTIGMEM
 	bool
-	depends on IA64_SGI_SN2 || (IA64_GENERIC || IA64_DIG || IA64_HP_ZX1) &&

NUMA - default y

(quoted diff) +1 -0
+	default y if IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  Say Y to support efficient handling of discontiguous physical memory,
 	  for architectures which are either NUMA (Non-Uniform Memory Access)

Same comment as above. NEC TX7 is an IA64_DIG platform.

Oops, sorry. Here's another one. How does it look?

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.1397 -> 1.1398
# include/asm-ia64/page.h 1.19 -> 1.20
# arch/ia64/kernel/setup.c 1.53 -> 1.54
# include/asm-ia64/pgtable.h 1.28 -> 1.29
# mm/bootmem.c 1.18 -> 1.19
# include/asm-ia64/numa.h 1.5 -> 1.6
# include/asm-ia64/processor.h 1.48 -> 1.49
# arch/ia64/mm/init.c 1.46 -> 1.47
# include/asm-ia64/nodedata.h 1.3 -> 1.4
# arch/ia64/mm/discontig.c 1.4 -> 1.5
# arch/ia64/Kconfig 1.38 -> 1.39
# drivers/acpi/Kconfig 1.12 -> 1.13
# include/asm-ia64/mmzone.h 1.4 -> 1.5
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/07/16 [email protected] 1.1398

# latest discontig
# --------------------------------------------
#
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Wed Jul 16 15:36:33 2003
+++ b/arch/ia64/Kconfig	Wed Jul 16 15:36:33 2003
@@ -211,7 +211,7 @@

config NUMA
bool "Enable NUMA support" if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
- default y if IA64_SGI_SN2
+ default y if IA64_SGI_SN2 || IA64_GENERIC
help
Say Y to compile the kernel to support NUMA (Non-Uniform Memory Access). This option is for configuring high-end multiprocessor
@@ -234,9 +234,8 @@
endchoice

config DISCONTIGMEM
- bool
- depends on IA64_SGI_SN2 || (IA64_GENERIC || IA64_DIG || IA64_HP_ZX1) && NUMA
- default y
+ bool "Discontiguous memory support" if IA64_DIG
+ default y if IA64_SGI_SN2 || IA64_GENERIC
help
Say Y to support efficient handling of discontiguous physical memory, for architectures which are either NUMA (Non-Uniform Memory Access)
@@ -245,8 +244,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 +257,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 +290,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 +15 -13
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
@@ -138,7 +138,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);
@@ -149,22 +149,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;
 	}
 }
 
@@ -180,7 +179,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
@@ -202,9 +201,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,6 +702,8 @@
 	 * 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
+	/* for discontig machines, we do this in discontig.c */
 	if (smp_processor_id() = 0) {
 		cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, PERCPU_PAGE_SIZE,
 					   __pa(MAX_DMA_ADDRESS));
@@ -714,6 +715,7 @@
 			per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
 		}
 	}
+#endif
 	cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 #else /* !CONFIG_SMP */
 	cpu_data = __phys_per_cpu_start;
arch/ia64/mm/discontig.c +132 -164

403 lines not on this page · raw message

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

248 lines not on this page · raw message

drivers/acpi/Kconfig +1 -1
diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
@@ -133,7 +133,7 @@
 
 config ACPI_NUMA
 	bool "NUMA support" if NUMA && (IA64 && !IA64_HP_SIM || X86 && ACPI && !ACPI_HT_ONLY && !X86_64)
-	default y if IA64 && IA64_SGI_SN
+	default y if IA64_GENERIC || IA64_SGI_SN2
 
 config ACPI_ASUS
         tristate "ASUS/Medion Laptop Extras"
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 +19 -11
diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h
@@ -93,18 +93,26 @@
 
 #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
-#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)
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+extern int ia64_pfn_valid(unsigned long pfn);
+#else
+#define ia64_pfn_valid(pfn) (1)
+#endif
+
+extern unsigned long max_low_pfn;
+#define pfn_valid(pfn) (((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
+
+#if defined(CONFIG_VIRTUAL_MEM_MAP) && !defined(CONFIG_DISCONTIGMEM)
+#define vmem_map mem_map
+#else
+extern struct page *vmem_map;
 #endif
+
+#define pfn_to_page(pfn)	(vmem_map + (pfn))
+#define page_to_pfn(page)	((unsigned long) (page - vmem_map))
+
+#define virt_to_page(kaddr)	(pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 
 typedef union ia64_va {
 	struct {
include/asm-ia64/pgtable.h +0 -1
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
@@ -241,10 +239,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)))
@@ -416,6 +412,7 @@

extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern void paging_init (void);
+extern int filter_rsvd_memory(unsigned long start, unsigned long end, void *arg);

/*
* Note: The macros below rely on the fact that MAX_SWAPFILES_SHIFT <= number of

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;
+	struct cpuinfo_ia64 *cpu_data[NR_CPUS];
+	int nodeid;
 #endif
 };
 
mm/bootmem.c +24 -8
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);
@@ -251,7 +267,7 @@
 
 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;
@@ -260,23 +276,23 @@
 	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;
#11 lore raw
In reply to Christoph Hellwig
Quoted 3 lines
Quoted 1 line

Same comment as above. NEC TX7 is an IA64_DIG platform.

Oops, sorry. Here's another one. How does it look?

...

arch/ia64/Kconfig line 234

Quoted 13 lines
arch/ia64/Kconfig +1 -1
@@ -211,7 +211,7 @@
 
 config NUMA
 	bool "Enable NUMA support" if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
-	default y if IA64_SGI_SN2
+	default y if IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
 	  Access).  This option is for configuring high-end multiprocessor
@@ -234,9 +234,8 @@
 endchoice

OK. Thanks.

arch/ia64/Kconfig

Quoted 11 lines
arch/ia64/Kconfig +0 -2
 config DISCONTIGMEM
-	bool
-	depends on IA64_SGI_SN2 || (IA64_GENERIC || IA64_DIG || IA64_HP_ZX1) &&

NUMA - default y

arch/ia64/Kconfig +2 -0
+	bool "Discontiguous memory support" if IA64_DIG
+	default y if IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  Say Y to support efficient handling of discontiguous physical memory,
 	  for architectures which are either NUMA (Non-Uniform Memory Access)
@@ -245,8 +244,7 @@

Maybe that should better be

     bool "Discontiguous memory support" if (IA64_DIG && NUMA)

Discontigmem alone doesn't make sense, yet, I think...

Regards,
Erich

#12 lore raw
In reply to Christoph Hellwig
Quoted 4 lines · Erich Focht

Maybe that should better be

     bool "Discontiguous memory support" if (IA64_DIG && NUMA)

Discontigmem alone doesn't make sense, yet, I think...

Not for ia64 I guess, unless we make zx1 use discontig as well. Patch appended.

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.1397 -> 1.1399
# include/asm-ia64/page.h 1.19 -> 1.20
# arch/ia64/kernel/setup.c 1.53 -> 1.54
# include/asm-ia64/pgtable.h 1.28 -> 1.29
# mm/bootmem.c 1.18 -> 1.19
# include/asm-ia64/numa.h 1.5 -> 1.6
# include/asm-ia64/processor.h 1.48 -> 1.49
# arch/ia64/mm/init.c 1.46 -> 1.47
# include/asm-ia64/nodedata.h 1.3 -> 1.4
# arch/ia64/mm/discontig.c 1.4 -> 1.5
# arch/ia64/Kconfig 1.38 -> 1.40
# drivers/acpi/Kconfig 1.12 -> 1.13
# include/asm-ia64/mmzone.h 1.4 -> 1.5
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/07/16 [email protected] 1.1398

# latest discontig
# --------------------------------------------
# 03/07/17	[email protected]	1.1399
# another discontig patch
# --------------------------------------------
#
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Thu Jul 17 16:59:05 2003
+++ b/arch/ia64/Kconfig	Thu Jul 17 16:59:05 2003
@@ -211,7 +211,7 @@

config NUMA
bool "Enable NUMA support" if IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
- default y if IA64_SGI_SN2
+ default y if IA64_SGI_SN2 || IA64_GENERIC
help
Say Y to compile the kernel to support NUMA (Non-Uniform Memory Access). This option is for configuring high-end multiprocessor
@@ -234,9 +234,8 @@
endchoice

config DISCONTIGMEM
- bool
- depends on IA64_SGI_SN2 || (IA64_GENERIC || IA64_DIG || IA64_HP_ZX1) && NUMA
- default y
+ bool "Discontiguous memory support" if (IA64_DIG && NUMA)
+ default y if IA64_SGI_SN2 || IA64_GENERIC
help
Say Y to support efficient handling of discontiguous physical memory, for architectures which are either NUMA (Non-Uniform Memory Access)
@@ -245,8 +244,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 +257,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 +290,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 +15 -13
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
@@ -138,7 +138,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);
@@ -149,22 +149,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;
 	}
 }
 
@@ -180,7 +179,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
@@ -202,9 +201,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,6 +702,8 @@
 	 * 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
+	/* for discontig machines, we do this in discontig.c */
 	if (smp_processor_id() = 0) {
 		cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, PERCPU_PAGE_SIZE,
 					   __pa(MAX_DMA_ADDRESS));
@@ -714,6 +715,7 @@
 			per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
 		}
 	}
+#endif
 	cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 #else /* !CONFIG_SMP */
 	cpu_data = __phys_per_cpu_start;
arch/ia64/mm/discontig.c +132 -164

403 lines not on this page · raw message

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

248 lines not on this page · raw message

drivers/acpi/Kconfig +1 -1
diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
@@ -133,7 +133,7 @@
 
 config ACPI_NUMA
 	bool "NUMA support" if NUMA && (IA64 && !IA64_HP_SIM || X86 && ACPI && !ACPI_HT_ONLY && !X86_64)
-	default y if IA64 && IA64_SGI_SN
+	default y if IA64_GENERIC || IA64_SGI_SN2
 
 config ACPI_ASUS
         tristate "ASUS/Medion Laptop Extras"
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 +19 -11
diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h
@@ -93,18 +93,26 @@
 
 #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
-#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)
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+extern int ia64_pfn_valid(unsigned long pfn);
+#else
+#define ia64_pfn_valid(pfn) (1)
+#endif
+
+extern unsigned long max_low_pfn;
+#define pfn_valid(pfn) (((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
+
+#if defined(CONFIG_VIRTUAL_MEM_MAP) && !defined(CONFIG_DISCONTIGMEM)
+#define vmem_map mem_map
+#else
+extern struct page *vmem_map;
 #endif
+
+#define pfn_to_page(pfn)	(vmem_map + (pfn))
+#define page_to_pfn(page)	((unsigned long) (page - vmem_map))
+
+#define virt_to_page(kaddr)	(pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 
 typedef union ia64_va {
 	struct {
include/asm-ia64/pgtable.h +0 -1
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
@@ -241,10 +239,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)))
@@ -416,6 +412,7 @@

extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern void paging_init (void);
+extern int filter_rsvd_memory(unsigned long start, unsigned long end, void *arg);

/*
* Note: The macros below rely on the fact that MAX_SWAPFILES_SHIFT <= number of

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;
+	struct cpuinfo_ia64 *cpu_data[NR_CPUS];
+	int nodeid;
 #endif
 };
 
mm/bootmem.c +24 -8
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);
@@ -251,7 +267,7 @@
 
 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;
@@ -260,23 +276,23 @@
 	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;
#13 lore raw
In reply to Christoph Hellwig

Looks good, applies cleanly on top of 2.6.0-test1 + ia64 but doesn't boot on TX7 :-( Dies right after the elilo output lines... Maybe Tak (CC'd) finds some time to have a look?

Regards,
Erich

Quoted 11 lines · Jesse Barnes
Quoted 4 lines · Erich Focht

Maybe that should better be

     bool "Discontiguous memory support" if (IA64_DIG && NUMA)

Discontigmem alone doesn't make sense, yet, I think...

Not for ia64 I guess, unless we make zx1 use discontig as well. Patch appended.

Thanks,
Jesse

#14 lore raw
In reply to Christoph Hellwig

From: Erich Focht <[email protected]>
Subject: Re: [Discontig-devel] [PATCH] another discontig patch
Date: Fri, 18 Jul 2003 18:15:44 +0200
Message-ID: <[email protected]>

Quoted 3 lines

Looks good, applies cleanly on top of 2.6.0-test1 + ia64 but doesn't boot on TX7 :-( Dies right after the elilo output lines... Maybe Tak (CC'd) finds some time to have a look?

I'll attend OLS this week so I think I can't have time to test it. I'll look into it next week.

---
1st Computer Software Division, NEC Corporation Takayoshi Kochi <[email protected]/[email protected]>