diff for duplicates of <50C135EA.2030308@gmail.com> diff --git a/a/2.txt b/N1/2.txt index 8b13789..b212b3c 100644 --- a/a/2.txt +++ b/N1/2.txt @@ -1 +1,172 @@ +>From 0ba5a0996d307d89f19ef79cf5fed1f8c4a7ed27 Mon Sep 17 00:00:00 2001 +From: Jiang Liu <jiang.liu@huawei.com> +Date: Sun, 2 Dec 2012 20:54:32 +0800 +Subject: [PATCH 1/3] memblock: introduce interfaces to assoicate tag and data + with reserved regions +Currently some subsystems use private static arrays to store information +assoicated with memory blocks allocated/reserved from memblock subsystem. +For example, dma-contiguous.c uses cma_reserved[] to store information +assoicated with allocated memory blocks. + +So introduce interfaces to associate tag(type) and caller specific data +with allocated/reserved memblock regions. Users of memblock subsystem +may be simplified by using these new interfaces. + +Signed-off-by: Jiang Liu <jiang.liu@huawei.com> +--- + include/linux/memblock.h | 33 ++++++++++++++++++++++++++ + mm/Kconfig | 3 +++ + mm/memblock.c | 58 +++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 93 insertions(+), 1 deletion(-) + +diff --git a/include/linux/memblock.h b/include/linux/memblock.h +index d452ee1..40dea53 100644 +--- a/include/linux/memblock.h ++++ b/include/linux/memblock.h +@@ -22,6 +22,10 @@ + struct memblock_region { + phys_addr_t base; + phys_addr_t size; ++#ifdef CONFIG_HAVE_MEMBLOCK_TAG ++ void *data; ++ int tag; ++#endif + #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP + int nid; + #endif +@@ -118,6 +122,35 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, + i != (u64)ULLONG_MAX; \ + __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid)) + ++#ifdef CONFIG_HAVE_MEMBLOCK_TAG ++#define MEMBLOCK_TAG_DEFAULT 0x0 /* default tag for bootmem allocatror */ ++ ++int memblock_mark_tag(phys_addr_t base, phys_addr_t size, int tag, void *data); ++void memblock_free_all_with_tag(int tag); ++ ++/* Only merge regions with default tag */ ++static inline bool memblock_tag_mergeable(struct memblock_region *prev, ++ struct memblock_region *next) ++{ ++ return prev->tag == MEMBLOCK_TAG_DEFAULT && ++ next->tag == MEMBLOCK_TAG_DEFAULT; ++} ++ ++static inline void memblock_init_tag(struct memblock_region *reg) ++{ ++ reg->tag = MEMBLOCK_TAG_DEFAULT; ++ reg->data = NULL; ++} ++#else /* CONFIG_HAVE_MEMBLOCK_TAG */ ++static inline bool memblock_tag_mergeable(struct memblock_region *prev, ++ struct memblock_region *next) ++{ ++ return true; ++} ++ ++static inline void memblock_init_tag(struct memblock_region *reg) {} ++#endif /* CONFIG_HAVE_MEMBLOCK_TAG */ ++ + #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP + int memblock_set_node(phys_addr_t base, phys_addr_t size, int nid); + +diff --git a/mm/Kconfig b/mm/Kconfig +index a3f8ddd..5080390 100644 +--- a/mm/Kconfig ++++ b/mm/Kconfig +@@ -131,6 +131,9 @@ config SPARSEMEM_VMEMMAP + config HAVE_MEMBLOCK + boolean + ++config HAVE_MEMBLOCK_TAG ++ boolean ++ + config HAVE_MEMBLOCK_NODE_MAP + boolean + +diff --git a/mm/memblock.c b/mm/memblock.c +index 6259055..c2c644e 100644 +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -307,7 +307,8 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type) + + if (this->base + this->size != next->base || + memblock_get_region_node(this) != +- memblock_get_region_node(next)) { ++ memblock_get_region_node(next) || ++ !memblock_tag_mergeable(this, next)) { + BUG_ON(this->base + this->size > next->base); + i++; + continue; +@@ -339,6 +340,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type, + memmove(rgn + 1, rgn, (type->cnt - idx) * sizeof(*rgn)); + rgn->base = base; + rgn->size = size; ++ memblock_init_tag(rgn); + memblock_set_region_node(rgn, nid); + type->cnt++; + type->total_size += size; +@@ -764,6 +766,60 @@ int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size, + } + #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ + ++#ifdef CONFIG_HAVE_MEMBLOCK_TAG ++/** ++ * memblock_mark_tag - mark @tag and @data with reserved regions ++ * @base: base of area to mark @tag and @data with ++ * @size: size of area to mark @tag and @data with ++ * @tag: tag (type) to assoicated with reserved regions ++ * @data: caller specific data to associated with reserved regions ++ * ++ * Associate @tag(type) and caller specific @data with reserved memblock ++ * regions in [@base,@base+@size). ++ * Regions which cross the area boundaries are split as necessary. ++ * ++ * RETURNS: ++ * 0 on success, -errno on failure. ++ */ ++int __init_memblock memblock_mark_tag(phys_addr_t base, phys_addr_t size, ++ int tag, void *data) ++{ ++ struct memblock_type *type = &memblock.reserved; ++ int start_rgn, end_rgn; ++ int i, ret; ++ ++ ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn); ++ if (ret) ++ return ret; ++ ++ for (i = start_rgn; i < end_rgn; i++) { ++ type->regions[i].tag = tag; ++ type->regions[i].data = data; ++ } ++ ++ memblock_merge_regions(type); ++ ++ return 0; ++} ++ ++/** ++ * memblock_free_all_with_tag - free all reserved regions with @tag ++ * @tag: tag to identify reserved memblock regions to be freed ++ * ++ * Free all reserved memblock regions with tag (type) of @tag ++ */ ++void __init_memblock memblock_free_all_with_tag(int tag) ++{ ++ int i; ++ struct memblock_type *type = &memblock.reserved; ++ ++ /* scan backward because it may remove current region */ ++ for (i = type->cnt - 1; i >= 0; i--) ++ if (type->regions[i].tag == tag) ++ memblock_remove_region(type, i); ++} ++#endif /* CONFIG_HAVE_MEMBLOCK_TAG */ ++ + static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size, + phys_addr_t align, phys_addr_t max_addr, + int nid) +-- +1.7.9.5 diff --git a/N1/3.hdr b/N1/3.hdr new file mode 100644 index 0000000..7623aaf --- /dev/null +++ b/N1/3.hdr @@ -0,0 +1,6 @@ +Content-Type: text/x-patch; + name="0002-x86-memhotplug-reserve-memory-from-bootmem-allocator.patch" +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment; + filename*0="0002-x86-memhotplug-reserve-memory-from-bootmem-allocator.pa"; + filename*1="tch" diff --git a/N1/3.txt b/N1/3.txt new file mode 100644 index 0000000..61aa094 --- /dev/null +++ b/N1/3.txt @@ -0,0 +1,188 @@ +>From ba05910c7915e3f95a0cd0893b9abc6cd98ab22e Mon Sep 17 00:00:00 2001 +From: Jiang Liu <jiang.liu@huawei.com> +Date: Sun, 2 Dec 2012 21:26:21 +0800 +Subject: [PATCH 2/3] x86, memhotplug: reserve memory from bootmem allocator + for memory hotplug + +There's no mechanism to migrate pages allocated from bootmem allocator, +thus a memory device may become irremovable if bootmem allocates any +pages from it. + +This patch introduces a mechanism to +1) reserve memory from bootmem allocator for hotplug early 'enough' + during boot. +2) free reserve memory into buddy system at late when memory hogplug + infrastructure has been initialized. + +Signed-off-by: Jiang Liu <jiang.liu@huawei.com> +--- + arch/x86/kernel/setup.c | 11 ++++++++ + arch/x86/mm/init.c | 56 ++++++++++++++++++++++++++++++++++++++++ + arch/x86/mm/init_32.c | 2 ++ + arch/x86/mm/init_64.c | 2 ++ + include/linux/memblock.h | 1 + + include/linux/memory_hotplug.h | 5 ++++ + mm/Kconfig | 1 + + 7 files changed, 78 insertions(+) + +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index ca45696..93f6f10 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -940,6 +940,17 @@ void __init setup_arch(char **cmdline_p) + max_low_pfn = max_pfn; + } + #endif ++ ++ /* ++ * Try to reserve memory from bootmem allocator for memory hotplug ++ * before updating memblock.current_limit to cover all low memory. ++ * Until now memblock.current_limit is still set to the initial value ++ * of max_pfn_mapped, which is 512M on x86_64 and xxx on i386. And ++ * memblock allocates available memory in reverse order, so we almost ++ * have no chance to reserve memory below 512M for memory hotplug. ++ */ ++ reserve_memory_for_hotplug(); ++ + memblock.current_limit = get_max_mapped(); + dma_contiguous_reserve(0); + +diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c +index d7aea41..36bb5c2 100644 +--- a/arch/x86/mm/init.c ++++ b/arch/x86/mm/init.c +@@ -424,3 +424,59 @@ void __init zone_sizes_init(void) + free_area_init_nodes(max_zone_pfns); + } + ++#ifdef CONFIG_MEMORY_HOTREMOVE ++static int __init reserve_bootmem_for_hotplug(phys_addr_t base, ++ phys_addr_t size) ++{ ++ if (memblock_is_region_reserved(base, size) || ++ memblock_reserve(base, size) < 0) ++ return -EBUSY; ++ ++ BUG_ON(memblock_mark_tag(base, size, MEMBLOCK_TAG_HOTPLUG, NULL)); ++ ++ return 0; ++} ++ ++/* ++ * Try to reserve low memory for hotplug according to user configured ++ * movablecore_map. Movable zone hasn't been determined yet, so can't rely ++ * on zone_movable_is_highmem() but to reserve all low memory configured by ++ * movablecore_map parameter. ++ * Assume entries in movablecore_map.map are sorted in increasing order. ++ */ ++static int __init reserve_hotplug_memory_from_movable_map(void) ++{ ++ int i; ++ phys_addr_t start, end; ++ struct movablecore_entry *ep; ++ ++ if (movablecore_map.nr_map == 0) ++ return 0; ++ ++ for (i = 0; i < movablecore_map.nr_map; i++) { ++ ep = &movablecore_map.map[i]; ++ start = ep->start << PAGE_SHIFT; ++ end = (min(ep->end, max_low_pfn) + 1) << PAGE_SHIFT; ++ if (end <= start) ++ break; ++ ++ if (reserve_bootmem_for_hotplug(start, end - start)) ++ pr_warn("mm: failed to reserve lowmem [%#016llx-%#016llx] for hotplug.", ++ (unsigned long long)start, ++ (unsigned long long)end - 1); ++ } ++ ++ return 1; ++} ++ ++void __init reserve_memory_for_hotplug(void) ++{ ++ if (reserve_hotplug_memory_from_movable_map()) ++ return; ++} ++ ++void __init free_memory_reserved_for_hotplug(void) ++{ ++ memblock_free_all_with_tag(MEMBLOCK_TAG_HOTPLUG); ++} ++#endif +diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c +index 11a5800..815700a 100644 +--- a/arch/x86/mm/init_32.c ++++ b/arch/x86/mm/init_32.c +@@ -745,6 +745,8 @@ void __init mem_init(void) + */ + set_highmem_pages_init(); + ++ free_memory_reserved_for_hotplug(); ++ + /* this will put all low memory onto the freelists */ + totalram_pages += free_all_bootmem(); + +diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c +index 3baff25..1a92fd6 100644 +--- a/arch/x86/mm/init_64.c ++++ b/arch/x86/mm/init_64.c +@@ -695,6 +695,8 @@ void __init mem_init(void) + + reservedpages = 0; + ++ free_memory_reserved_for_hotplug(); ++ + /* this will put all low memory onto the freelists */ + #ifdef CONFIG_NUMA + totalram_pages = numa_free_all_bootmem(); +diff --git a/include/linux/memblock.h b/include/linux/memblock.h +index 40dea53..5420ed9 100644 +--- a/include/linux/memblock.h ++++ b/include/linux/memblock.h +@@ -124,6 +124,7 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, + + #ifdef CONFIG_HAVE_MEMBLOCK_TAG + #define MEMBLOCK_TAG_DEFAULT 0x0 /* default tag for bootmem allocatror */ ++#define MEMBLOCK_TAG_HOTPLUG 0x1 /* reserved for memory hotplug */ + + int memblock_mark_tag(phys_addr_t base, phys_addr_t size, int tag, void *data); + void memblock_free_all_with_tag(int tag); +diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h +index 95573ec..edf183d 100644 +--- a/include/linux/memory_hotplug.h ++++ b/include/linux/memory_hotplug.h +@@ -222,6 +222,8 @@ static inline void unlock_memory_hotplug(void) {} + #ifdef CONFIG_MEMORY_HOTREMOVE + + extern int is_mem_section_removable(unsigned long pfn, unsigned long nr_pages); ++extern void reserve_memory_for_hotplug(void); ++extern void free_memory_reserved_for_hotplug(void); + + #else + static inline int is_mem_section_removable(unsigned long pfn, +@@ -229,6 +231,9 @@ static inline int is_mem_section_removable(unsigned long pfn, + { + return 0; + } ++ ++static inline void reserve_memory_for_hotplug(void) {} ++static inline void free_memory_reserved_for_hotplug(void) {} + #endif /* CONFIG_MEMORY_HOTREMOVE */ + + extern int mem_online_node(int nid); +diff --git a/mm/Kconfig b/mm/Kconfig +index 5080390..9d69e5d 100644 +--- a/mm/Kconfig ++++ b/mm/Kconfig +@@ -160,6 +160,7 @@ config MEMORY_HOTPLUG_SPARSE + + config MEMORY_HOTREMOVE + bool "Allow for memory hot remove" ++ select HAVE_MEMBLOCK_TAG + depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE + depends on MIGRATION + +-- +1.7.9.5 diff --git a/N1/4.hdr b/N1/4.hdr new file mode 100644 index 0000000..453cade --- /dev/null +++ b/N1/4.hdr @@ -0,0 +1,6 @@ +Content-Type: text/x-patch; + name="0003-CMA-use-new-memblock-interfaces-to-simplify-implemen.patch" +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment; + filename*0="0003-CMA-use-new-memblock-interfaces-to-simplify-implemen.pa"; + filename*1="tch" diff --git a/N1/4.txt b/N1/4.txt new file mode 100644 index 0000000..d4cb98a --- /dev/null +++ b/N1/4.txt @@ -0,0 +1,116 @@ +>From d1ddc6e2196758923c71d649d52b9a14d678419b Mon Sep 17 00:00:00 2001 +From: Jiang Liu <jiang.liu@huawei.com> +Date: Sun, 2 Dec 2012 21:00:52 +0800 +Subject: [PATCH 3/3] CMA: use new memblock interfaces to simplify + implementation + +This patch simplifies dma-continuous.c by using new memblock interfaces. + +Signed-off-by: Jiang Liu <jiang.liu@huawei.com> +--- + drivers/base/Kconfig | 1 + + drivers/base/dma-contiguous.c | 36 +++++++++++++----------------------- + include/linux/memblock.h | 1 + + 3 files changed, 15 insertions(+), 23 deletions(-) + +diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig +index b34b5cd..b0ac008 100644 +--- a/drivers/base/Kconfig ++++ b/drivers/base/Kconfig +@@ -197,6 +197,7 @@ config CMA + depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK && EXPERIMENTAL + select MIGRATION + select MEMORY_ISOLATION ++ select HAVE_MEMBLOCK_TAG + help + This enables the Contiguous Memory Allocator which allows drivers + to allocate big physically-contiguous blocks of memory for use with +diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c +index 612afcc..c092b76 100644 +--- a/drivers/base/dma-contiguous.c ++++ b/drivers/base/dma-contiguous.c +@@ -190,27 +190,24 @@ no_mem: + return ERR_PTR(ret); + } + +-static struct cma_reserved { +- phys_addr_t start; +- unsigned long size; +- struct device *dev; +-} cma_reserved[MAX_CMA_AREAS] __initdata; + static unsigned cma_reserved_count __initdata; + + static int __init cma_init_reserved_areas(void) + { +- struct cma_reserved *r = cma_reserved; +- unsigned i = cma_reserved_count; ++ struct memblock_region *reg; ++ struct cma *cma; + + pr_debug("%s()\n", __func__); + +- for (; i; --i, ++r) { +- struct cma *cma; +- cma = cma_create_area(PFN_DOWN(r->start), +- r->size >> PAGE_SHIFT); +- if (!IS_ERR(cma)) +- dev_set_cma_area(r->dev, cma); +- } ++ for_each_memblock(memory, reg) ++ if (reg->tag == MEMBLOCK_TAG_CMA) { ++ cma = cma_create_area(PFN_DOWN(reg->base), ++ reg->size >> PAGE_SHIFT); ++ if (!IS_ERR(cma)) ++ dev_set_cma_area(reg->data, cma); ++ } ++ memblock_free_all_with_tag(MEMBLOCK_TAG_CMA); ++ + return 0; + } + core_initcall(cma_init_reserved_areas); +@@ -230,7 +227,6 @@ core_initcall(cma_init_reserved_areas); + int __init dma_declare_contiguous(struct device *dev, unsigned long size, + phys_addr_t base, phys_addr_t limit) + { +- struct cma_reserved *r = &cma_reserved[cma_reserved_count]; + unsigned long alignment; + + pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__, +@@ -238,7 +234,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size, + (unsigned long)limit); + + /* Sanity checks */ +- if (cma_reserved_count == ARRAY_SIZE(cma_reserved)) { ++ if (cma_reserved_count == MAX_CMA_AREAS) { + pr_err("Not enough slots for CMA reserved regions!\n"); + return -ENOSPC; + } +@@ -277,13 +273,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size, + } + } + +- /* +- * Each reserved area must be initialised later, when more kernel +- * subsystems (like slab allocator) are available. +- */ +- r->start = base; +- r->size = size; +- r->dev = dev; ++ BUG_ON(memblock_mark_tag(base, size, MEMBLOCK_TAG_CMA, dev)); + cma_reserved_count++; + pr_info("CMA: reserved %ld MiB at %08lx\n", size / SZ_1M, + (unsigned long)base); +diff --git a/include/linux/memblock.h b/include/linux/memblock.h +index 5420ed9..a662c07 100644 +--- a/include/linux/memblock.h ++++ b/include/linux/memblock.h +@@ -125,6 +125,7 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, + #ifdef CONFIG_HAVE_MEMBLOCK_TAG + #define MEMBLOCK_TAG_DEFAULT 0x0 /* default tag for bootmem allocatror */ + #define MEMBLOCK_TAG_HOTPLUG 0x1 /* reserved for memory hotplug */ ++#define MEMBLOCK_TAG_CMA 0x2 /* reserved for CMA */ + + int memblock_mark_tag(phys_addr_t base, phys_addr_t size, int tag, void *data); + void memblock_free_all_with_tag(int tag); +-- +1.7.9.5 diff --git a/a/content_digest b/N1/content_digest index 186a4ec..2bbe4a3 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -47,5 +47,487 @@ "\01:2\0" "fn\00001-memblock-introduce-interfaces-to-assoicate-tag-and-d.patch\0" "b\0" + ">From 0ba5a0996d307d89f19ef79cf5fed1f8c4a7ed27 Mon Sep 17 00:00:00 2001\n" + "From: Jiang Liu <jiang.liu@huawei.com>\n" + "Date: Sun, 2 Dec 2012 20:54:32 +0800\n" + "Subject: [PATCH 1/3] memblock: introduce interfaces to assoicate tag and data\n" + " with reserved regions\n" + "\n" + "Currently some subsystems use private static arrays to store information\n" + "assoicated with memory blocks allocated/reserved from memblock subsystem.\n" + "For example, dma-contiguous.c uses cma_reserved[] to store information\n" + "assoicated with allocated memory blocks.\n" + "\n" + "So introduce interfaces to associate tag(type) and caller specific data\n" + "with allocated/reserved memblock regions. Users of memblock subsystem\n" + "may be simplified by using these new interfaces.\n" + "\n" + "Signed-off-by: Jiang Liu <jiang.liu@huawei.com>\n" + "---\n" + " include/linux/memblock.h | 33 ++++++++++++++++++++++++++\n" + " mm/Kconfig | 3 +++\n" + " mm/memblock.c | 58 +++++++++++++++++++++++++++++++++++++++++++++-\n" + " 3 files changed, 93 insertions(+), 1 deletion(-)\n" + "\n" + "diff --git a/include/linux/memblock.h b/include/linux/memblock.h\n" + "index d452ee1..40dea53 100644\n" + "--- a/include/linux/memblock.h\n" + "+++ b/include/linux/memblock.h\n" + "@@ -22,6 +22,10 @@\n" + " struct memblock_region {\n" + " \tphys_addr_t base;\n" + " \tphys_addr_t size;\n" + "+#ifdef CONFIG_HAVE_MEMBLOCK_TAG\n" + "+\tvoid *data;\n" + "+\tint tag;\n" + "+#endif\n" + " #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP\n" + " \tint nid;\n" + " #endif\n" + "@@ -118,6 +122,35 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start,\n" + " \t i != (u64)ULLONG_MAX;\t\t\t\t\t\\\n" + " \t __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid))\n" + " \n" + "+#ifdef CONFIG_HAVE_MEMBLOCK_TAG\n" + "+#define\tMEMBLOCK_TAG_DEFAULT\t0x0 /* default tag for bootmem allocatror */\n" + "+\n" + "+int memblock_mark_tag(phys_addr_t base, phys_addr_t size, int tag, void *data);\n" + "+void memblock_free_all_with_tag(int tag);\n" + "+\n" + "+/* Only merge regions with default tag */\n" + "+static inline bool memblock_tag_mergeable(struct memblock_region *prev,\n" + "+\t\t\t\t\t struct memblock_region *next)\n" + "+{\n" + "+\treturn prev->tag == MEMBLOCK_TAG_DEFAULT &&\n" + "+\t next->tag == MEMBLOCK_TAG_DEFAULT;\n" + "+}\n" + "+\n" + "+static inline void memblock_init_tag(struct memblock_region *reg)\n" + "+{\n" + "+\treg->tag = MEMBLOCK_TAG_DEFAULT;\n" + "+\treg->data = NULL;\n" + "+}\n" + "+#else /* CONFIG_HAVE_MEMBLOCK_TAG */\n" + "+static inline bool memblock_tag_mergeable(struct memblock_region *prev,\n" + "+\t\t\t\t\t struct memblock_region *next)\n" + "+{\n" + "+\treturn true;\n" + "+}\n" + "+\n" + "+static inline void memblock_init_tag(struct memblock_region *reg) {}\n" + "+#endif /* CONFIG_HAVE_MEMBLOCK_TAG */\n" + "+\n" + " #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP\n" + " int memblock_set_node(phys_addr_t base, phys_addr_t size, int nid);\n" + " \n" + "diff --git a/mm/Kconfig b/mm/Kconfig\n" + "index a3f8ddd..5080390 100644\n" + "--- a/mm/Kconfig\n" + "+++ b/mm/Kconfig\n" + "@@ -131,6 +131,9 @@ config SPARSEMEM_VMEMMAP\n" + " config HAVE_MEMBLOCK\n" + " \tboolean\n" + " \n" + "+config HAVE_MEMBLOCK_TAG\n" + "+\tboolean\n" + "+\n" + " config HAVE_MEMBLOCK_NODE_MAP\n" + " \tboolean\n" + " \n" + "diff --git a/mm/memblock.c b/mm/memblock.c\n" + "index 6259055..c2c644e 100644\n" + "--- a/mm/memblock.c\n" + "+++ b/mm/memblock.c\n" + "@@ -307,7 +307,8 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type)\n" + " \n" + " \t\tif (this->base + this->size != next->base ||\n" + " \t\t memblock_get_region_node(this) !=\n" + "-\t\t memblock_get_region_node(next)) {\n" + "+\t\t memblock_get_region_node(next) ||\n" + "+\t\t !memblock_tag_mergeable(this, next)) {\n" + " \t\t\tBUG_ON(this->base + this->size > next->base);\n" + " \t\t\ti++;\n" + " \t\t\tcontinue;\n" + "@@ -339,6 +340,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type,\n" + " \tmemmove(rgn + 1, rgn, (type->cnt - idx) * sizeof(*rgn));\n" + " \trgn->base = base;\n" + " \trgn->size = size;\n" + "+\tmemblock_init_tag(rgn);\n" + " \tmemblock_set_region_node(rgn, nid);\n" + " \ttype->cnt++;\n" + " \ttype->total_size += size;\n" + "@@ -764,6 +766,60 @@ int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,\n" + " }\n" + " #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */\n" + " \n" + "+#ifdef CONFIG_HAVE_MEMBLOCK_TAG\n" + "+/**\n" + "+ * memblock_mark_tag - mark @tag and @data with reserved regions\n" + "+ * @base: base of area to mark @tag and @data with\n" + "+ * @size: size of area to mark @tag and @data with\n" + "+ * @tag: tag (type) to assoicated with reserved regions\n" + "+ * @data: caller specific data to associated with reserved regions\n" + "+ *\n" + "+ * Associate @tag(type) and caller specific @data with reserved memblock\n" + "+ * regions in [@base,@base+@size).\n" + "+ * Regions which cross the area boundaries are split as necessary.\n" + "+ *\n" + "+ * RETURNS:\n" + "+ * 0 on success, -errno on failure.\n" + "+ */\n" + "+int __init_memblock memblock_mark_tag(phys_addr_t base, phys_addr_t size,\n" + "+\t\t\t\t int tag, void *data)\n" + "+{\n" + "+\tstruct memblock_type *type = &memblock.reserved;\n" + "+\tint start_rgn, end_rgn;\n" + "+\tint i, ret;\n" + "+\n" + "+\tret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);\n" + "+\tif (ret)\n" + "+\t\treturn ret;\n" + "+\n" + "+\tfor (i = start_rgn; i < end_rgn; i++) {\n" + "+\t\ttype->regions[i].tag = tag;\n" + "+\t\ttype->regions[i].data = data;\n" + "+\t}\n" + "+\n" + "+\tmemblock_merge_regions(type);\n" + "+\n" + "+\treturn 0;\n" + "+}\n" + "+\n" + "+/**\n" + "+ * memblock_free_all_with_tag - free all reserved regions with @tag\n" + "+ * @tag: tag to identify reserved memblock regions to be freed\n" + "+ *\n" + "+ * Free all reserved memblock regions with tag (type) of @tag\n" + "+ */\n" + "+void __init_memblock memblock_free_all_with_tag(int tag)\n" + "+{\n" + "+\tint i;\n" + "+\tstruct memblock_type *type = &memblock.reserved;\n" + "+\n" + "+\t/* scan backward because it may remove current region */\n" + "+\tfor (i = type->cnt - 1; i >= 0; i--)\n" + "+\t\tif (type->regions[i].tag == tag)\n" + "+\t\t\tmemblock_remove_region(type, i);\n" + "+}\n" + "+#endif /* CONFIG_HAVE_MEMBLOCK_TAG */\n" + "+\n" + " static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,\n" + " \t\t\t\t\tphys_addr_t align, phys_addr_t max_addr,\n" + " \t\t\t\t\tint nid)\n" + "-- \n" + 1.7.9.5 + "\01:3\0" + "fn\00002-x86-memhotplug-reserve-memory-from-bootmem-allocator.patch\0" + "b\0" + ">From ba05910c7915e3f95a0cd0893b9abc6cd98ab22e Mon Sep 17 00:00:00 2001\n" + "From: Jiang Liu <jiang.liu@huawei.com>\n" + "Date: Sun, 2 Dec 2012 21:26:21 +0800\n" + "Subject: [PATCH 2/3] x86, memhotplug: reserve memory from bootmem allocator\n" + " for memory hotplug\n" + "\n" + "There's no mechanism to migrate pages allocated from bootmem allocator,\n" + "thus a memory device may become irremovable if bootmem allocates any\n" + "pages from it.\n" + "\n" + "This patch introduces a mechanism to\n" + "1) reserve memory from bootmem allocator for hotplug early 'enough'\n" + " during boot.\n" + "2) free reserve memory into buddy system at late when memory hogplug\n" + " infrastructure has been initialized.\n" + "\n" + "Signed-off-by: Jiang Liu <jiang.liu@huawei.com>\n" + "---\n" + " arch/x86/kernel/setup.c | 11 ++++++++\n" + " arch/x86/mm/init.c | 56 ++++++++++++++++++++++++++++++++++++++++\n" + " arch/x86/mm/init_32.c | 2 ++\n" + " arch/x86/mm/init_64.c | 2 ++\n" + " include/linux/memblock.h | 1 +\n" + " include/linux/memory_hotplug.h | 5 ++++\n" + " mm/Kconfig | 1 +\n" + " 7 files changed, 78 insertions(+)\n" + "\n" + "diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c\n" + "index ca45696..93f6f10 100644\n" + "--- a/arch/x86/kernel/setup.c\n" + "+++ b/arch/x86/kernel/setup.c\n" + "@@ -940,6 +940,17 @@ void __init setup_arch(char **cmdline_p)\n" + " \t\tmax_low_pfn = max_pfn;\n" + " \t}\n" + " #endif\n" + "+\n" + "+\t/*\n" + "+\t * Try to reserve memory from bootmem allocator for memory hotplug\n" + "+\t * before updating memblock.current_limit to cover all low memory.\n" + "+\t * Until now memblock.current_limit is still set to the initial value\n" + "+\t * of max_pfn_mapped, which is 512M on x86_64 and xxx on i386. And\n" + "+\t * memblock allocates available memory in reverse order, so we almost\n" + "+\t * have no chance to reserve memory below 512M for memory hotplug.\n" + "+\t */\n" + "+\treserve_memory_for_hotplug();\n" + "+\n" + " \tmemblock.current_limit = get_max_mapped();\n" + " \tdma_contiguous_reserve(0);\n" + " \n" + "diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c\n" + "index d7aea41..36bb5c2 100644\n" + "--- a/arch/x86/mm/init.c\n" + "+++ b/arch/x86/mm/init.c\n" + "@@ -424,3 +424,59 @@ void __init zone_sizes_init(void)\n" + " \tfree_area_init_nodes(max_zone_pfns);\n" + " }\n" + " \n" + "+#ifdef CONFIG_MEMORY_HOTREMOVE\n" + "+static int __init reserve_bootmem_for_hotplug(phys_addr_t base,\n" + "+\t\t\t\t\t phys_addr_t size)\n" + "+{\n" + "+\tif (memblock_is_region_reserved(base, size) ||\n" + "+\t memblock_reserve(base, size) < 0)\n" + "+\t\treturn -EBUSY;\n" + "+\n" + "+\tBUG_ON(memblock_mark_tag(base, size, MEMBLOCK_TAG_HOTPLUG, NULL));\n" + "+\n" + "+\treturn 0;\n" + "+}\n" + "+\n" + "+/*\n" + "+ * Try to reserve low memory for hotplug according to user configured\n" + "+ * movablecore_map. Movable zone hasn't been determined yet, so can't rely\n" + "+ * on zone_movable_is_highmem() but to reserve all low memory configured by\n" + "+ * movablecore_map parameter.\n" + "+ * Assume entries in movablecore_map.map are sorted in increasing order.\n" + "+ */\n" + "+static int __init reserve_hotplug_memory_from_movable_map(void)\n" + "+{\n" + "+\tint i;\n" + "+\tphys_addr_t start, end;\n" + "+\tstruct movablecore_entry *ep;\n" + "+\n" + "+\tif (movablecore_map.nr_map == 0)\n" + "+\t\treturn 0;\n" + "+\n" + "+\tfor (i = 0; i < movablecore_map.nr_map; i++) {\n" + "+\t\tep = &movablecore_map.map[i];\n" + "+\t\tstart = ep->start << PAGE_SHIFT;\n" + "+\t\tend = (min(ep->end, max_low_pfn) + 1) << PAGE_SHIFT;\n" + "+\t\tif (end <= start)\n" + "+\t\t\tbreak;\n" + "+\n" + "+\t\tif (reserve_bootmem_for_hotplug(start, end - start))\n" + "+\t\t\tpr_warn(\"mm: failed to reserve lowmem [%#016llx-%#016llx] for hotplug.\",\n" + "+\t\t\t\t(unsigned long long)start,\n" + "+\t\t\t\t(unsigned long long)end - 1);\n" + "+\t}\n" + "+\n" + "+\treturn 1;\n" + "+}\n" + "+\n" + "+void __init reserve_memory_for_hotplug(void)\n" + "+{\n" + "+\tif (reserve_hotplug_memory_from_movable_map())\n" + "+\t\treturn;\n" + "+}\n" + "+\n" + "+void __init free_memory_reserved_for_hotplug(void)\n" + "+{\n" + "+\tmemblock_free_all_with_tag(MEMBLOCK_TAG_HOTPLUG);\n" + "+}\n" + "+#endif\n" + "diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c\n" + "index 11a5800..815700a 100644\n" + "--- a/arch/x86/mm/init_32.c\n" + "+++ b/arch/x86/mm/init_32.c\n" + "@@ -745,6 +745,8 @@ void __init mem_init(void)\n" + " \t */\n" + " \tset_highmem_pages_init();\n" + " \n" + "+\tfree_memory_reserved_for_hotplug();\n" + "+\n" + " \t/* this will put all low memory onto the freelists */\n" + " \ttotalram_pages += free_all_bootmem();\n" + " \n" + "diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c\n" + "index 3baff25..1a92fd6 100644\n" + "--- a/arch/x86/mm/init_64.c\n" + "+++ b/arch/x86/mm/init_64.c\n" + "@@ -695,6 +695,8 @@ void __init mem_init(void)\n" + " \n" + " \treservedpages = 0;\n" + " \n" + "+\tfree_memory_reserved_for_hotplug();\n" + "+\n" + " \t/* this will put all low memory onto the freelists */\n" + " #ifdef CONFIG_NUMA\n" + " \ttotalram_pages = numa_free_all_bootmem();\n" + "diff --git a/include/linux/memblock.h b/include/linux/memblock.h\n" + "index 40dea53..5420ed9 100644\n" + "--- a/include/linux/memblock.h\n" + "+++ b/include/linux/memblock.h\n" + "@@ -124,6 +124,7 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start,\n" + " \n" + " #ifdef CONFIG_HAVE_MEMBLOCK_TAG\n" + " #define\tMEMBLOCK_TAG_DEFAULT\t0x0 /* default tag for bootmem allocatror */\n" + "+#define\tMEMBLOCK_TAG_HOTPLUG\t0x1 /* reserved for memory hotplug */\n" + " \n" + " int memblock_mark_tag(phys_addr_t base, phys_addr_t size, int tag, void *data);\n" + " void memblock_free_all_with_tag(int tag);\n" + "diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h\n" + "index 95573ec..edf183d 100644\n" + "--- a/include/linux/memory_hotplug.h\n" + "+++ b/include/linux/memory_hotplug.h\n" + "@@ -222,6 +222,8 @@ static inline void unlock_memory_hotplug(void) {}\n" + " #ifdef CONFIG_MEMORY_HOTREMOVE\n" + " \n" + " extern int is_mem_section_removable(unsigned long pfn, unsigned long nr_pages);\n" + "+extern void reserve_memory_for_hotplug(void);\n" + "+extern void free_memory_reserved_for_hotplug(void);\n" + " \n" + " #else\n" + " static inline int is_mem_section_removable(unsigned long pfn,\n" + "@@ -229,6 +231,9 @@ static inline int is_mem_section_removable(unsigned long pfn,\n" + " {\n" + " \treturn 0;\n" + " }\n" + "+\n" + "+static inline void reserve_memory_for_hotplug(void) {}\n" + "+static inline void free_memory_reserved_for_hotplug(void) {}\n" + " #endif /* CONFIG_MEMORY_HOTREMOVE */\n" + " \n" + " extern int mem_online_node(int nid);\n" + "diff --git a/mm/Kconfig b/mm/Kconfig\n" + "index 5080390..9d69e5d 100644\n" + "--- a/mm/Kconfig\n" + "+++ b/mm/Kconfig\n" + "@@ -160,6 +160,7 @@ config MEMORY_HOTPLUG_SPARSE\n" + " \n" + " config MEMORY_HOTREMOVE\n" + " \tbool \"Allow for memory hot remove\"\n" + "+\tselect HAVE_MEMBLOCK_TAG\n" + " \tdepends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE\n" + " \tdepends on MIGRATION\n" + " \n" + "-- \n" + 1.7.9.5 + "\01:4\0" + "fn\00003-CMA-use-new-memblock-interfaces-to-simplify-implemen.patch\0" + "b\0" + ">From d1ddc6e2196758923c71d649d52b9a14d678419b Mon Sep 17 00:00:00 2001\n" + "From: Jiang Liu <jiang.liu@huawei.com>\n" + "Date: Sun, 2 Dec 2012 21:00:52 +0800\n" + "Subject: [PATCH 3/3] CMA: use new memblock interfaces to simplify\n" + " implementation\n" + "\n" + "This patch simplifies dma-continuous.c by using new memblock interfaces.\n" + "\n" + "Signed-off-by: Jiang Liu <jiang.liu@huawei.com>\n" + "---\n" + " drivers/base/Kconfig | 1 +\n" + " drivers/base/dma-contiguous.c | 36 +++++++++++++-----------------------\n" + " include/linux/memblock.h | 1 +\n" + " 3 files changed, 15 insertions(+), 23 deletions(-)\n" + "\n" + "diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig\n" + "index b34b5cd..b0ac008 100644\n" + "--- a/drivers/base/Kconfig\n" + "+++ b/drivers/base/Kconfig\n" + "@@ -197,6 +197,7 @@ config CMA\n" + " \tdepends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK && EXPERIMENTAL\n" + " \tselect MIGRATION\n" + " \tselect MEMORY_ISOLATION\n" + "+\tselect HAVE_MEMBLOCK_TAG\n" + " \thelp\n" + " \t This enables the Contiguous Memory Allocator which allows drivers\n" + " \t to allocate big physically-contiguous blocks of memory for use with\n" + "diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c\n" + "index 612afcc..c092b76 100644\n" + "--- a/drivers/base/dma-contiguous.c\n" + "+++ b/drivers/base/dma-contiguous.c\n" + "@@ -190,27 +190,24 @@ no_mem:\n" + " \treturn ERR_PTR(ret);\n" + " }\n" + " \n" + "-static struct cma_reserved {\n" + "-\tphys_addr_t start;\n" + "-\tunsigned long size;\n" + "-\tstruct device *dev;\n" + "-} cma_reserved[MAX_CMA_AREAS] __initdata;\n" + " static unsigned cma_reserved_count __initdata;\n" + " \n" + " static int __init cma_init_reserved_areas(void)\n" + " {\n" + "-\tstruct cma_reserved *r = cma_reserved;\n" + "-\tunsigned i = cma_reserved_count;\n" + "+\tstruct memblock_region *reg;\n" + "+\tstruct cma *cma;\n" + " \n" + " \tpr_debug(\"%s()\\n\", __func__);\n" + " \n" + "-\tfor (; i; --i, ++r) {\n" + "-\t\tstruct cma *cma;\n" + "-\t\tcma = cma_create_area(PFN_DOWN(r->start),\n" + "-\t\t\t\t r->size >> PAGE_SHIFT);\n" + "-\t\tif (!IS_ERR(cma))\n" + "-\t\t\tdev_set_cma_area(r->dev, cma);\n" + "-\t}\n" + "+\tfor_each_memblock(memory, reg)\n" + "+\t\tif (reg->tag == MEMBLOCK_TAG_CMA) {\n" + "+\t\t\tcma = cma_create_area(PFN_DOWN(reg->base),\n" + "+\t\t\t\t\t reg->size >> PAGE_SHIFT);\n" + "+\t\t\tif (!IS_ERR(cma))\n" + "+\t\t\t\tdev_set_cma_area(reg->data, cma);\n" + "+\t\t}\n" + "+\tmemblock_free_all_with_tag(MEMBLOCK_TAG_CMA);\n" + "+\n" + " \treturn 0;\n" + " }\n" + " core_initcall(cma_init_reserved_areas);\n" + "@@ -230,7 +227,6 @@ core_initcall(cma_init_reserved_areas);\n" + " int __init dma_declare_contiguous(struct device *dev, unsigned long size,\n" + " \t\t\t\t phys_addr_t base, phys_addr_t limit)\n" + " {\n" + "-\tstruct cma_reserved *r = &cma_reserved[cma_reserved_count];\n" + " \tunsigned long alignment;\n" + " \n" + " \tpr_debug(\"%s(size %lx, base %08lx, limit %08lx)\\n\", __func__,\n" + "@@ -238,7 +234,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size,\n" + " \t\t (unsigned long)limit);\n" + " \n" + " \t/* Sanity checks */\n" + "-\tif (cma_reserved_count == ARRAY_SIZE(cma_reserved)) {\n" + "+\tif (cma_reserved_count == MAX_CMA_AREAS) {\n" + " \t\tpr_err(\"Not enough slots for CMA reserved regions!\\n\");\n" + " \t\treturn -ENOSPC;\n" + " \t}\n" + "@@ -277,13 +273,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size,\n" + " \t\t}\n" + " \t}\n" + " \n" + "-\t/*\n" + "-\t * Each reserved area must be initialised later, when more kernel\n" + "-\t * subsystems (like slab allocator) are available.\n" + "-\t */\n" + "-\tr->start = base;\n" + "-\tr->size = size;\n" + "-\tr->dev = dev;\n" + "+\tBUG_ON(memblock_mark_tag(base, size, MEMBLOCK_TAG_CMA, dev));\n" + " \tcma_reserved_count++;\n" + " \tpr_info(\"CMA: reserved %ld MiB at %08lx\\n\", size / SZ_1M,\n" + " \t\t(unsigned long)base);\n" + "diff --git a/include/linux/memblock.h b/include/linux/memblock.h\n" + "index 5420ed9..a662c07 100644\n" + "--- a/include/linux/memblock.h\n" + "+++ b/include/linux/memblock.h\n" + "@@ -125,6 +125,7 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start,\n" + " #ifdef CONFIG_HAVE_MEMBLOCK_TAG\n" + " #define\tMEMBLOCK_TAG_DEFAULT\t0x0 /* default tag for bootmem allocatror */\n" + " #define\tMEMBLOCK_TAG_HOTPLUG\t0x1 /* reserved for memory hotplug */\n" + "+#define\tMEMBLOCK_TAG_CMA\t0x2 /* reserved for CMA */\n" + " \n" + " int memblock_mark_tag(phys_addr_t base, phys_addr_t size, int tag, void *data);\n" + " void memblock_free_all_with_tag(int tag);\n" + "-- \n" + 1.7.9.5 -97963415fdbe490fcf9ed20892fd85133e2548043ff48af929475c300832df65 +099d809225fa7c39802a2a24d30e21e9687980ac0aa8efbd41350af47d9fb3b8
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.