diff options
-rw-r--r-- | include/linux/memblock.h | 24 | ||||
-rw-r--r-- | mm/memblock.c | 12 | ||||
-rw-r--r-- | mm/memory_hotplug.c | 1 |
3 files changed, 37 insertions, 0 deletions
diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 97480d392e40..2f52c8c492bd 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h | |||
@@ -47,6 +47,10 @@ struct memblock { | |||
47 | 47 | ||
48 | extern struct memblock memblock; | 48 | extern struct memblock memblock; |
49 | extern int memblock_debug; | 49 | extern int memblock_debug; |
50 | #ifdef CONFIG_MOVABLE_NODE | ||
51 | /* If movable_node boot option specified */ | ||
52 | extern bool movable_node_enabled; | ||
53 | #endif /* CONFIG_MOVABLE_NODE */ | ||
50 | 54 | ||
51 | #define memblock_dbg(fmt, ...) \ | 55 | #define memblock_dbg(fmt, ...) \ |
52 | if (memblock_debug) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) | 56 | if (memblock_debug) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) |
@@ -65,6 +69,26 @@ int memblock_reserve(phys_addr_t base, phys_addr_t size); | |||
65 | void memblock_trim_memory(phys_addr_t align); | 69 | void memblock_trim_memory(phys_addr_t align); |
66 | int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); | 70 | int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); |
67 | int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); | 71 | int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); |
72 | #ifdef CONFIG_MOVABLE_NODE | ||
73 | static inline bool memblock_is_hotpluggable(struct memblock_region *m) | ||
74 | { | ||
75 | return m->flags & MEMBLOCK_HOTPLUG; | ||
76 | } | ||
77 | |||
78 | static inline bool movable_node_is_enabled(void) | ||
79 | { | ||
80 | return movable_node_enabled; | ||
81 | } | ||
82 | #else | ||
83 | static inline bool memblock_is_hotpluggable(struct memblock_region *m) | ||
84 | { | ||
85 | return false; | ||
86 | } | ||
87 | static inline bool movable_node_is_enabled(void) | ||
88 | { | ||
89 | return false; | ||
90 | } | ||
91 | #endif | ||
68 | 92 | ||
69 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP | 93 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP |
70 | int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn, | 94 | int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn, |
diff --git a/mm/memblock.c b/mm/memblock.c index d5681008dce1..6a2a48a122a9 100644 --- a/mm/memblock.c +++ b/mm/memblock.c | |||
@@ -39,6 +39,9 @@ struct memblock memblock __initdata_memblock = { | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | int memblock_debug __initdata_memblock; | 41 | int memblock_debug __initdata_memblock; |
42 | #ifdef CONFIG_MOVABLE_NODE | ||
43 | bool movable_node_enabled __initdata_memblock = false; | ||
44 | #endif | ||
42 | static int memblock_can_resize __initdata_memblock; | 45 | static int memblock_can_resize __initdata_memblock; |
43 | static int memblock_memory_in_slab __initdata_memblock = 0; | 46 | static int memblock_memory_in_slab __initdata_memblock = 0; |
44 | static int memblock_reserved_in_slab __initdata_memblock = 0; | 47 | static int memblock_reserved_in_slab __initdata_memblock = 0; |
@@ -820,6 +823,11 @@ void __init_memblock __next_free_mem_range(u64 *idx, int nid, | |||
820 | * @out_nid: ptr to int for nid of the range, can be %NULL | 823 | * @out_nid: ptr to int for nid of the range, can be %NULL |
821 | * | 824 | * |
822 | * Reverse of __next_free_mem_range(). | 825 | * Reverse of __next_free_mem_range(). |
826 | * | ||
827 | * Linux kernel cannot migrate pages used by itself. Memory hotplug users won't | ||
828 | * be able to hot-remove hotpluggable memory used by the kernel. So this | ||
829 | * function skip hotpluggable regions if needed when allocating memory for the | ||
830 | * kernel. | ||
823 | */ | 831 | */ |
824 | void __init_memblock __next_free_mem_range_rev(u64 *idx, int nid, | 832 | void __init_memblock __next_free_mem_range_rev(u64 *idx, int nid, |
825 | phys_addr_t *out_start, | 833 | phys_addr_t *out_start, |
@@ -844,6 +852,10 @@ void __init_memblock __next_free_mem_range_rev(u64 *idx, int nid, | |||
844 | if (nid != MAX_NUMNODES && nid != memblock_get_region_node(m)) | 852 | if (nid != MAX_NUMNODES && nid != memblock_get_region_node(m)) |
845 | continue; | 853 | continue; |
846 | 854 | ||
855 | /* skip hotpluggable memory regions if needed */ | ||
856 | if (movable_node_is_enabled() && memblock_is_hotpluggable(m)) | ||
857 | continue; | ||
858 | |||
847 | /* scan areas before each reservation for intersection */ | 859 | /* scan areas before each reservation for intersection */ |
848 | for ( ; ri >= 0; ri--) { | 860 | for ( ; ri >= 0; ri--) { |
849 | struct memblock_region *r = &rsv->regions[ri]; | 861 | struct memblock_region *r = &rsv->regions[ri]; |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 489f235502db..01e39afde1cb 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -1446,6 +1446,7 @@ static int __init cmdline_parse_movable_node(char *p) | |||
1446 | * the kernel away from hotpluggable memory. | 1446 | * the kernel away from hotpluggable memory. |
1447 | */ | 1447 | */ |
1448 | memblock_set_bottom_up(true); | 1448 | memblock_set_bottom_up(true); |
1449 | movable_node_enabled = true; | ||
1449 | #else | 1450 | #else |
1450 | pr_warn("movable_node option not supported\n"); | 1451 | pr_warn("movable_node option not supported\n"); |
1451 | #endif | 1452 | #endif |