forked from mirrors/linux
		
	[PATCH] x86_64: Support memory hotadd without sparsemem
Memory hotadd doesn't need SPARSEMEM, but can be handled by just preallocating mem_maps. This only needs some untangling of ifdefs to enable the necessary code even without SPARSEMEM. Originally from Keith Mannthey, hacked by AK. Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
		
							parent
							
								
									805e8c03c9
								
							
						
					
					
						commit
						9d99aaa31f
					
				
					 6 changed files with 47 additions and 12 deletions
				
			
		|  | @ -651,6 +651,7 @@ void __init mem_init(void) | ||||||
|  * Specifically, in the case of x86, we will always add |  * Specifically, in the case of x86, we will always add | ||||||
|  * memory to the highmem for now. |  * memory to the highmem for now. | ||||||
|  */ |  */ | ||||||
|  | #ifdef CONFIG_HOTPLUG_MEMORY | ||||||
| #ifndef CONFIG_NEED_MULTIPLE_NODES | #ifndef CONFIG_NEED_MULTIPLE_NODES | ||||||
| int add_memory(u64 start, u64 size) | int add_memory(u64 start, u64 size) | ||||||
| { | { | ||||||
|  | @ -667,6 +668,7 @@ int remove_memory(u64 start, u64 size) | ||||||
| 	return -EINVAL; | 	return -EINVAL; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| kmem_cache_t *pgd_cache; | kmem_cache_t *pgd_cache; | ||||||
| kmem_cache_t *pmd_cache; | kmem_cache_t *pmd_cache; | ||||||
|  |  | ||||||
|  | @ -80,7 +80,7 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size) | ||||||
| 	return 0; | 	return 0; | ||||||
| }  | }  | ||||||
| 
 | 
 | ||||||
