<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
We need this for the time being because mem= will overwrite the
BIOS e820 table.  We need to make sure that any pages that we
online are actualy RAM, so we need to consult the original
e820.  Otherwise, we online pages in, say, the PCI config space
and the adapters get angry when you hand those to userspace.

Signed-off-by: Dave Hansen &lt;haveblue@us.ibm.com&gt;
---

 memhotplug-dave/arch/i386/kernel/setup.c |    2 +
 memhotplug-dave/arch/i386/mm/init.c      |   49 ++++++++++++++++++-------------
 memhotplug-dave/drivers/base/memory.c    |   11 +++++-
 memhotplug-dave/mm/Kconfig               |    3 +
 memhotplug-dave/mm/memory_hotplug.c      |   19 +++++++++++-
 5 files changed, 62 insertions(+), 22 deletions(-)

diff -puN arch/i386/mm/init.c~Y2-page_is_ram_hotplug arch/i386/mm/init.c
--- memhotplug/arch/i386/mm/init.c~Y2-page_is_ram_hotplug	2005-02-17 15:25:52.000000000 -0800
+++ memhotplug-dave/arch/i386/mm/init.c	2005-02-17 15:25:52.000000000 -0800
@@ -192,38 +192,42 @@ static inline int page_kills_ppro(unsign
 
 extern int is_available_memory(efi_memory_desc_t *);
 
-int page_is_ram(unsigned long pagenr)
+static int page_is_ram_efi(unsigned long pagenr)
 {
+#ifdef CONFIG_EFI
 	int i;
 	unsigned long addr, end;
+	efi_memory_desc_t *md;
 
-	if (efi_enabled) {
-		efi_memory_desc_t *md;
-
-		for (i = 0; i &lt; memmap.nr_map; i++) {
-			md = &amp;memmap.map[i];
-			if (!is_available_memory(md))
-				continue;
-			addr = (md-&gt;phys_addr+PAGE_SIZE-1) &gt;&gt; PAGE_SHIFT;
-			end = (md-&gt;phys_addr + (md-&gt;num_pages &lt;&lt; EFI_PAGE_SHIFT)) &gt;&gt; PAGE_SHIFT;
-
-			if ((pagenr &gt;= addr) &amp;&amp; (pagenr &lt; end))
-				return 1;
-		}
-		return 0;
+	for (i = 0; i &lt; memmap.nr_map; i++) {
+		md = &amp;memmap.map[i];
+		if (!is_available_memory(md))
+			continue;
+		addr = (md-&gt;phys_addr+PAGE_SIZE-1) &gt;&gt; PAGE_SHIFT;
+		end = (md-&gt;phys_addr + (md-&gt;num_pages &lt;&lt; EFI_PAGE_SHIFT)) &gt;&gt; PAGE_SHIFT;
+		if ((pagenr &gt;= addr) &amp;&amp; (pagenr &lt; end))
+			return 1;
 	}
+#endif /* CONFIG_EFI */
+	return 0;
+}
 
-	for (i = 0; i &lt; e820.nr_map; i++) {
+int page_is_ram_e820(unsigned long pagenr, struct e820map *local_e820)
+{
+	int i;
+	unsigned long addr, end;
+
+	for (i = 0; i &lt; local_e820-&gt;nr_map; i++) {
 
-		if (e820.map[i].type != E820_RAM)	/* not usable memory */
+		if (local_e820-&gt;map[i].type != E820_RAM) /* not usable memory */
 			continue;
 		/*
 		 *	!!!FIXME!!! Some BIOSen report areas as RAM that
 		 *	are not. Notably the 640-&gt;1Mb area. We need a sanity
 		 *	check here.
 		 */
-		addr = (e820.map[i].addr+PAGE_SIZE-1) &gt;&gt; PAGE_SHIFT;
-		end = (e820.map[i].addr+e820.map[i].size) &gt;&gt; PAGE_SHIFT;
+		addr = (local_e820-&gt;map[i].addr+PAGE_SIZE-1) &gt;&gt; PAGE_SHIFT;
+		end = (local_e820-&gt;map[i].addr+local_e820-&gt;map[i].size) &gt;&gt; PAGE_SHIFT;
 		if  ((pagenr &gt;= addr) &amp;&amp; (pagenr &lt; end))
 			return 1;
 	}
@@ -797,3 +801,10 @@ void free_initrd_mem(unsigned long start
 	}
 }
 #endif
+
+int page_is_ram(unsigned long pagenr)
+{
+	if (efi_enabled)
+		return page_is_ram_efi(pagenr);
+	return page_is_ram_e820(pagenr, &amp;e820);
+}
diff -puN mm/memory_hotplug.c~Y2-page_is_ram_hotplug mm/memory_hotplug.c
--- memhotplug/mm/memory_hotplug.c~Y2-page_is_ram_hotplug	2005-02-17 15:25:52.000000000 -0800
+++ memhotplug-dave/mm/memory_hotplug.c	2005-02-17 15:25:52.000000000 -0800
@@ -46,6 +46,7 @@ got_map_ptr:
 }
 
 extern int sparse_add_one_section(int, int, struct page *); /* FIXME header*/
+void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn, unsigned long size);
 int __add_section(struct zone *zone, unsigned long phys_start_pfn,
 		  unsigned long attr)
 {
@@ -147,6 +148,21 @@ int __add_pages(struct zone *zone, unsig
 	return err;
 }
 
+#ifdef CONFIG_SIMULATED_MEM_HOTPLUG
+int page_is_hotpluggable_ram(unsigned long pfn)
+{
+	extern struct e820map bios_e820;
+	extern int page_is_ram_e820(unsigned long, struct e820map*);
+
+	return page_is_ram_e820(pfn, &amp;bios_e820);
+}
+#else
+int page_is_hotpluggable_ram(unsigned long pfn)
+{
+	return 1;
+}
+#endif
+
 int online_pages(unsigned long pfn, unsigned long nr_pages)
 {
 	int i;
@@ -156,7 +172,8 @@ int online_pages(unsigned long pfn, unsi
 
 	for (i = 0; i &lt; nr_pages; i++) {
 		struct page *page = pfn_to_page(pfn + i);
-		if (page_is_ram(pfn + i))
+
+		if (page_is_hotpluggable_ram(pfn + i))
 			online_page(page);
 	}
 
diff -puN arch/i386/kernel/setup.c~Y2-page_is_ram_hotplug arch/i386/kernel/setup.c
--- memhotplug/arch/i386/kernel/setup.c~Y2-page_is_ram_hotplug	2005-02-17 15:25:52.000000000 -0800
+++ memhotplug-dave/arch/i386/kernel/setup.c	2005-02-17 15:25:52.000000000 -0800
@@ -118,6 +118,7 @@ struct sys_desc_table_struct {
 struct edid_info edid_info;
 struct ist_info ist_info;
 struct e820map e820;
+struct e820map bios_e820;
 
 unsigned char aux_device_present;
 
@@ -1417,6 +1418,7 @@ void __init setup_arch(char **cmdline_p)
 	else {
 		printk(KERN_INFO "BIOS-provided physical RAM map:\n");
 		print_memory_map(machine_specific_memory_setup());
+		bios_e820 = e820;
 	}
 
 	copy_edd();
diff -L build-fix-ia64 -puN /dev/null /dev/null
diff -puN mm/Kconfig~Y2-page_is_ram_hotplug mm/Kconfig
--- memhotplug/mm/Kconfig~Y2-page_is_ram_hotplug	2005-02-17 15:25:52.000000000 -0800
+++ memhotplug-dave/mm/Kconfig	2005-02-17 15:25:52.000000000 -0800
@@ -20,4 +20,7 @@ config FLATMEM
 
 endchoice
 
+config SIMULATED_MEM_HOTPLUG
+	bool "Simulate memory hotplug on non-hotplug hardware"
+	depends on X86 &amp;&amp; !X86_64
 
diff -puN drivers/base/memory.c~Y2-page_is_ram_hotplug drivers/base/memory.c
--- memhotplug/drivers/base/memory.c~Y2-page_is_ram_hotplug	2005-02-17 15:25:52.000000000 -0800
+++ memhotplug-dave/drivers/base/memory.c	2005-02-17 15:25:52.000000000 -0800
@@ -297,12 +297,14 @@ static int block_size_init(void)
  * All the probe stuff here
  */
 
+extern int page_is_hotpluggable_ram(unsigned long pfn);
 /* define this off in some header somewhere ... */
 #ifdef CONFIG_ARCH_MEMORY_PROBE
 static ssize_t
 memory_probe_store(struct class *class, const char __user *buf, size_t count)
 {
 	u64 phys_addr;
+	unsigned long offset;
 	int ret;
 	/*
 	 * Hmmm... what do we really want this to do?
@@ -313,8 +315,13 @@ memory_probe_store(struct class *class, 
 	phys_addr = simple_strtoull(buf, NULL, 0);
 
 	// a hardware check for the ram?
-	//if (!ram_present(phys_addr, PAGES_PER_SECTION))
-	//	return -EINVAL;
+	for (offset = 0; offset &lt; PAGES_PER_SECTION; offset++) {
+		unsigned long page_nr = (phys_addr &gt;&gt; PAGE_SHIFT) + offset;
+		if (page_is_hotpluggable_ram(page_nr))
+			break;
+	}
+	if (offset == PAGES_PER_SECTION)
+		return -EINVAL;
 
 	ret = add_memory(phys_addr, (PAGES_PER_SECTION &lt;&lt; PAGE_SHIFT), 0);
 
_
</pre></body></html>