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 --- 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 < memmap.nr_map; i++) { - md = &memmap.map[i]; - if (!is_available_memory(md)) - continue; - addr = (md->phys_addr+PAGE_SIZE-1) >> PAGE_SHIFT; - end = (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >> PAGE_SHIFT; - - if ((pagenr >= addr) && (pagenr < end)) - return 1; - } - return 0; + for (i = 0; i < memmap.nr_map; i++) { + md = &memmap.map[i]; + if (!is_available_memory(md)) + continue; + addr = (md->phys_addr+PAGE_SIZE-1) >> PAGE_SHIFT; + end = (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >> PAGE_SHIFT; + if ((pagenr >= addr) && (pagenr < end)) + return 1; } +#endif /* CONFIG_EFI */ + return 0; +} - for (i = 0; i < 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 < local_e820->nr_map; i++) { - if (e820.map[i].type != E820_RAM) /* not usable memory */ + if (local_e820->map[i].type != E820_RAM) /* not usable memory */ continue; /* * !!!FIXME!!! Some BIOSen report areas as RAM that * are not. Notably the 640->1Mb area. We need a sanity * check here. */ - addr = (e820.map[i].addr+PAGE_SIZE-1) >> PAGE_SHIFT; - end = (e820.map[i].addr+e820.map[i].size) >> PAGE_SHIFT; + addr = (local_e820->map[i].addr+PAGE_SIZE-1) >> PAGE_SHIFT; + end = (local_e820->map[i].addr+local_e820->map[i].size) >> PAGE_SHIFT; if ((pagenr >= addr) && (pagenr < 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, &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, &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 < 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 && !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 < PAGES_PER_SECTION; offset++) { + unsigned long page_nr = (phys_addr >> 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 << PAGE_SHIFT), 0); _