| int __init e820_mapped(unsigned long start, unsigned long end, unsigned type)  | int __meminit e820_mapped(unsigned long start, unsigned long end, unsigned type) | ||||||
| {  | {  | ||||||
| 	int i; | 	int i; | ||||||
| 	for (i = 0; i < e820.nr_map; i++) {  | 	for (i = 0; i < e820.nr_map; i++) {  | ||||||
|  |  | ||||||
|  | @ -507,9 +507,8 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size) | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Memory hotplug specific functions |  * Memory hotplug specific functions | ||||||
|  * These are only for non-NUMA machines right now. |  | ||||||
|  */ |  */ | ||||||
| #ifdef CONFIG_MEMORY_HOTPLUG | #if defined(CONFIG_ACPI_HOTPLUG_MEMORY) || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE) | ||||||
| 
 | 
 | ||||||
| void online_page(struct page *page) | void online_page(struct page *page) | ||||||
| { | { | ||||||
|  | @ -520,6 +519,39 @@ void online_page(struct page *page) | ||||||
| 	num_physpages++; | 	num_physpages++; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifndef CONFIG_MEMORY_HOTPLUG | ||||||
|  | /*
 | ||||||
|  |  * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance, | ||||||
|  |  * just online the pages. | ||||||
|  |  */ | ||||||
|  | int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages) | ||||||
|  | { | ||||||
|  | 	int err = -EIO; | ||||||
|  | 	unsigned long pfn; | ||||||
|  | 	unsigned long total = 0, mem = 0; | ||||||
|  | 	for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) { | ||||||
|  | 		unsigned long addr = pfn << PAGE_SHIFT; | ||||||
|  | 		if (pfn_valid(pfn) && e820_mapped(addr, addr+1, E820_RAM)) { | ||||||
|  | 			online_page(pfn_to_page(pfn)); | ||||||
|  | 			err = 0; | ||||||
|  | 			mem++; | ||||||
|  | 		} | ||||||
|  | 		total++; | ||||||
|  | 	} | ||||||
|  | 	if (!err) { | ||||||
|  | 		z->spanned_pages += total; | ||||||
|  | 		z->present_pages += mem; | ||||||
|  | 		z->zone_pgdat->node_spanned_pages += total; | ||||||
|  | 		z->zone_pgdat->node_present_pages += mem; | ||||||
|  | 	} | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Memory is added always to NORMAL zone. This means you will never get | ||||||
|  |  * additional DMA/DMA32 memory. | ||||||
|  |  */ | ||||||
| int add_memory(u64 start, u64 size) | int add_memory(u64 start, u64 size) | ||||||
| { | { | ||||||
| 	struct pglist_data *pgdat = NODE_DATA(0); | 	struct pglist_data *pgdat = NODE_DATA(0); | ||||||
|  |  | ||||||
|  | @ -329,7 +329,7 @@ config ACPI_CONTAINER | ||||||
| config ACPI_HOTPLUG_MEMORY | config ACPI_HOTPLUG_MEMORY | ||||||
| 	tristate "Memory Hotplug" | 	tristate "Memory Hotplug" | ||||||
| 	depends on ACPI | 	depends on ACPI | ||||||
| 	depends on MEMORY_HOTPLUG | 	depends on MEMORY_HOTPLUG || X86_64 | ||||||
| 	default n | 	default n | ||||||
| 	help | 	help | ||||||
| 	  This driver adds supports for ACPI Memory Hotplug.  This driver | 	  This driver adds supports for ACPI Memory Hotplug.  This driver | ||||||
|  |  | ||||||
|  | @ -245,7 +245,8 @@ void __init parse_early_param(void); | ||||||
| #define __cpuexitdata	__exitdata | #define __cpuexitdata	__exitdata | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_MEMORY_HOTPLUG | #if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \ | ||||||
|  | 	|| defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE) | ||||||
| #define __meminit | #define __meminit | ||||||
| #define __meminitdata | #define __meminitdata | ||||||
| #define __memexit | #define __memexit | ||||||
|  |  | ||||||
|  | @ -58,8 +58,6 @@ extern int add_one_highpage(struct page *page, int pfn, int bad_ppro); | ||||||
| /* need some defines for these for archs that don't support it */ | /* need some defines for these for archs that don't support it */ | ||||||
| extern void online_page(struct page *page); | extern void online_page(struct page *page); | ||||||
| /* VM interface that may be used by firmware interface */ | /* VM interface that may be used by firmware interface */ | ||||||
| extern int add_memory(u64 start, u64 size); |  | ||||||
| extern int remove_memory(u64 start, u64 size); |  | ||||||
| extern int online_pages(unsigned long, unsigned long); | extern int online_pages(unsigned long, unsigned long); | ||||||
| 
 | 
 | ||||||
| /* reasonably generic interface to expand the physical pages in a zone  */ | /* reasonably generic interface to expand the physical pages in a zone  */ | ||||||
|  | @ -92,11 +90,6 @@ static inline int mhp_notimplemented(const char *func) | ||||||
| 	return -ENOSYS; | 	return -ENOSYS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline int __add_pages(struct zone *zone, unsigned long start_pfn, |  | ||||||
| 	unsigned long nr_pages) |  | ||||||
| { |  | ||||||
| 	return mhp_notimplemented(__FUNCTION__); |  | ||||||
| } |  | ||||||
| #endif /* ! CONFIG_MEMORY_HOTPLUG */ | #endif /* ! CONFIG_MEMORY_HOTPLUG */ | ||||||
| static inline int __remove_pages(struct zone *zone, unsigned long start_pfn, | static inline int __remove_pages(struct zone *zone, unsigned long start_pfn, | ||||||
| 	unsigned long nr_pages) | 	unsigned long nr_pages) | ||||||
|  | @ -105,4 +98,11 @@ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn, | ||||||
| 	dump_stack(); | 	dump_stack(); | ||||||
| 	return -ENOSYS; | 	return -ENOSYS; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \ | ||||||
|  | 	|| defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE) | ||||||
|  | extern int add_memory(u64 start, u64 size); | ||||||
|  | extern int remove_memory(u64 start, u64 size); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #endif /* __LINUX_MEMORY_HOTPLUG_H */ | #endif /* __LINUX_MEMORY_HOTPLUG_H */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Andi Kleen
						Andi Kleen