Memory-Hotplug: Fix the bug on interface /dev/mem for 64-bit kernel The new added memory can not be access by interface /dev/mem, because we do not update the variable high_memory, max_pfn and max_low_pfn. Memory hotplug still has critical issues for 32-bit kernel, and it is more important for 64-bit kernel, we fix it on 64-bit first. We add a function update_end_of_memory_vars in file arch/x86/mm/init.c to update these variables. Signed-off-by: Shaohui Zheng CC: Andi Kleen CC: Li Haicheng Reviewed-by: Wu Fengguang Reviewed-by: KAMEZAWA Hiroyuki diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index d406c52..b6a85cc 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -386,3 +387,24 @@ void free_initrd_mem(unsigned long start, unsigned long end) free_init_pages("initrd memory", start, end); } #endif + +/** + * After memory hotplug, the variable max_pfn, max_low_pfn and high_memory will + * be affected, it will be updated in this function. Memory hotplug still has + * critical issues on 32-bit kennel, it was more important on 64-bit kernel, + * so we update the variables for 64-bit kernel first, fix me in future for + * 32-bit kenrel. + */ +void __meminit __attribute__((weak)) update_end_of_memory_vars(u64 start, + u64 size) +{ +#ifdef CONFIG_X86_64 + unsigned long start_pfn = start >> PAGE_SHIFT; + unsigned long end_pfn = PFN_UP(start + size); + + if (end_pfn > max_pfn) { + max_low_pfn = max_pfn = end_pfn; + high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1; + } +#endif /* CONFIG_X86_64 */ +} diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index b10ec49..84533a5 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -13,6 +13,7 @@ extern unsigned long max_low_pfn; extern unsigned long min_low_pfn; +extern void update_end_of_memory_vars(u64 start, u64 size); /* * highest page diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 030ce8a..3e94b23 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -523,6 +523,9 @@ int __ref add_memory(int nid, u64 start, u64 size) BUG_ON(ret); } + /* update max_pfn, max_low_pfn and high_memory */ + update_end_of_memory_vars(start, size); + goto out; error: