memblock: Kill early_node_map[], take 2
Subsystems (18)
PATCH 1/1 memblock: Kill early_node_map[], take 2
Hello,
This patchset was posted quite a while ago but got lost during the korg disturbance and I forgot about it too. Thankfully, benh pinged me about testing this patchset yesterday, so here's the refreshed version.
Changes from the last take[L] are,
* Rebased on top of updated x86/memblock.
* Acked-by's added & updated patches folded into the series.
* 0001-memblock-Make-memblock_overlaps_region-static.patch:
dropped as commit to make the same change is already upstream. (2d7d3eb2ba "mm/memblock.c: quiet sparse noise")
* 0001-memblock-Fix-include-breakages-caused-by-24aa07882b.patch:
rolled into the series. Also updated to handle openrisc.
* 0002-memblock-Make-memblock_-add-remove-free-reserve-retu.patch:
trivial update to handle addition of memblock_end_of_DRAM
* 0005-memblock-Kill-sentinel-entries-at-the-end-of-static-.patch:
updated to reflect POISON change by c9d8c3d089 "mm/memblock.c: avoid abuse of RED_INACTIVE"
* 0006-memblock-Kill-memblock_init.patch:
updated to include openrisc
* 0013-memblock-s-memblock_analyze-memblock_allow_resize-an.patch:
updated to include openrisc
This patchset builds on the previous "memblock, x86: Allow node info in memblock and remove x86 specific memblock code" patchset[1], which now is in tip:x86/memblock. This patchset updates memblock so that it's easier to use, converts all archs which use early_node_map[] to use memblock instead, and kills early_node_map[].
Bootmem allocator is still looming there but this ensures a unified way forward where memblock is the universal early memory management mechanism. This cleans up the entanglement between memblock and early_node_map[] in the backend but API visible to archs is still a bit confusing and can use some cleanup and documentation once things settle down a bit.
x86, powerpc and sparc are boot tested in several different configurations. On x86 allmod/noconfigs are compile tested. On all other archs except for score, defconfig + some variations are compile tested.
This does touch a lot of archs but except for x86 and powerpc the changes are mostly trivial and as bulk of the changes involve updates to generic memblock code, it would be great if these can be routed through single tree (tip:x86/memblock).
0001-memblock-Fix-include-breakages-caused-by-24aa07882b.patch 0002-memblock-Make-memblock_-add-remove-free-reserve-retu.patch 0003-memblock-Use-memblock_reserve-in-memblock-internal-f.patch 0004-memblock-Add-__memblock_dump_all.patch 0005-memblock-Kill-sentinel-entries-at-the-end-of-static-.patch 0006-memblock-Kill-memblock_init.patch 0007-memblock-Separate-out-memblock_isolate_range-from-me.patch 0008-memblock-Reimplement-__memblock_remove-using-membloc.patch 0009-memblock-Make-memblock-functions-handle-overflowing-.patch 0010-memblock-Reimplement-memblock_enforce_memory_limit-u.patch 0011-powerpc-Cleanup-memblock-usage.patch 0012-memblock-Track-total-size-of-regions-automatically.patch 0013-memblock-s-memblock_analyze-memblock_allow_resize-an.patch 0014-memblock-Implement-memblock_add_node.patch 0015-powerpc-Use-HAVE_MEMBLOCK_NODE_MAP.patch 0016-sparc-Use-HAVE_MEMBLOCK_NODE_MAP.patch 0017-SuperH-Use-HAVE_MEMBLOCK_NODE_MAP.patch 0018-ia64-Use-HAVE_MEMBLOCK_NODE_MAP.patch 0019-mips-Use-HAVE_MEMBLOCK_NODE_MAP.patch 0020-s390-Use-HAVE_MEMBLOCK_NODE_MAP.patch 0021-score-Use-HAVE_MEMBLOCK_NODE_MAP.patch 0022-memblock-Kill-early_node_map.patch 0023-memblock-Reimplement-memblock-allocation-using-rever.patch
0001-0014 clean up and improve generic memblock code (powerpc update is to allow updates to generic code) so that it's easier for archs. e.g. memblock_init/analyze() are no longer necessary.
0015-0017 convert archs which were using memblock + early_node_map[] to use MEMBLOCK_HAVE_NODE_MAP.
0018-0021 convert archs which were using only early_node_map[] to MEMBLOCK_HAVE_NODE_MAP.
0022 kills now unused early_node_map[].
0023 reimplements memblock allocator in sane way, which is possible with early_node_map[] gone.
This patchset is available in the following git branch.
git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git memblock-kill-early_node_map
And diffstat follows.
arch/arm/kernel/setup.c | 1 arch/arm/mm/init.c | 4 arch/ia64/Kconfig | 6 arch/ia64/mm/contig.c | 3 arch/ia64/mm/init.c | 4 arch/microblaze/include/asm/memblock.h | 14 arch/microblaze/kernel/prom.c | 3 arch/mips/Kconfig | 6 arch/mips/kernel/setup.c | 3 arch/mips/sgi-ip27/ip27-memory.c | 5 arch/openrisc/include/asm/memblock.h | 24 - arch/openrisc/kernel/prom.c | 3 arch/powerpc/Kconfig | 4 arch/powerpc/include/asm/memblock.h | 8 arch/powerpc/kernel/machine_kexec.c | 3 arch/powerpc/kernel/prom.c | 20 - arch/powerpc/mm/init_32.c | 4 arch/powerpc/mm/mem.c | 2 arch/powerpc/mm/numa.c | 10 arch/powerpc/mm/tlb_nohash.c | 1 arch/powerpc/platforms/embedded6xx/wii.c | 23 - arch/powerpc/platforms/ps3/mm.c | 1 arch/s390/Kconfig | 6 arch/s390/kernel/setup.c | 4 arch/score/Kconfig | 12 arch/score/kernel/setup.c | 4 arch/sh/Kconfig | 1 arch/sh/include/asm/memblock.h | 4 arch/sh/kernel/machine_kexec.c | 3 arch/sh/kernel/setup.c | 3 arch/sh/mm/Kconfig | 3 arch/sh/mm/init.c | 3 arch/sparc/Kconfig | 4 arch/sparc/include/asm/memblock.h | 8 arch/sparc/mm/init_64.c | 28 - arch/unicore32/kernel/setup.c | 1 arch/unicore32/mm/init.c | 4 arch/unicore32/mm/mmu.c | 1 arch/x86/Kconfig | 3 arch/x86/kernel/e820.c | 3 arch/x86/kernel/head32.c | 2 arch/x86/kernel/head64.c | 2 arch/x86/xen/enlighten.c | 2 drivers/iommu/intel-iommu.c | 1 include/linux/memblock.h | 116 +++-- include/linux/mm.h | 50 -- include/linux/mmzone.h | 8 include/linux/poison.h | 6 mm/memblock.c | 603 ++++++++++++++----------------- mm/page_alloc.c | 259 ------------- 50 files changed, 455 insertions(+), 841 deletions(-)
--
tejun
[L] http://thread.gmane.org/gmane.linux.kernel.cross-arch/10464
[1] https://lkml.org/lkml/2011/7/12/95
PATCH 1/23 memblock: Fix include breakages caused by 24aa07882b
24aa07882b (memblock, x86: Replace memblock_x86_reserve/free_range() with generic ones) removed arch/x86/include/asm/memblock.h and dropped its inclusion from include/linux/memblock.h which breaks other architectures which depended on the generic memblock.h pulling in the arch specific one.
However, the proper fix isn't adding back the asm inclusion. memblock doesn't have any arch dependent part and doesn't need arch specific header file and asm/memblock.h files are either practically empty or contain mostly unrelated arch specific stuff.
* In microblaze, sh, powerpc, sparc and openrisc, asm/memblock.h is either empty or just contains unused MEMBLOCK_DBG() macro. Remove them.
* In arm and unicore32, asm/memblock.h contains arch specific stuff. Include it directly from its users. It might be a good idea to rename the header file to avoid confusion.
--- arch/arm/kernel/setup.c | 1 + arch/arm/mm/init.c | 1 + arch/microblaze/include/asm/memblock.h | 14 -------------- arch/openrisc/include/asm/memblock.h | 24 ------------------------ arch/powerpc/include/asm/memblock.h | 8 -------- arch/sh/include/asm/memblock.h | 4 ---- arch/sparc/include/asm/memblock.h | 8 -------- arch/unicore32/kernel/setup.c | 1 + arch/unicore32/mm/init.c | 1 + arch/unicore32/mm/mmu.c | 1 + 10 files changed, 5 insertions(+), 58 deletions(-) delete mode 100644 arch/microblaze/include/asm/memblock.h delete mode 100644 arch/openrisc/include/asm/memblock.h delete mode 100644 arch/powerpc/include/asm/memblock.h delete mode 100644 arch/sh/include/asm/memblock.h delete mode 100644 arch/sparc/include/asm/memblock.h
arch/arm/kernel/setup.c +1 -0
@@ -52,6 +52,7 @@#include <asm/mach/time.h> #include <asm/traps.h> #include <asm/unwind.h> +#include <asm/memblock.h> #if defined(CONFIG_DEPRECATED_PARAM_STRUCT )#include "compat.h"
arch/arm/mm/init.c +1 -0
@@ -32,6 +32,7 @@#include <asm/mach/arch.h> #include <asm/mach/map.h> +#include <asm/memblock.h> #include "mm.h"
arch/microblaze/include/asm/memblock.h deleted +0 -14
@@ -1,14 +0,0 @@ -/* -* Copyright (C) 2008 Michal Simek <[email protected]> -* -* This file is subject to the terms and conditions of the GNU General Public -* License. See the file "COPYING" in the main directory of this archive -* for more details. -*/ - -#ifndef _ASM_MICROBLAZE_MEMBLOCK_H -#define _ASM_MICROBLAZE_MEMBLOCK_H - -#endif /* _ASM_MICROBLAZE_MEMBLOCK_H */ - -
arch/openrisc/include/asm/memblock.h deleted +0 -24
@@ -1,24 +0,0 @@ -/* -* OpenRISC Linux -* -* Linux architectural port borrowing liberally from similar works of -* others. All original copyrights apply as per the original source -* declaration. -* -* OpenRISC implementation: -* Copyright (C) 2003 Matjaz Breskvar <[email protected]> -* Copyright (C) 2010-2011 Jonas Bonn <[email protected]> -* et al. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -*/ - -#ifndef __ASM_OPENRISC_MEMBLOCK_H -#define __ASM_OPENRISC_MEMBLOCK_H - -/* empty */ - -#endif /* __ASM_OPENRISC_MEMBLOCK_H */
arch/powerpc/include/asm/memblock.h deleted +0 -8
@@ -1,8 +0,0 @@ -#ifndef _ASM_POWERPC_MEMBLOCK_H -#define _ASM_POWERPC_MEMBLOCK_H - -#include <asm/udbg.h> - -#define MEMBLOCK_DBG(fmt...) udbg_printf(fmt) - -#endif /* _ASM_POWERPC_MEMBLOCK_H */
arch/sh/include/asm/memblock.h deleted +0 -4
@@ -1,4 +0,0 @@ -#ifndef __ASM_SH_MEMBLOCK_H -#define __ASM_SH_MEMBLOCK_H - -#endif /* __ASM_SH_MEMBLOCK_H */
arch/sparc/include/asm/memblock.h deleted +0 -8
@@ -1,8 +0,0 @@ -#ifndef _SPARC64_MEMBLOCK_H -#define _SPARC64_MEMBLOCK_H - -#include <asm/oplib.h> - -#define MEMBLOCK_DBG(fmt...) prom_printf(fmt) - -#endif /* !(_SPARC64_MEMBLOCK_H) */
arch/unicore32/kernel/setup.c +1 -0
@@ -37,6 +37,7 @@#include <asm/cacheflush.h> #include <asm/tlbflush.h> #include <asm/traps.h> +#include <asm/memblock.h> #include "setup.h"
arch/unicore32/mm/init.c +1 -0
@@ -26,6 +26,7 @@#include <asm/setup.h> #include <asm/sizes.h> #include <asm/tlb.h> +#include <asm/memblock.h> #include <mach/map.h> #include "mm.h"
arch/unicore32/mm/mmu.c +1 -0
@@ -25,6 +25,7 @@#include <asm/setup.h> #include <asm/sizes.h> #include <asm/tlb.h> +#include <asm/memblock.h> #include <mach/map.h>
Signature · 1 line
1.7.3.1
PATCH 2/23 memblock: Make memblock_{add|remove|free|reserve}() return int and update prototypes
In reply to Tejun Heomemblock_{add|remove|free|reserve}() return either 0 or -errno but had long as return type. Chage it to int. Also, drop 'extern' from all prototypes in memblock.h - they are unnecessary and used inconsistently (especially if mm.h is included in the picture).
--- include/linux/memblock.h | 64 +++++++++++++++++++++------------------------- mm/memblock.c | 18 ++++++------ 2 files changed, 38 insertions(+), 44 deletions(-)
include/linux/memblock.h +29 -35
@@ -52,15 +52,15 @@ phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end,int memblock_free_reserved_regions (void );int memblock_reserve_reserved_regions (void ); -extern void memblock_init (void ); -extern void memblock_analyze (void ); -extern long memblock_add (phys_addr_t base,phys_addr_t size); -extern long memblock_remove (phys_addr_t base,phys_addr_t size); -extern long memblock_free (phys_addr_t base,phys_addr_t size); -extern long memblock_reserve (phys_addr_t base,phys_addr_t size); +void memblock_init (void ); +void memblock_analyze (void ); +int memblock_add (phys_addr_t base,phys_addr_t size); +int memblock_remove (phys_addr_t base,phys_addr_t size); +int memblock_free (phys_addr_t base,phys_addr_t size); +int memblock_reserve (phys_addr_t base,phys_addr_t size); -extern void __next_free_mem_range (u64 *idx,int nid,phys_addr_t *out_start, -phys_addr_t *out_end,int *out_nid); +void __next_free_mem_range (u64 *idx,int nid,phys_addr_t *out_start, +phys_addr_t *out_end,int *out_nid);/** * for_each_free_mem_range - iterate through free memblock areas
@@ -80,7 +80,7 @@ extern void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, __next_free_mem_range(&i, nid, p_start, p_end, p_nid))#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP -extern int memblock_set_node (phys_addr_t base,phys_addr_t size,int nid); +int memblock_set_node (phys_addr_t base,phys_addr_t size,int nid);static inline void memblock_set_region_node (struct memblock_region *r,int nid) {
@@ -105,37 +105,31 @@ static inline int memblock_get_region_node(const struct memblock_region *r)/* The numa aware allocator is only available if * CONFIG_ARCH_POPULATES_NODE_MAP is set */ -extern phys_addr_t memblock_find_in_range_node (phys_addr_t start, -phys_addr_t end, -phys_addr_t size, -phys_addr_t align,int nid); -extern phys_addr_t memblock_alloc_nid (phys_addr_t size,phys_addr_t align, -int nid); -extern phys_addr_t memblock_alloc_try_nid (phys_addr_t size,phys_addr_t align, -int nid); +phys_addr_t memblock_find_in_range_node (phys_addr_t start,phys_addr_t end, +phys_addr_t size,phys_addr_t align,int nid); +phys_addr_t memblock_alloc_nid (phys_addr_t size,phys_addr_t align,int nid); +phys_addr_t memblock_alloc_try_nid (phys_addr_t size,phys_addr_t align,int nid); -extern phys_addr_t memblock_alloc (phys_addr_t size,phys_addr_t align); +phys_addr_t memblock_alloc (phys_addr_t size,phys_addr_t align);/* Flags for memblock_alloc_base() amd __memblock_alloc_base() */ #define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)#define MEMBLOCK_ALLOC_ACCESSIBLE 0 -extern phys_addr_t memblock_alloc_base (phys_addr_t size, -phys_addr_t align, -phys_addr_t max_addr); -extern phys_addr_t __memblock_alloc_base (phys_addr_t size, -phys_addr_t align, -phys_addr_t max_addr); -extern phys_addr_t memblock_phys_mem_size (void ); -extern phys_addr_t memblock_start_of_DRAM (void ); -extern phys_addr_t memblock_end_of_DRAM (void ); -extern void memblock_enforce_memory_limit (phys_addr_t memory_limit); -extern int memblock_is_memory (phys_addr_t addr); -extern int memblock_is_region_memory (phys_addr_t base,phys_addr_t size); -extern int memblock_is_reserved (phys_addr_t addr); -extern int memblock_is_region_reserved (phys_addr_t base,phys_addr_t size); - -extern void memblock_dump_all (void ); +phys_addr_t memblock_alloc_base (phys_addr_t size,phys_addr_t align, +phys_addr_t max_addr); +phys_addr_t __memblock_alloc_base (phys_addr_t size,phys_addr_t align, +phys_addr_t max_addr); +phys_addr_t memblock_phys_mem_size (void ); +phys_addr_t memblock_start_of_DRAM (void ); +phys_addr_t memblock_end_of_DRAM (void ); +void memblock_enforce_memory_limit (phys_addr_t memory_limit); +int memblock_is_memory (phys_addr_t addr); +int memblock_is_region_memory (phys_addr_t base,phys_addr_t size); +int memblock_is_reserved (phys_addr_t addr); +int memblock_is_region_reserved (phys_addr_t base,phys_addr_t size); + +void memblock_dump_all (void );/** * memblock_set_current_limit - Set the current allocation limit to allow
@@ -143,7 +137,7 @@ extern void memblock_dump_all(void);* accessible during boot * @limit: New limit value (physical address) */ -extern void memblock_set_current_limit (phys_addr_t limit); +void memblock_set_current_limit (phys_addr_t limit);/*
mm/memblock.c +9 -9
@@ -176,7 +176,7 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u }/* Defined below but needed now */ -static long memblock_add_region (struct memblock_type *type,phys_addr_t base,phys_addr_t size); +static int memblock_add_region (struct memblock_type *type,phys_addr_t base,phys_addr_t size); static int __init_memblock memblock_double_array(struct memblock_type *type) {
@@ -316,8 +316,8 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type,* RETURNS: * 0 on success, -errno on failure. */ -static long __init_memblock memblock_add_region (struct memblock_type *type, -phys_addr_t base,phys_addr_t size) +static int __init_memblock memblock_add_region(struct memblock_type *type, +phys_addr_t base,phys_addr_t size) {bool insert = false;phys_addr_t obase = base, end = base + size;
@@ -387,13 +387,13 @@ repeat: } } -long __init_memblock memblock_add (phys_addr_t base,phys_addr_t size) +int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size) {return memblock_add_region (&memblock.memory, base, size); } -static long __init_memblock __memblock_remove (struct memblock_type *type, -phys_addr_t base,phys_addr_t size) +static int __init_memblock __memblock_remove(struct memblock_type *type, +phys_addr_t base,phys_addr_t size) {phys_addr_t end = base + size;int i;
@@ -443,12 +443,12 @@ static long __init_memblock __memblock_remove(struct memblock_type *type,return 0 ; } -long __init_memblock memblock_remove (phys_addr_t base,phys_addr_t size) +int __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size) {return __memblock_remove (&memblock.memory, base, size); } -long __init_memblock memblock_free (phys_addr_t base,phys_addr_t size) +int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size) { memblock_dbg(" memblock_free: [%#016llx-%#016llx] %pF\n", (unsigned long long)base,
@@ -458,7 +458,7 @@ long __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)return __memblock_remove (&memblock.reserved, base, size); } -long __init_memblock memblock_reserve (phys_addr_t base,phys_addr_t size) +int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) {struct memblock_type *_rgn = &memblock.reserved;
Signature · 1 line
1.7.3.1
PATCH 3/23 memblock: Use memblock_reserve() in memblock internal functions
In reply to Tejun HeoMake memblock_double_array(), __memblock_alloc_base() and memblock_alloc_nid() use memblock_reserve() instead of calling memblock_add_region() with reserved array directly. This eases debugging and updates to memblock_add_region().
--- mm/memblock.c | 9 +++------ 1 files changed, 3 insertions(+), 6 deletions(-)
mm/memblock.c +3 -6
@@ -175,9 +175,6 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u } } -/* Defined below but needed now */ -static int memblock_add_region (struct memblock_type *type,phys_addr_t base,phys_addr_t size); - static int __init_memblock memblock_double_array(struct memblock_type *type) {struct memblock_region *new_array, *old_array;
@@ -235,7 +232,7 @@ static int __init_memblock memblock_double_array(struct memblock_type *type)return 0 ;/* Add the new reserved region now. Should not fail ! */ -BUG_ON (memblock_add_region (&memblock.reserved, addr, new_size)); +BUG_ON (memblock_reserve (addr, new_size));/* If the array wasn't our static init one, then free it. We only do * that before SLAB is available as later on, we don't know whether
@@ -652,7 +649,7 @@ phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, ph size =round_up (size, align); found =memblock_find_in_range (0 , max_addr, size, align); -if (found && !memblock_add_region (&memblock.reserved, found, size)) +if (found && !memblock_reserve (found, size))return found;return 0 ;
@@ -748,7 +745,7 @@ phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int n found =memblock_find_in_range_node (0 ,MEMBLOCK_ALLOC_ACCESSIBLE , size, align, nid); -if (found && !memblock_add_region (&memblock.reserved, found, size)) +if (found && !memblock_reserve (found, size))return found;return 0 ;
Signature · 1 line
1.7.3.1
PATCH 4/23 memblock: Add __memblock_dump_all()
In reply to Tejun HeoAdd __memblock_dump_all() which dumps memblock configuration whether memblock_debug is enabled or not.
--- include/linux/memblock.h | 8 +++++++- mm/memblock.c | 5 +---- 2 files changed, 8 insertions(+), 5 deletions(-)
include/linux/memblock.h +7 -1
@@ -129,7 +129,13 @@ int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);int memblock_is_reserved (phys_addr_t addr);int memblock_is_region_reserved (phys_addr_t base,phys_addr_t size); -void memblock_dump_all (void ); +extern void __memblock_dump_all (void ); + +static inline void memblock_dump_all (void ) +{ +if (memblock_debug) +__memblock_dump_all (); +}/** * memblock_set_current_limit - Set the current allocation limit to allow
mm/memblock.c +1 -4
@@ -898,11 +898,8 @@ static void __init_memblock memblock_dump(struct memblock_type *type, char *name } } -void __init_memblock memblock_dump_all(void) +void __init_memblock __memblock_dump_all(void) { -if (!memblock_debug) -return ; -pr_info ("MEMBLOCK configuration:\n" );pr_info (" memory size = 0x%llx\n" , (unsigned long long )memblock.memory_size);
Signature · 1 line
1.7.3.1
PATCH 5/23 memblock: Kill sentinel entries at the end of static region arrays
In reply to Tejun Heomemblock no longer depends on having one more entry at the end during addition making the sentinel entries at the end of region arrays not too useful. Remove the sentinels. This eases further updates.
--- include/linux/poison.h | 6 ------ mm/memblock.c | 14 ++------------ 2 files changed, 2 insertions(+), 18 deletions(-)
include/linux/poison.h +0 -6
@@ -40,12 +40,6 @@#define RED_INACTIVE 0x09F911029D74E35BULL/* when obj is inactive */ #define RED_ACTIVE 0xD84156C5635688C0ULL/* when obj is active */ -#ifdef CONFIG_PHYS_ADDR_T_64BIT -#define MEMBLOCK_INACTIVE 0x3a84fb0144c9e71bULL -#else -#define MEMBLOCK_INACTIVE 0x44c9e71bUL -#endif -#define SLUB_RED_INACTIVE 0xbb#define SLUB_RED_ACTIVE 0xcc
mm/memblock.c +2 -12
@@ -24,8 +24,8 @@ struct memblock memblock __initdata_memblock; int memblock_debug __initdata_memblock; int memblock_can_resize __initdata_memblock; -static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS + 1] __initdata_memblock; -static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS + 1] __initdata_memblock; +static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock; +static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;/* inline so we don't get a warning when pr_debug is compiled out */ static inline const char *memblock_type_name (struct memblock_type *type)
@@ -911,12 +911,6 @@ void __init memblock_analyze(void) {int i; -/* Check marker in the unused last array entry */ -WARN_ON (memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS ].base - !=MEMBLOCK_INACTIVE ); -WARN_ON (memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS ].base - !=MEMBLOCK_INACTIVE ); - memblock.memory_size =0 ;for (i =0 ; i < memblock.memory.cnt; i++)
@@ -940,10 +934,6 @@ void __init memblock_init(void) memblock.reserved.regions = memblock_reserved_init_regions; memblock.reserved.max =INIT_MEMBLOCK_REGIONS ; -/* Write a marker in the unused last array entry */ - memblock.memory.regions[INIT_MEMBLOCK_REGIONS ].base =MEMBLOCK_INACTIVE ; - memblock.reserved.regions[INIT_MEMBLOCK_REGIONS ].base =MEMBLOCK_INACTIVE ; -/* Create a dummy zero size MEMBLOCK which will get coalesced away later. * This simplifies the memblock_add() code below... */
Signature · 1 line
1.7.3.1
PATCH 6/23 memblock: Kill memblock_init()
In reply to Tejun Heomemblock_init() initializes arrays for regions and memblock itself; however, all these can be done with struct initializers and memblock_init() can be removed. This patch kills memblock_init() and initializes memblock with struct initializer.
The only difference is that the first dummy entries don't have .nid set to MAX_NUMNODES initially. This doesn't cause any behavior difference.
--- arch/arm/mm/init.c | 1 - arch/microblaze/kernel/prom.c | 1 - arch/openrisc/kernel/prom.c | 1 - arch/powerpc/kernel/prom.c | 2 - arch/sh/mm/init.c | 1 - arch/sparc/mm/init_64.c | 2 - arch/unicore32/mm/init.c | 1 - arch/x86/kernel/head32.c | 2 - arch/x86/kernel/head64.c | 2 - arch/x86/xen/enlighten.c | 2 - include/linux/memblock.h | 1 - mm/memblock.c | 48 ++++++++++++----------------------------- 12 files changed, 14 insertions(+), 50 deletions(-)
arch/arm/mm/init.c +0 -1
@@ -333,7 +333,6 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)sort (&meminfo.bank, meminfo.nr_banks,sizeof (meminfo.bank[0 ]), meminfo_cmp,NULL ); -memblock_init ();for (i =0 ; i < mi->nr_banks; i++)memblock_add (mi->bank[i].start, mi->bank[i].size);
arch/microblaze/kernel/prom.c +0 -1
@@ -122,7 +122,6 @@ void __init early_init_devtree(void *params)of_scan_flat_dt (early_init_dt_scan_chosen, cmd_line);/* Scan memory nodes and rebuild MEMBLOCKs */ -memblock_init ();of_scan_flat_dt (early_init_dt_scan_root,NULL );of_scan_flat_dt (early_init_dt_scan_memory,NULL );
arch/openrisc/kernel/prom.c +0 -1
@@ -76,7 +76,6 @@ void __init early_init_devtree(void *params)of_scan_flat_dt (early_init_dt_scan_chosen, cmd_line);/* Scan memory nodes and rebuild MEMBLOCKs */ -memblock_init ();of_scan_flat_dt (early_init_dt_scan_root,NULL );of_scan_flat_dt (early_init_dt_scan_memory,NULL );
arch/powerpc/kernel/prom.c +0 -2
@@ -733,8 +733,6 @@ void __init early_init_devtree(void *params)of_scan_flat_dt (early_init_dt_scan_chosen_ppc, cmd_line);/* Scan memory nodes and rebuild MEMBLOCKs */ -memblock_init (); -of_scan_flat_dt (early_init_dt_scan_root,NULL );of_scan_flat_dt (early_init_dt_scan_memory_ppc,NULL );
arch/sh/mm/init.c +0 -1
@@ -324,7 +324,6 @@ void __init paging_init(void)unsigned long vaddr, end;int nid; -memblock_init (); sh_mv.mv_mem_init ();early_reserve_mem ();
arch/sparc/mm/init_64.c +0 -2
@@ -1769,8 +1769,6 @@ void __init paging_init(void)sun4v_ktsb_init (); } -memblock_init (); -/* Find available physical memory... * * Read it twice in order to work around a bug in openfirmware.
arch/unicore32/mm/init.c +0 -1
@@ -246,7 +246,6 @@ void __init uc32_memblock_init(struct meminfo *mi)sort (&meminfo.bank, meminfo.nr_banks,sizeof (meminfo.bank[0 ]), meminfo_cmp,NULL ); -memblock_init ();for (i =0 ; i < mi->nr_banks; i++)memblock_add (mi->bank[i].start, mi->bank[i].size);
arch/x86/kernel/head32.c +0 -2
@@ -31,8 +31,6 @@ static void __init i386_default_early_setup(void)void __init i386_start_kernel (void ) { -memblock_init (); -memblock_reserve (__pa_symbol (&_text),__pa_symbol (&__bss_stop) -__pa_symbol (&_text));
arch/x86/kernel/head64.c +0 -2
@@ -98,8 +98,6 @@ void __init x86_64_start_reservations(char *real_mode_data) {copy_bootdata (__va (real_mode_data)); -memblock_init (); -memblock_reserve (__pa_symbol (&_text),__pa_symbol (&__bss_stop) -__pa_symbol (&_text));
arch/x86/xen/enlighten.c +0 -2
@@ -1215,8 +1215,6 @@ asmlinkage void __init xen_start_kernel(void)local_irq_disable (); early_boot_irqs_disabled = true; -memblock_init (); -xen_raw_console_write ("mapping kernel into physical memory\n" ); pgd =xen_setup_kernel_pagetable (pgd, xen_start_info->nr_pages);xen_ident_map_ISA ();
include/linux/memblock.h +0 -1
@@ -52,7 +52,6 @@ phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end,int memblock_free_reserved_regions (void );int memblock_reserve_reserved_regions (void ); -void memblock_init (void );void memblock_analyze (void );int memblock_add (phys_addr_t base,phys_addr_t size);int memblock_remove (phys_addr_t base,phys_addr_t size);
mm/memblock.c +14 -34
63 lines not on this page · raw message
Signature · 1 line
1.7.3.1
PATCH 7/23 memblock: Separate out memblock_isolate_range() from memblock_set_node()
In reply to Tejun Heomemblock_set_node() operates in three steps - break regions crossing boundaries, set nid and merge back regions. This patch separates the first part into a separate function - memblock_isolate_range(), which breaks regions crossing range boundaries and returns range index range for regions properly contained in the specified memory range.
This doesn't introduce any behavior change and will be used to further unify region handling.
--- mm/memblock.c | 117 ++++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 78 insertions(+), 39 deletions(-)
mm/memblock.c +78 -39
@@ -400,6 +400,77 @@ int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)return memblock_add_region (&memblock.memory, base, size); } +#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP +/** +* memblock_isolate_range - isolate given range into disjoint memblocks +* @type: memblock type to isolate range for +* @base: base of range to isolate +* @size: size of range to isolate +* @start_rgn: out parameter for the start of isolated region +* @end_rgn: out parameter for the end of isolated region +* +* Walk @type and ensure that regions don't cross the boundaries defined by +* [@base,@base+@size). Crossing regions are split at the boundaries, +* which may create at most two more regions. The index of the first +* region inside the range is returned in *@start_rgn and end in *@end_rgn. +* +* RETURNS: +* 0 on success, -errno on failure. +*/ +static int __init_memblock memblock_isolate_range(struct memblock_type *type, +phys_addr_t base,phys_addr_t size, +int *start_rgn,int *end_rgn) +{ +phys_addr_t end = base + size; +int i; + + *start_rgn = *end_rgn =0 ; + +/* we'll create at most two more regions */ +while (type->cnt +2 > type->max) +if (memblock_double_array (type) <0 ) +return -ENOMEM ; + +for (i =0 ; i < type->cnt; i++) { +struct memblock_region *rgn = &type->regions[i]; +phys_addr_t rbase = rgn->base; +phys_addr_t rend = rbase + rgn->size; + +if (rbase >= end) +break ; +if (rend <= base) +continue ; + +if (rbase < base) { +/* +* @rgn intersects from below. Split and continue +* to process the next region - the new top half. +*/ + rgn->base = base; + rgn->size = rend - rgn->base; +memblock_insert_region (type, i, rbase, base - rbase, + rgn->nid); + }else if (rend > end) { +/* +* @rgn intersects from above. Split and redo the +* current region - the new bottom half. +*/ + rgn->base = end; + rgn->size = rend - rgn->base; +memblock_insert_region (type, i--, rbase, end - rbase, + rgn->nid); + }else { +/* @rgn is fully contained, record it */ +if (!*end_rgn) + *start_rgn = i; + *end_rgn = i +1 ; + } + } + +return 0 ; +} +#endif + static int __init_memblock __memblock_remove(struct memblock_type *type,phys_addr_t base,phys_addr_t size) {
@@ -603,47 +674,15 @@ int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size, int nid) {struct memblock_type *type = &memblock.memory; -phys_addr_t end = base + size; -int i; +int start_rgn, end_rgn; +int i, ret; -/* we'll create at most two more regions */ -while (type->cnt +2 > type->max) -if (memblock_double_array (type) <0 ) -return -ENOMEM ; + ret =memblock_isolate_range (type, base, size, &start_rgn, &end_rgn); +if (ret) +return ret; -for (i =0 ; i < type->cnt; i++) { -struct memblock_region *rgn = &type->regions[i]; -phys_addr_t rbase = rgn->base; -phys_addr_t rend = rbase + rgn->size; - -if (rbase >= end) -break ; -if (rend <= base) -continue ; - -if (rbase < base) { -/* -* @rgn intersects from below. Split and continue -* to process the next region - the new top half. -*/ - rgn->base = base; - rgn->size = rend - rgn->base; -memblock_insert_region (type, i, rbase, base - rbase, - rgn->nid); - }else if (rend > end) { -/* -* @rgn intersects from above. Split and redo the -* current region - the new bottom half. -*/ - rgn->base = end; - rgn->size = rend - rgn->base; -memblock_insert_region (type, i--, rbase, end - rbase, - rgn->nid); - }else { -/* @rgn is fully contained, set ->nid */ - rgn->nid = nid; - } - } +for (i = start_rgn; i < end_rgn; i++) + type->regions[i].nid = nid;memblock_merge_regions (type);return 0 ;
Signature · 1 line
1.7.3.1
PATCH 8/23 memblock: Reimplement __memblock_remove() using memblock_isolate_range()
In reply to Tejun Heo__memblock_remove()'s open coded region manipulation can be trivially replaced with memblock_islate_range(). This increases code sharing and eases improving region tracking.
This pulls memblock_isolate_range() out of HAVE_MEMBLOCK_NODE_MAP. Make it use memblock_get_region_node() instead of assuming rgn->nid is available.
-v2: Fixed build failure on !HAVE_MEMBLOCK_NODE_MAP caused by direct
rgn->nid access.
--- mm/memblock.c | 56 +++++++++----------------------------------------------- 1 files changed, 9 insertions(+), 47 deletions(-)
mm/memblock.c +9 -47
@@ -400,7 +400,6 @@ int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)return memblock_add_region (&memblock.memory, base, size); } -#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP /** * memblock_isolate_range - isolate given range into disjoint memblocks * @type: memblock type to isolate range for
@@ -449,7 +448,7 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, rgn->base = base; rgn->size = rend - rgn->base;memblock_insert_region (type, i, rbase, base - rbase, - rgn->nid); +memblock_get_region_node (rgn)); }else if (rend > end) {/* * @rgn intersects from above. Split and redo the
@@ -458,7 +457,7 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, rgn->base = end; rgn->size = rend - rgn->base;memblock_insert_region (type, i--, rbase, end - rbase, - rgn->nid); +memblock_get_region_node (rgn)); }else {/* @rgn is fully contained, record it */ if (!*end_rgn)
@@ -469,56 +468,19 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type,return 0 ; } -#endif static int __init_memblock __memblock_remove(struct memblock_type *type,phys_addr_t base,phys_addr_t size) { -phys_addr_t end = base + size; -int i; - -/* Walk through the array for collisions */ -for (i =0 ; i < type->cnt; i++) { -struct memblock_region *rgn = &type->regions[i]; -phys_addr_t rend = rgn->base + rgn->size; - -/* Nothing more to do, exit */ -if (rgn->base > end || rgn->size ==0 ) -break ; - -/* If we fully enclose the block, drop it */ -if (base <= rgn->base && end >= rend) { -memblock_remove_region (type, i--); -continue ; - } - -/* If we are fully enclosed within a block -* then we need to split it and we are done -*/ -if (base > rgn->base && end < rend) { - rgn->size = base - rgn->base; -if (!memblock_add_region (type, end, rend - end)) -return 0 ; -/* Failure to split is bad, we at least -* restore the block before erroring -*/ - rgn->size = rend - rgn->base; -WARN_ON (1 ); -return -1 ; - } - -/* Check if we need to trim the bottom of a block */ -if (rgn->base < end && rend > end) { - rgn->size -= end - rgn->base; - rgn->base = end; -break ; - } +int start_rgn, end_rgn; +int i, ret; -/* And check if we need to trim the top of a block */ -if (base < rend) - rgn->size -= rend - base; + ret =memblock_isolate_range (type, base, size, &start_rgn, &end_rgn); +if (ret) +return ret; - } +for (i = end_rgn -1 ; i >= start_rgn; i--) +memblock_remove_region (type, i);return 0 ; }
Signature · 1 line
1.7.3.1
PATCH 9/23 memblock: Make memblock functions handle overflowing range @size
In reply to Tejun HeoAllow memblock users to specify range where @base + @size overflows and automatically cap it at maximum. This makes the interface more robust and specifying till-the-end-of-memory easier.
--- mm/memblock.c | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-)
mm/memblock.c +12 -3
@@ -49,6 +49,12 @@ static inline const char *memblock_type_name(struct memblock_type *type)return "unknown" ; } +/* adjust *@size so that (@base + *@size) doesn't overflow, return new size */ +static inline phys_addr_t memblock_cap_size (phys_addr_t base,phys_addr_t *size) +{ +return *size =min (*size, (phys_addr_t )ULLONG_MAX - base); +} +/* * Address comparison utilities */
@@ -328,7 +334,8 @@ static int __init_memblock memblock_add_region(struct memblock_type *type, phys_addr_t base, phys_addr_t size) { bool insert = false; -phys_addr_t obase = base, end = base + size; +phys_addr_t obase = base; +phys_addr_t end = base +memblock_cap_size (base, &size);int i, nr_new;/* special case for empty array */
@@ -420,7 +427,7 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, phys_addr_t base, phys_addr_t size, int *start_rgn, int *end_rgn) { - phys_addr_t end = base + size; + phys_addr_t end = base + memblock_cap_size(base, &size);int i; *start_rgn = *end_rgn =0 ;
@@ -868,16 +875,18 @@ int __init_memblock memblock_is_memory(phys_addr_t addr) int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size) {int idx =memblock_search (&memblock.memory, base); +phys_addr_t end = base +memblock_cap_size (base, &size);if (idx ==-1 )return 0 ;return memblock.memory.regions[idx].base <= base && (memblock.memory.regions[idx].base + - memblock.memory.regions[idx].size) >= (base + size); + memblock.memory.regions[idx].size) >= end; } int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size) { +memblock_cap_size (base, &size);return memblock_overlaps_region (&memblock.reserved, base, size) >=0 ; }
Signature · 1 line
1.7.3.1
PATCH 10/23 memblock: Reimplement memblock_enforce_memory_limit() using __memblock_remove()
In reply to Tejun HeoWith recent updates, the basic memblock operations are robust enough that there's no reason for memblock_enfore_memory_limit() to directly manipulate memblock region arrays. Reimplement it using __memblock_remove().
--- mm/memblock.c | 42 +++++++++++++----------------------------- 1 files changed, 13 insertions(+), 29 deletions(-)
mm/memblock.c +13 -29
@@ -804,44 +804,28 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void) }/* You must call memblock_analyze() after this. */ -void __init memblock_enforce_memory_limit (phys_addr_t memory_limit) +void __init memblock_enforce_memory_limit (phys_addr_t limit) {unsigned long i; -phys_addr_t limit; -struct memblock_region *p; +phys_addr_t max_addr = (phys_addr_t )ULLONG_MAX ; -if (!memory_limit) +if (!limit)return ; -/* Truncate the memblock regions to satisfy the memory limit. */ - limit = memory_limit; +/* find out max address */ for (i =0 ; i < memblock.memory.cnt; i++) { -if (limit > memblock.memory.regions[i].size) { - limit -= memblock.memory.regions[i].size; -continue ; - } - - memblock.memory.regions[i].size = limit; - memblock.memory.cnt = i +1 ; -break ; - } - - memory_limit =memblock_end_of_DRAM (); +struct memblock_region *r = &memblock.memory.regions[i]; -/* And truncate any reserves above the limit also. */ -for (i =0 ; i < memblock.reserved.cnt; i++) { - p = &memblock.reserved.regions[i]; - -if (p->base > memory_limit) - p->size =0 ; -else if ((p->base + p->size) > memory_limit) - p->size = memory_limit - p->base; - -if (p->size ==0 ) { -memblock_remove_region (&memblock.reserved, i); - i--; +if (limit <= r->size) { + max_addr = r->base + limit; +break ; } + limit -= r->size; } + +/* truncate both memory and reserved regions */ +__memblock_remove (&memblock.memory, max_addr, (phys_addr_t )ULLONG_MAX ); +__memblock_remove (&memblock.reserved, max_addr, (phys_addr_t )ULLONG_MAX ); } static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
Signature · 1 line
1.7.3.1
PATCH 11/23 powerpc: Cleanup memblock usage
In reply to Tejun Heo* early_init_devtree(): Total memory size is aligned to PAGE_SIZE; however, alignment isn't enforced if memory_limit is explicitly specified. Simplify the logic and always apply PAGE_SIZE alignment.
* MMU_init(): memblock regions is truncated by directly modifying memblock.memory.cnt. This is incomplete (reserved array is not truncated) and unnecessarily low level hindering further memblock improvments. Use memblock_enforce_memory_limit() instead.
* wii_memory_fixups(): Unnecessarily low level direct manipulation of memblock regions. The same result can be achieved using properly abstracted operations. Reimplement using memblock API.
--- arch/powerpc/kernel/prom.c | 17 ++++++----------- arch/powerpc/mm/init_32.c | 2 +- arch/powerpc/platforms/embedded6xx/wii.c | 22 +++++++++------------- 3 files changed, 16 insertions(+), 25 deletions(-)
arch/powerpc/kernel/prom.c +6 -11
@@ -754,17 +754,12 @@ void __init early_init_devtree(void *params)early_reserve_mem ();phyp_dump_reserve_mem (); - limit = memory_limit; -if (! limit) { -phys_addr_t memsize; - -/* Ensure that total memory size is page-aligned, because -* otherwise mark_bootmem() gets upset. */ -memblock_analyze (); - memsize =memblock_phys_mem_size (); -if ((memsize &PAGE_MASK ) != memsize) - limit = memsize &PAGE_MASK ; - } +/* +* Ensure that total memory size is page-aligned, because otherwise +* mark_bootmem() gets upset. +*/ +memblock_analyze (); + limit =ALIGN (memory_limit ?:memblock_phys_mem_size (),PAGE_SIZE );memblock_enforce_memory_limit (limit);memblock_analyze ();
arch/powerpc/mm/init_32.c +1 -1
@@ -134,7 +134,7 @@ void __init MMU_init(void)if (memblock.memory.cnt >1 ) {#ifndef CONFIG_WII - memblock.memory.cnt =1 ; +memblock_enforce_memory_limit (memblock.memory.regions[0 ].size);memblock_analyze ();printk (KERN_WARNING "Only using first contiguous memory region" );#else
arch/powerpc/platforms/embedded6xx/wii.c +9 -13
@@ -79,23 +79,19 @@ void __init wii_memory_fixups(void)BUG_ON (memblock.memory.cnt !=2 );BUG_ON (!page_aligned (p[0 ].base) || !page_aligned (p[1 ].base)); - p[0 ].size =_ALIGN_DOWN (p[0 ].size,PAGE_SIZE ); - p[1 ].size =_ALIGN_DOWN (p[1 ].size,PAGE_SIZE ); +/* trim unaligned tail */ +memblock_remove (ALIGN (p[1 ].base + p[1 ].size,PAGE_SIZE ), + (phys_addr_t )ULLONG_MAX ); - wii_hole_start = p[0 ].base + p[0 ].size; +/* determine hole, add & reserve them */ + wii_hole_start =ALIGN (p[0 ].base + p[0 ].size,PAGE_SIZE ); wii_hole_size = p[1 ].base - wii_hole_start; - -pr_info ("MEM1: <%08llx %08llx>\n" , p[0 ].base, p[0 ].size); -pr_info ("HOLE: <%08lx %08lx>\n" , wii_hole_start, wii_hole_size); -pr_info ("MEM2: <%08llx %08llx>\n" , p[1 ].base, p[1 ].size); - - p[0 ].size += wii_hole_size + p[1 ].size; - - memblock.memory.cnt =1 ; +memblock_add (wii_hole_start, wii_hole_size); +memblock_reserve (wii_hole_start, wii_hole_size);memblock_analyze (); -/* reserve the hole */ -memblock_reserve (wii_hole_start, wii_hole_size); +BUG_ON (memblock.memory.cnt !=1 ); +__memblock_dump_all ();/* allow ioremapping the address space in the hole */ __allow_ioremap_reserved =1 ;
Signature · 1 line
1.7.3.1
PATCH 12/23 memblock: Track total size of regions automatically
In reply to Tejun HeoTotal size of memory regions was calculated by memblock_analyze() requiring explicitly calling the function between operations which can change memory regions and possible users of total size, which is cumbersome and fragile.
This patch makes each memblock_type track total size automatically with minor modifications to memblock manipulation functions and remove requirements on calling memblock_analyze(). [__]memblock_dump_all() now also dumps the total size of reserved regions.
--- include/linux/memblock.h | 2 +- mm/memblock.c | 27 +++++++++++++-------------- 2 files changed, 14 insertions(+), 15 deletions(-)
include/linux/memblock.h +1 -1
@@ -30,12 +30,12 @@ struct memblock_region {struct memblock_type {unsigned long cnt;/* number of regions */ unsigned long max;/* size of the allocated array */ +phys_addr_t total_size;/* size of all regions */ struct memblock_region *regions; };struct memblock {phys_addr_t current_limit; -phys_addr_t memory_size;/* Updated by memblock_analyze() */ struct memblock_type memory;struct memblock_type reserved; };
mm/memblock.c +13 -14
@@ -179,12 +179,14 @@ int __init_memblock memblock_reserve_reserved_regions(void) static void __init_memblock memblock_remove_region(struct memblock_type *type, unsigned long r) { + type->total_size -= type->regions[r].size;memmove (&type->regions[r], &type->regions[r +1 ], (type->cnt - (r +1 )) *sizeof (type->regions[r])); type->cnt--;/* Special case for empty arrays */ if (type->cnt ==0 ) { +WARN_ON (type->total_size !=0 ); type->cnt =1 ; type->regions[0 ].base =0 ; type->regions[0 ].size =0 ;
@@ -314,6 +316,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type, rgn->size = size;memblock_set_region_node (rgn, nid); type->cnt++; + type->total_size += size; }/**
@@ -340,10 +343,11 @@ static int __init_memblock memblock_add_region(struct memblock_type *type,/* special case for empty array */ if (type->regions[0 ].size ==0 ) { -WARN_ON (type->cnt !=1 ); +WARN_ON (type->cnt !=1 || type->total_size); type->regions[0 ].base = base; type->regions[0 ].size = size;memblock_set_region_node (&type->regions[0 ],MAX_NUMNODES ); + type->total_size = size;return 0 ; } repeat:
@@ -453,7 +457,8 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type,* to process the next region - the new top half. */ rgn->base = base; - rgn->size = rend - rgn->base; + rgn->size -= base - rbase; + type->total_size -= base - rbase;memblock_insert_region (type, i, rbase, base - rbase,memblock_get_region_node (rgn)); }else if (rend > end) {
@@ -462,7 +467,8 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type,* current region - the new bottom half. */ rgn->base = end; - rgn->size = rend - rgn->base; + rgn->size -= end - rbase; + type->total_size -= end - rbase;memblock_insert_region (type, i--, rbase, end - rbase,memblock_get_region_node (rgn)); }else {
@@ -784,10 +790,9 @@ phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, i* Remaining API functions */ -/* You must call memblock_analyze() before this. */ phys_addr_t __init memblock_phys_mem_size (void ) { -return memblock.memory_size; +return memblock.memory.total_size; }/* lowest address */
@@ -803,7 +808,6 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size); } -/* You must call memblock_analyze() after this. */ void __init memblock_enforce_memory_limit (phys_addr_t limit) {unsigned long i;
@@ -906,7 +910,9 @@ static void __init_memblock memblock_dump(struct memblock_type *type, char *name void __init_memblock __memblock_dump_all(void) {pr_info ("MEMBLOCK configuration:\n" ); -pr_info (" memory size = 0x%llx\n" , (unsigned long long )memblock.memory_size); +pr_info (" memory size = %#llx reserved size = %#llx\n" , + (unsigned long long )memblock.memory.total_size, + (unsigned long long )memblock.reserved.total_size);memblock_dump (&memblock.memory,"memory" );memblock_dump (&memblock.reserved,"reserved" );
@@ -914,13 +920,6 @@ void __init_memblock __memblock_dump_all(void)void __init memblock_analyze (void ) { -int i; - - memblock.memory_size =0 ; - -for (i =0 ; i < memblock.memory.cnt; i++) - memblock.memory_size += memblock.memory.regions[i].size; -/* We allow resizing from there */ memblock_can_resize =1 ; }
Signature · 1 line
1.7.3.1
PATCH 13/23 memblock: s/memblock_analyze()/memblock_allow_resize()/ and update users
In reply to Tejun HeoThe only function of memblock_analyze() is now allowing resize of memblock region arrays. Rename it to memblock_allow_resize() and update its users.
* The following users remain the same other than renaming.
arm/mm/init.c::arm_memblock_init()
microblaze/kernel/prom.c::early_init_devtree()
powerpc/kernel/prom.c::early_init_devtree()
openrisc/kernel/prom.c::early_init_devtree()
sh/mm/init.c::paging_init()
sparc/mm/init_64.c::paging_init()
unicore32/mm/init.c::uc32_memblock_init()
* In the following users, analyze was used to update total size which is no longer necessary.
powerpc/kernel/machine_kexec.c::reserve_crashkernel() powerpc/kernel/prom.c::early_init_devtree() powerpc/mm/init_32.c::MMU_init() powerpc/mm/tlb_nohash.c::__early_init_mmu() powerpc/platforms/ps3/mm.c::ps3_mm_add_memory() powerpc/platforms/embedded6xx/wii.c::wii_memory_fixups() sh/kernel/machine_kexec.c::reserve_crashkernel()
* x86/kernel/e820.c::memblock_x86_fill() was directly setting memblock_can_resize before populating memblock and calling analyze afterwards. Call memblock_allow_resize() before start populating.
memblock_can_resize is now static inside memblock.c.
--- arch/arm/mm/init.c | 2 +- arch/microblaze/kernel/prom.c | 2 +- arch/openrisc/kernel/prom.c | 2 +- arch/powerpc/kernel/machine_kexec.c | 3 --- arch/powerpc/kernel/prom.c | 3 +-- arch/powerpc/mm/init_32.c | 2 -- arch/powerpc/mm/tlb_nohash.c | 1 - arch/powerpc/platforms/embedded6xx/wii.c | 1 - arch/powerpc/platforms/ps3/mm.c | 1 - arch/sh/kernel/machine_kexec.c | 3 --- arch/sh/mm/init.c | 2 +- arch/sparc/mm/init_64.c | 2 +- arch/unicore32/mm/init.c | 2 +- arch/x86/kernel/e820.c | 3 +-- include/linux/memblock.h | 3 +-- mm/memblock.c | 5 ++--- 16 files changed, 11 insertions(+), 26 deletions(-)
arch/arm/mm/init.c +1 -1
@@ -371,7 +371,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)if (mdesc->reserve) mdesc->reserve (); -memblock_analyze (); +memblock_allow_resize ();memblock_dump_all (); }
arch/microblaze/kernel/prom.c +1 -1
@@ -129,7 +129,7 @@ void __init early_init_devtree(void *params)strlcpy (boot_command_line, cmd_line,COMMAND_LINE_SIZE );parse_early_param (); -memblock_analyze (); +memblock_allow_resize ();pr_debug ("Phys. mem: %lx\n" , (unsigned long )memblock_phys_mem_size ());
arch/openrisc/kernel/prom.c +1 -1
@@ -82,7 +82,7 @@ void __init early_init_devtree(void *params)/* Save command line for /proc/cmdline and then parse parameters */ strlcpy (boot_command_line, cmd_line,COMMAND_LINE_SIZE ); -memblock_analyze (); +memblock_allow_resize ();/* We must copy the flattend device tree from init memory to regular * memory because the device tree references the strings in it
arch/powerpc/kernel/machine_kexec.c +0 -3
@@ -107,9 +107,6 @@ void __init reserve_crashkernel(void)unsigned long long crash_size, crash_base;int ret; -/* this is necessary because of memblock_phys_mem_size() */ -memblock_analyze (); -/* use common parsing */ ret =parse_crashkernel (boot_command_line,memblock_phys_mem_size (), &crash_size, &crash_base);
arch/powerpc/kernel/prom.c +1 -2
@@ -758,11 +758,10 @@ void __init early_init_devtree(void *params)* Ensure that total memory size is page-aligned, because otherwise * mark_bootmem() gets upset. */ -memblock_analyze (); limit =ALIGN (memory_limit ?:memblock_phys_mem_size (),PAGE_SIZE );memblock_enforce_memory_limit (limit); -memblock_analyze (); +memblock_allow_resize ();memblock_dump_all ();DBG ("Phys. mem: %llx\n" ,memblock_phys_mem_size ());
arch/powerpc/mm/init_32.c +0 -2
@@ -135,7 +135,6 @@ void __init MMU_init(void)if (memblock.memory.cnt >1 ) {#ifndef CONFIG_WII memblock_enforce_memory_limit (memblock.memory.regions[0 ].size); -memblock_analyze ();printk (KERN_WARNING "Only using first contiguous memory region" );#else wii_memory_fixups ();
@@ -158,7 +157,6 @@ void __init MMU_init(void)#ifndef CONFIG_HIGHMEM total_memory = total_lowmem;memblock_enforce_memory_limit (total_lowmem); -memblock_analyze ();#endif /* CONFIG_HIGHMEM */ }
arch/powerpc/mm/tlb_nohash.c +0 -1
@@ -615,7 +615,6 @@ static void __early_init_mmu(int boot_cpu)/* limit memory so we dont have linear faults */ memblock_enforce_memory_limit (linear_map_top); -memblock_analyze ();patch_exception (0x1c0 , exc_data_tlb_miss_bolted_book3e);patch_exception (0x1e0 , exc_instruction_tlb_miss_bolted_book3e);
arch/powerpc/platforms/embedded6xx/wii.c +0 -1
@@ -88,7 +88,6 @@ void __init wii_memory_fixups(void) wii_hole_size = p[1 ].base - wii_hole_start;memblock_add (wii_hole_start, wii_hole_size);memblock_reserve (wii_hole_start, wii_hole_size); -memblock_analyze ();BUG_ON (memblock.memory.cnt !=1 );__memblock_dump_all ();
arch/powerpc/platforms/ps3/mm.c +0 -1
@@ -319,7 +319,6 @@ static int __init ps3_mm_add_memory(void) }memblock_add (start_addr, map.r1.size); -memblock_analyze (); result =online_pages (start_pfn, nr_pages);
arch/sh/kernel/machine_kexec.c +0 -3
@@ -157,9 +157,6 @@ void __init reserve_crashkernel(void)unsigned long long crash_size, crash_base;int ret; -/* this is necessary because of memblock_phys_mem_size() */ -memblock_analyze (); - ret =parse_crashkernel (boot_command_line,memblock_phys_mem_size (), &crash_size, &crash_base);if (ret ==0 && crash_size >0 ) {
arch/sh/mm/init.c +1 -1
@@ -336,7 +336,7 @@ void __init paging_init(void) sh_mv.mv_mem_reserve ();memblock_enforce_memory_limit (memory_limit); -memblock_analyze (); +memblock_allow_resize ();memblock_dump_all ();
arch/sparc/mm/init_64.c +1 -1
@@ -1794,7 +1794,7 @@ void __init paging_init(void)memblock_enforce_memory_limit (cmdline_memory_size); -memblock_analyze (); +memblock_allow_resize ();memblock_dump_all ();set_bit (0 , mmu_context_bmap);
arch/unicore32/mm/init.c +1 -1
@@ -264,7 +264,7 @@ void __init uc32_memblock_init(struct meminfo *mi)uc32_mm_memblock_reserve (); -memblock_analyze (); +memblock_allow_resize ();memblock_dump_all (); }
arch/x86/kernel/e820.c +1 -2
@@ -1072,7 +1072,7 @@ void __init memblock_x86_fill(void)* We are safe to enable resizing, beause memblock_x86_fill() * is rather later for x86 */ - memblock_can_resize =1 ; +memblock_allow_resize ();for (i =0 ; i < e820.nr_map; i++) {struct e820entry *ei = &e820.map[i];
@@ -1087,7 +1087,6 @@ void __init memblock_x86_fill(void)memblock_add (ei->addr, ei->size); } -memblock_analyze ();memblock_dump_all (); }
include/linux/memblock.h +1 -2
@@ -42,7 +42,6 @@ struct memblock {extern struct memblock memblock;extern int memblock_debug; -extern int memblock_can_resize;#define memblock_dbg (fmt, ...) \ if (memblock_debug) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
@@ -52,7 +51,7 @@ phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end,int memblock_free_reserved_regions (void );int memblock_reserve_reserved_regions (void ); -void memblock_analyze (void ); +void memblock_allow_resize (void );int memblock_add (phys_addr_t base,phys_addr_t size);int memblock_remove (phys_addr_t base,phys_addr_t size);int memblock_free (phys_addr_t base,phys_addr_t size);
mm/memblock.c +2 -3
@@ -36,7 +36,7 @@ struct memblock memblock __initdata_memblock = { }; int memblock_debug __initdata_memblock; -int memblock_can_resize __initdata_memblock; +static int memblock_can_resize __initdata_memblock;/* inline so we don't get a warning when pr_debug is compiled out */ static inline const char *memblock_type_name (struct memblock_type *type)
@@ -918,9 +918,8 @@ void __init_memblock __memblock_dump_all(void)memblock_dump (&memblock.reserved,"reserved" ); } -void __init memblock_analyze (void ) +void __init memblock_allow_resize (void ) { -/* We allow resizing from there */ memblock_can_resize =1 ; }
Signature · 1 line
1.7.3.1
PATCH 14/23 memblock: Implement memblock_add_node()
In reply to Tejun HeoImplement memblock_add_node() which can add a new memblock memory region with specific node ID.
--- include/linux/memblock.h | 1 + mm/memblock.c | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-)
include/linux/memblock.h +1 -0
@@ -52,6 +52,7 @@ int memblock_free_reserved_regions(void);int memblock_reserve_reserved_regions (void );void memblock_allow_resize (void ); +int memblock_add_node (phys_addr_t base,phys_addr_t size,int nid);int memblock_add (phys_addr_t base,phys_addr_t size);int memblock_remove (phys_addr_t base,phys_addr_t size);int memblock_free (phys_addr_t base,phys_addr_t size);
mm/memblock.c +13 -7
@@ -324,6 +324,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type,* @type: memblock type to add new region into * @base: base address of the new region * @size: size of the new region +* @nid: nid of the new region * * Add new memblock region [@base,@base+@size) into @type. The new region * is allowed to overlap with existing ones - overlaps don't affect already
@@ -334,7 +335,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type,* 0 on success, -errno on failure. */ static int __init_memblock memblock_add_region(struct memblock_type *type, -phys_addr_t base,phys_addr_t size) +phys_addr_t base,phys_addr_t size,int nid) {bool insert = false;phys_addr_t obase = base;
@@ -346,7 +347,7 @@ static int __init_memblock memblock_add_region(struct memblock_type *type,WARN_ON (type->cnt !=1 || type->total_size); type->regions[0 ].base = base; type->regions[0 ].size = size; -memblock_set_region_node (&type->regions[0 ],MAX_NUMNODES ); +memblock_set_region_node (&type->regions[0 ], nid); type->total_size = size;return 0 ; }
@@ -376,7 +377,7 @@ repeat: nr_new++;if (insert)memblock_insert_region (type, i++, base, - rbase - base,MAX_NUMNODES ); + rbase - base, nid); }/* area below @rend is dealt with, forget about it */ base =min (rend, end);
@@ -386,8 +387,7 @@ repeat:if (base < end) { nr_new++;if (insert) -memblock_insert_region (type, i, base, end - base, -MAX_NUMNODES ); +memblock_insert_region (type, i, base, end - base, nid); }/*
@@ -406,9 +406,15 @@ repeat: } } +int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size, +int nid) +{ +return memblock_add_region (&memblock.memory, base, size, nid); +} + int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size) { -return memblock_add_region (&memblock.memory, base, size); +return memblock_add_region (&memblock.memory, base, size,MAX_NUMNODES ); }/**
@@ -522,7 +528,7 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) (void *)_RET_IP_);BUG_ON (0 == size); -return memblock_add_region (_rgn, base, size); +return memblock_add_region (_rgn, base, size,MAX_NUMNODES ); }/**
Signature · 1 line
1.7.3.1
PATCH 15/23 powerpc: Use HAVE_MEMBLOCK_NODE_MAP
In reply to Tejun Heopowerpc doesn't access early_node_map[] directly and enabling HAVE_MEMBLOCK_NODE_MAP is trivial - replacing add_active_range() calls with memblock_set_node() and selecting HAVE_MEMBLOCK_NODE_MAP is enough.
--- arch/powerpc/Kconfig | 1 + arch/powerpc/mm/mem.c | 2 +- arch/powerpc/mm/numa.c | 10 ++++------ 3 files changed, 6 insertions(+), 7 deletions(-)
arch/powerpc/Kconfig +1 -0
@@ -117,6 +117,7 @@ config PPC select HAVE_KRETPROBES select HAVE_ARCH_TRACEHOOK select HAVE_MEMBLOCK + select HAVE_MEMBLOCK_NODE_MAP select HAVE_DMA_ATTRS select HAVE_DMA_API_DEBUG select USE_GENERIC_SMP_HELPERS if SMP
arch/powerpc/mm/mem.c +1 -1
@@ -199,7 +199,7 @@ void __init do_init_bootmem(void)unsigned long start_pfn, end_pfn; start_pfn =memblock_region_memory_base_pfn (reg); end_pfn =memblock_region_memory_end_pfn (reg); -add_active_range (0 , start_pfn, end_pfn); +memblock_set_node (0 , (phys_addr_t )ULLONG_MAX ,0 ); }/* Add all physical memory to the bootmem map, mark each area
arch/powerpc/mm/numa.c +4 -6
@@ -690,9 +690,7 @@ static void __init parse_drconf_memory(struct device_node *memory)node_set_online (nid); sz =numa_enforce_memory_limit (base, size);if (sz) -add_active_range (nid, base >>PAGE_SHIFT , - (base >>PAGE_SHIFT ) - + (sz >>PAGE_SHIFT )); +memblock_set_node (base, sz, nid); }while (--ranges); } }
@@ -782,8 +780,7 @@ new_range:continue ; } -add_active_range (nid, start >>PAGE_SHIFT , - (start >>PAGE_SHIFT ) + (size >>PAGE_SHIFT )); +memblock_set_node (start, size, nid);if (--ranges) goto new_range;
@@ -819,7 +816,8 @@ static void __init setup_nonnuma(void) end_pfn =memblock_region_memory_end_pfn (reg);fake_numa_create_new_node (end_pfn, &nid); -add_active_range (nid, start_pfn, end_pfn); +memblock_set_node (PFN_PHYS (start_pfn), +PFN_PHYS (end_pfn - start_pfn), nid);node_set_online (nid); } }
Signature · 1 line
1.7.3.1
PATCH 16/23 sparc: Use HAVE_MEMBLOCK_NODE_MAP
In reply to Tejun Heosparc doesn't access early_node_map[] directly and enabling HAVE_MEMBLOCK_NODE_MAP is trivial - replacing add_active_range() calls with memblock_set_node() and selecting HAVE_MEMBLOCK_NODE_MAP is enough.
-v2: Use select in Kconfig instead as suggested by Sam Ravnborg.
--- arch/sparc/Kconfig | 1 + arch/sparc/mm/init_64.c | 24 ++++-------------------- 2 files changed, 5 insertions(+), 20 deletions(-)
arch/sparc/Kconfig +1 -0
@@ -43,6 +43,7 @@ config SPARC64 select HAVE_KPROBES select HAVE_RCU_TABLE_FREE if SMP select HAVE_MEMBLOCK + select HAVE_MEMBLOCK_NODE_MAP select HAVE_SYSCALL_WRAPPERS select HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD
arch/sparc/mm/init_64.c +4 -20
@@ -816,7 +816,7 @@ static u64 memblock_nid_range(u64 start, u64 end, int *nid)#endif /* This must be invoked after performing all of the necessary -* add_active_range() calls for 'nid'. We need to be able to get +* memblock_set_node() calls for 'nid'. We need to be able to get * correct data from get_pfn_range_for_nid(). */ static void __init allocate_node_data (int nid)
@@ -987,14 +987,11 @@ static void __init add_node_ranges(void) this_end =memblock_nid_range (start, end, &nid); -numadbg ("Adding active range nid[%d] " +numadbg ("Setting memblock NUMA node nid[%d] " "start[%lx] end[%lx]\n" , nid, start, this_end); -add_active_range (nid, - start >>PAGE_SHIFT , - this_end >>PAGE_SHIFT ); - +memblock_set_node (start, this_end - start, nid); start = this_end; } }
@@ -1282,7 +1279,6 @@ static void __init bootmem_init_nonnuma(void) {unsigned long top_of_ram =memblock_end_of_DRAM ();unsigned long total_ram =memblock_phys_mem_size (); -struct memblock_region *reg;numadbg ("bootmem_init_nonnuma()\n" );
@@ -1292,20 +1288,8 @@ static void __init bootmem_init_nonnuma(void) (top_of_ram - total_ram) >> 20);init_node_masks_nonnuma (); - -for_each_memblock (memory, reg) { -unsigned long start_pfn, end_pfn; - -if (!reg->size) -continue ; - - start_pfn =memblock_region_memory_base_pfn (reg); - end_pfn =memblock_region_memory_end_pfn (reg); -add_active_range (0 , start_pfn, end_pfn); - } - +memblock_set_node (0 , (phys_addr_t )ULLONG_MAX ,0 );allocate_node_data (0 ); -node_set_online (0 ); }
Signature · 1 line
1.7.3.1
PATCH 17/23 SuperH: Use HAVE_MEMBLOCK_NODE_MAP
In reply to Tejun Heosh doesn't access early_node_map[] directly and enabling HAVE_MEMBLOCK_NODE_MAP is trivial - replacing add_active_range() calls with memblock_set_node() and selecting HAVE_MEMBLOCK_NODE_MAP is enough.
--- arch/sh/Kconfig | 1 + arch/sh/kernel/setup.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletions(-)
arch/sh/Kconfig +1 -0
@@ -4,6 +4,7 @@ config SUPERH select CLKDEV_LOOKUP select HAVE_IDE if HAS_IOPORT select HAVE_MEMBLOCK + select HAVE_MEMBLOCK_NODE_MAP select HAVE_OPROFILE select HAVE_GENERIC_DMA_COHERENT select HAVE_ARCH_TRACEHOOK
arch/sh/kernel/setup.c +2 -1
@@ -230,7 +230,8 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,pmb_bolt_mapping ((unsigned long )__va (start), start, end - start,PAGE_KERNEL ); -add_active_range (nid, start_pfn, end_pfn); +memblock_set_node (PFN_PHYS (start_pfn), +PFN_PHYS (end_pfn - start_pfn), nid); }void __init __weak plat_early_device_setup (void )
Signature · 1 line
1.7.3.1
PATCH 18/23 ia64: Use HAVE_MEMBLOCK_NODE_MAP
In reply to Tejun Heoia64 used early_node_map[] just to prime free_area_init_nodes(). Now memblock can be used for the same purpose and early_node_map[] is scheduled to be dropped. Use memblock instead.
--- arch/ia64/Kconfig | 3 +++ arch/ia64/mm/contig.c | 3 ++- arch/ia64/mm/init.c | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-)
arch/ia64/Kconfig +3 -0
@@ -23,6 +23,9 @@ config IA64 select HAVE_ARCH_TRACEHOOK select HAVE_DMA_API_DEBUG select HAVE_GENERIC_HARDIRQS + select HAVE_MEMBLOCK + select HAVE_MEMBLOCK_NODE_MAP + select ARCH_DISCARD_MEMBLOCK select GENERIC_IRQ_PROBE select GENERIC_PENDING_IRQ if SMP select IRQ_PER_CPU
arch/ia64/mm/contig.c +2 -1
@@ -16,6 +16,7 @@*/ #include <linux/bootmem.h> #include <linux/efi.h> +#include <linux/memblock.h> #include <linux/mm.h> #include <linux/nmi.h> #include <linux/swap.h>
@@ -348,7 +349,7 @@ paging_init (void) printk("Virtual mem_map starts at 0x%p\n", mem_map); }#else /* !CONFIG_VIRTUAL_MEM_MAP */ -add_active_range (0 ,0 , max_low_pfn); +memblock_add_node (0 ,PFN_PHYS (max_low_pfn),0 );free_area_init_nodes (max_zone_pfns);#endif /* !CONFIG_VIRTUAL_MEM_MAP */ zero_page_memmap_ptr =virt_to_page (ia64_imva (empty_zero_page));
arch/ia64/mm/init.c +2 -2
@@ -10,6 +10,7 @@#include <linux/bootmem.h> #include <linux/efi.h> #include <linux/elf.h> +#include <linux/memblock.h> #include <linux/mm.h> #include <linux/mmzone.h> #include <linux/module.h>
@@ -557,8 +558,7 @@ int __init register_active_ranges(u64 start, u64 len, int nid)#endif if (start < end) -add_active_range (nid,__pa (start) >>PAGE_SHIFT , -__pa (end) >>PAGE_SHIFT ); +memblock_add_node (__pa (start), end - start, nid);return 0 ; }
Signature · 1 line
1.7.3.1
PATCH 19/23 mips: Use HAVE_MEMBLOCK_NODE_MAP
In reply to Tejun Heomips used early_node_map[] just to prime free_area_init_nodes(). Now memblock can be used for the same purpose and early_node_map[] is scheduled to be dropped. Use memblock instead.
--- arch/mips/Kconfig | 3 +++ arch/mips/kernel/setup.c | 3 ++- arch/mips/sgi-ip27/ip27-memory.c | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-)
arch/mips/Kconfig +3 -0
@@ -25,6 +25,9 @@ config MIPS select GENERIC_IRQ_SHOW select HAVE_ARCH_JUMP_LABEL select IRQ_FORCED_THREADING + select HAVE_MEMBLOCK + select HAVE_MEMBLOCK_NODE_MAP + select ARCH_DISCARD_MEMBLOCK menu "Machine selection"
arch/mips/kernel/setup.c +2 -1
@@ -14,6 +14,7 @@#include <linux/ioport.h> #include <linux/export.h> #include <linux/screen_info.h> +#include <linux/memblock.h> #include <linux/bootmem.h> #include <linux/initrd.h> #include <linux/root_dev.h>
@@ -352,7 +353,7 @@ static void __init bootmem_init(void)continue ;#endif -add_active_range (0 , start, end); +memblock_add_node (PFN_PHYS (start),PFN_PHYS (end - start),0 ); }/*
arch/mips/sgi-ip27/ip27-memory.c +3 -2
@@ -12,6 +12,7 @@*/ #include <linux/init.h> #include <linux/kernel.h> +#include <linux/memblock.h> #include <linux/mm.h> #include <linux/mmzone.h> #include <linux/module.h>
@@ -381,8 +382,8 @@ static void __init szmem(void)continue ; } num_physpages += slot_psize; -add_active_range (node,slot_getbasepfn (node, slot), -slot_getbasepfn (node, slot) + slot_psize); +memblock_add_node (PFN_PHYS (slot_getbasepfn (node, slot)), +PFN_PHYS (slot_psize), node); } } }
Signature · 1 line
1.7.3.1
Re: [PATCH 19/23] mips: Use HAVE_MEMBLOCK_NODE_MAP
Quoted 3 lines · Tejun Heo
mips used early_node_map[] just to prime
free_area_init_nodes(). Now memblock can be used for the same purpose and early_node_map[] is scheduled to be dropped. Use memblock instead.
Thanks,
Ralf
PATCH 20/23 s390: Use HAVE_MEMBLOCK_NODE_MAP
In reply to Tejun Heos390 used early_node_map[] just to prime free_area_init_nodes(). Now memblock can be used for the same purpose and early_node_map[] is scheduled to be dropped. Use memblock instead.
--- arch/s390/Kconfig | 3 +++ arch/s390/kernel/setup.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletions(-)
arch/s390/Kconfig +3 -0
@@ -92,6 +92,9 @@ config S390 select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 select HAVE_RCU_TABLE_FREE if SMP select ARCH_SAVE_PAGE_KEYS if HIBERNATION + select HAVE_MEMBLOCK + select HAVE_MEMBLOCK_NODE_MAP + select ARCH_DISCARD_MEMBLOCK select ARCH_INLINE_SPIN_TRYLOCK select ARCH_INLINE_SPIN_TRYLOCK_BH select ARCH_INLINE_SPIN_LOCK
arch/s390/kernel/setup.c +3 -1
@@ -21,6 +21,7 @@#include <linux/module.h> #include <linux/sched.h> #include <linux/kernel.h> +#include <linux/memblock.h> #include <linux/mm.h> #include <linux/stddef.h> #include <linux/unistd.h>
@@ -820,7 +821,8 @@ setup_memory(void) end_chunk =min (end_chunk, end_pfn);if (start_chunk >= end_chunk)continue ; -add_active_range (0 , start_chunk, end_chunk); +memblock_add_node (PFN_PHYS (start_chunk), +PFN_PHYS (end_chunk - start_chunk),0 ); pfn =max (start_chunk, start_pfn);for (; pfn < end_chunk; pfn++) page_set_storage_key(PFN_PHYS(pfn),
Signature · 1 line
1.7.3.1
PATCH 21/23 score: Use HAVE_MEMBLOCK_NODE_MAP
In reply to Tejun Heoscore used early_node_map[] just to prime free_area_init_nodes(). Now memblock can be used for the same purpose and early_node_map[] is scheduled to be dropped. Use memblock instead.
While at it, replace 7 space indentations w/ tabs.
--- arch/score/Kconfig | 9 ++++++--- arch/score/kernel/setup.c | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-)
arch/score/Kconfig +6 -3
@@ -1,9 +1,12 @@ menu "Machine selection" config SCORE - def_bool y - select HAVE_GENERIC_HARDIRQS - select GENERIC_IRQ_SHOW + def_bool y + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_SHOW + select HAVE_MEMBLOCK + select HAVE_MEMBLOCK_NODE_MAP + select ARCH_DISCARD_MEMBLOCK choice prompt "System type"
arch/score/kernel/setup.c +3 -1
@@ -26,6 +26,7 @@#include <linux/bootmem.h> #include <linux/initrd.h> #include <linux/ioport.h> +#include <linux/memblock.h> #include <linux/mm.h> #include <linux/seq_file.h> #include <linux/screen_info.h>
@@ -54,7 +55,8 @@ static void __init bootmem_init(void)/* Initialize the boot-time allocator with low memory only. */ bootmap_size =init_bootmem_node (NODE_DATA (0 ), start_pfn, min_low_pfn, max_low_pfn); -add_active_range (0 , min_low_pfn, max_low_pfn); +memblock_add_node (PFN_PHYS (min_low_pfn), +PFN_PHYS (max_low_pfn - min_low_pfn),0 );free_bootmem (PFN_PHYS (start_pfn), (max_low_pfn - start_pfn) <<PAGE_SHIFT );
Signature · 1 line
1.7.3.1
PATCH 22/23 memblock: Kill early_node_map[]
In reply to Tejun HeoNow all ARCH_POPULATES_NODE_MAP archs select HAVE_MEBLOCK_NODE_MAP - there's no user of early_node_map[] left. Kill early_node_map[] and replace ARCH_POPULATES_NODE_MAP with HAVE_MEMBLOCK_NODE_MAP. Also, relocate for_each_mem_pfn_range() and helper from mm.h to memblock.h as page_alloc.c would no longer host an alternative implementation.
This change is ultimately one to one mapping and shouldn't cause any observable difference; however, after the recent changes, there are some functions which now would fit memblock.c better than page_alloc.c and dependency on HAVE_MEMBLOCK_NODE_MAP instead of HAVE_MEMBLOCK doesn't make much sense on some of them. Further cleanups for functions inside HAVE_MEMBLOCK_NODE_MAP in mm.h would be nice.
--- arch/ia64/Kconfig | 3 - arch/mips/Kconfig | 3 - arch/powerpc/Kconfig | 3 - arch/s390/Kconfig | 3 - arch/score/Kconfig | 3 - arch/sh/mm/Kconfig | 3 - arch/sparc/Kconfig | 3 - arch/x86/Kconfig | 3 - drivers/iommu/intel-iommu.c | 1 + include/linux/memblock.h | 23 ++++- include/linux/mm.h | 50 ++------- include/linux/mmzone.h | 8 +- mm/memblock.c | 2 +- mm/page_alloc.c | 259 +++---------------------------------------- 14 files changed, 55 insertions(+), 312 deletions(-)
arch/ia64/Kconfig +0 -3
@@ -477,9 +477,6 @@ config NODES_SHIFT MAX_NUMNODES will be 2^(This value). If in doubt, use the default. -config ARCH_POPULATES_NODE_MAP - def_bool y - # VIRTUAL_MEM_MAP and FLAT_NODE_MEM_MAP are functionally equivalent. # VIRTUAL_MEM_MAP has been retained for historical reasons. config VIRTUAL_MEM_MAP
arch/mips/Kconfig +0 -3
@@ -2067,9 +2067,6 @@ config ARCH_DISCONTIGMEM_ENABLE or have huge holes in the physical address space for other reasons. See <file:Documentation/vm/numa> for more. -config ARCH_POPULATES_NODE_MAP - def_bool y - config ARCH_SPARSEMEM_ENABLE bool select SPARSEMEM_STATIC
arch/powerpc/Kconfig +0 -3
@@ -422,9 +422,6 @@ config ARCH_SPARSEMEM_DEFAULT def_bool y depends on (SMP && PPC_PSERIES) || PPC_PS3 -config ARCH_POPULATES_NODE_MAP - def_bool y - config SYS_SUPPORTS_HUGETLBFS bool
arch/s390/Kconfig +0 -3
@@ -348,9 +348,6 @@ config WARN_DYNAMIC_STACK Say N if you are unsure. -config ARCH_POPULATES_NODE_MAP - def_bool y - comment "Kernel preemption" source "kernel/Kconfig.preempt"
arch/score/Kconfig +0 -3
@@ -63,9 +63,6 @@ config 32BIT config ARCH_FLATMEM_ENABLE def_bool y -config ARCH_POPULATES_NODE_MAP - def_bool y - source "mm/Kconfig" config MEMORY_START
arch/sh/mm/Kconfig +0 -3
@@ -143,9 +143,6 @@ config MAX_ACTIVE_REGIONS CPU_SUBTYPE_SH7785) default "1" -config ARCH_POPULATES_NODE_MAP - def_bool y - config ARCH_SELECT_MEMORY_MODEL def_bool y
arch/sparc/Kconfig +0 -3
@@ -353,9 +353,6 @@ config NODES_SPAN_OTHER_NODES def_bool y depends on NEED_MULTIPLE_NODES -config ARCH_POPULATES_NODE_MAP - def_bool y if SPARC64 - config ARCH_SELECT_MEMORY_MODEL def_bool y if SPARC64
arch/x86/Kconfig +0 -3
@@ -206,9 +206,6 @@ config ZONE_DMA32 bool default X86_64 -config ARCH_POPULATES_NODE_MAP - def_bool y - config AUDIT_ARCH bool default X86_64
drivers/iommu/intel-iommu.c +1 -0
@@ -41,6 +41,7 @@#include <linux/tboot.h> #include <linux/dmi.h> #include <linux/pci-ats.h> +#include <linux/memblock.h> #include <asm/cacheflush.h> #include <asm/iommu.h>
include/linux/memblock.h +20 -3
@@ -58,6 +58,26 @@ int memblock_remove(phys_addr_t base, phys_addr_t size);int memblock_free (phys_addr_t base,phys_addr_t size);int memblock_reserve (phys_addr_t base,phys_addr_t size); +#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP +void __next_mem_pfn_range (int *idx,int nid,unsigned long *out_start_pfn, +unsigned long *out_end_pfn,int *out_nid); + +/** +* for_each_mem_pfn_range - early memory pfn range iterator +* @i: an integer used as loop variable +* @nid: node selector, %MAX_NUMNODES for all nodes +* @p_start: ptr to ulong for start pfn of the range, can be %NULL +* @p_end: ptr to ulong for end pfn of the range, can be %NULL +* @p_nid: ptr to int for nid of the range, can be %NULL +* +* Walks over configured memory ranges. Available after early_node_map is +* populated. +*/ +#define for_each_mem_pfn_range (i, nid, p_start, p_end, p_nid) \ + for (i = -1, __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid); \ + i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid)) +#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ +void __next_free_mem_range (u64 *idx,int nid,phys_addr_t *out_start,phys_addr_t *out_end,int *out_nid);
@@ -101,9 +121,6 @@ static inline int memblock_get_region_node(const struct memblock_region *r) }#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ -/* The numa aware allocator is only available if -* CONFIG_ARCH_POPULATES_NODE_MAP is set -*/ phys_addr_t memblock_find_in_range_node (phys_addr_t start,phys_addr_t end,phys_addr_t size,phys_addr_t align,int nid);phys_addr_t memblock_alloc_nid (phys_addr_t size,phys_addr_t align,int nid);
include/linux/mm.h +11 -39
82 lines not on this page · raw message
include/linux/mmzone.h +4 -4
@@ -598,13 +598,13 @@ struct zonelist {#endif }; -#ifdef CONFIG_ARCH_POPULATES_NODE_MAP +#ifdef CONFIG_MEMBLOCK_HAVE_NODE_MAP struct node_active_region {unsigned long start_pfn;unsigned long end_pfn;int nid; }; -#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */ +#endif /* CONFIG_MEMBLOCK_HAVE_NODE_MAP */ #ifndef CONFIG_DISCONTIGMEM /* The array of struct pages - for discontigmem use pgdat->lmem_map */
@@ -720,7 +720,7 @@ extern int movable_zone;static inline int zone_movable_is_highmem (void ) { -#if defined(CONFIG_HIGHMEM ) && defined(CONFIG_ARCH_POPULATES_NODE_MAP ) +#if defined(CONFIG_HIGHMEM ) && defined(CONFIG_HAVE_MEMBLOCK_NODE )return movable_zone ==ZONE_HIGHMEM ;#else return 0 ;
@@ -938,7 +938,7 @@ static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist,#endif #if !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID ) && \ - !defined(CONFIG_ARCH_POPULATES_NODE_MAP ) + !defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP )static inline unsigned long early_pfn_to_nid (unsigned long pfn) {return 0 ;
mm/memblock.c +1 -1
@@ -716,7 +716,7 @@ phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align)static phys_addr_t __init memblock_nid_range_rev (phys_addr_t start,phys_addr_t end,int *nid) { -#ifdef CONFIG_ARCH_POPULATES_NODE_MAP +#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP unsigned long start_pfn, end_pfn;int i;
mm/page_alloc.c +18 -241
315 lines not on this page · raw message
Signature · 1 line
1.7.3.1
PATCH 23/23 memblock: Reimplement memblock allocation using reverse free area iterator
In reply to Tejun HeoNow that all early memory information is in memblock when enabled, we can implement reverse free area iterator and use it to implement NUMA aware allocator which is then wrapped for simpler variants instead of the confusing and inefficient mending of information in separate NUMA aware allocator.
Implement for_each_free_mem_range_reverse(), use it to reimplement memblock_find_in_range_node() which in turn is used by all allocators.
The visible allocator interface is inconsistent and can probably use some cleanup too.
--- include/linux/memblock.h | 24 ++++- mm/memblock.c | 273 +++++++++++++++++++++------------------------ 2 files changed, 149 insertions(+), 148 deletions(-)
include/linux/memblock.h +22 -2
@@ -46,6 +46,8 @@ extern int memblock_debug;#define memblock_dbg (fmt, ...) \ if (memblock_debug) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) +phys_addr_t memblock_find_in_range_node (phys_addr_t start,phys_addr_t end, +phys_addr_t size,phys_addr_t align,int nid);phys_addr_t memblock_find_in_range (phys_addr_t start,phys_addr_t end,phys_addr_t size,phys_addr_t align);int memblock_free_reserved_regions (void );
@@ -98,6 +100,26 @@ void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start, i != (u64 )ULLONG_MAX ; \ __next_free_mem_range(&i, nid, p_start, p_end, p_nid)) +void __next_free_mem_range_rev (u64 *idx,int nid,phys_addr_t *out_start, +phys_addr_t *out_end,int *out_nid); + +/** +* for_each_free_mem_range_reverse - rev-iterate through free memblock areas +* @i: u64 used as loop variable +* @nid: node selector, %MAX_NUMNODES for all nodes +* @p_start: ptr to phys_addr_t for start address of the range, can be %NULL +* @p_end: ptr to phys_addr_t for end address of the range, can be %NULL +* @p_nid: ptr to int for nid of the range, can be %NULL +* +* Walks over free (memory && !reserved) areas of memblock in reverse +* order. Available as soon as memblock is initialized. +*/ +#define for_each_free_mem_range_reverse (i, nid, p_start, p_end, p_nid) \ + for (i = (u64)ULLONG_MAX, \ + __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid); \ + i != (u64)ULLONG_MAX; \ + __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid)) +#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP int memblock_set_node (phys_addr_t base,phys_addr_t size,int nid);
@@ -121,8 +143,6 @@ static inline int memblock_get_region_node(const struct memblock_region *r) }#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ -phys_addr_t memblock_find_in_range_node (phys_addr_t start,phys_addr_t end, -phys_addr_t size,phys_addr_t align,int nid);phys_addr_t memblock_alloc_nid (phys_addr_t size,phys_addr_t align,int nid);phys_addr_t memblock_alloc_try_nid (phys_addr_t size,phys_addr_t align,int nid);
mm/memblock.c +127 -146
317 lines not on this page · raw message
Signature · 1 line
1.7.3.1
Quoted 6 lines · Tejun Heo
Hello,
This patchset was posted quite a while ago but got lost during the korg disturbance and I forgot about it too. Thankfully, benh pinged me about testing this patchset yesterday, so here's the refreshed version.
A bit scary - you should get it into linux-next i suspect - if that works out then we could then put it into tip:core/memblock if there are no objections from anyone.
It's not really an x86 tree and most of the changes are affecting non-x86 architectures, right?
Thanks,
Ingo
(cc'ing Stephen, hi!)
Quoted 9 lines · Ingo Molnar
Quoted 6 lines · Tejun Heo
Hello,
This patchset was posted quite a while ago but got lost during the korg disturbance and I forgot about it too. Thankfully, benh pinged me about testing this patchset yesterday, so here's the refreshed version.
Quoted 6 lines
A bit scary - you should get it into linux-next i suspect - if that works out then we could then put it into tip:core/memblock if there are no objections from anyone.
It's not really an x86 tree and most of the changes are affecting non-x86 architectures, right?
Hmmm... this was part of the memblock updates going through x86/memblock and unless we're gonna setup a separate tree for memblock (I don't think that would be necessary at this point) I think it would be better to route this x86/memblock eventually. That said, setting up temp linux-next branch for now sounds fine to me. hpa, what do you think?
Thanks.
Signature · 1 line
tejun
Quoted 19 lines · Tejun Heo
(cc'ing Stephen, hi!)
Quoted 9 lines · Ingo Molnar
Quoted 6 lines · Tejun Heo
Hello,
This patchset was posted quite a while ago but got lost during the korg disturbance and I forgot about it too. Thankfully, benh pinged me about testing this patchset yesterday, so here's the refreshed version.
Quoted 6 lines
A bit scary - you should get it into linux-next i suspect - if that works out then we could then put it into tip:core/memblock if there are no objections from anyone.
It's not really an x86 tree and most of the changes are affecting non-x86 architectures, right?
Quoted 6 lines
Hmmm... this was part of the memblock updates going through x86/memblock and unless we're gonna setup a separate tree for memblock (I don't think that would be necessary at this point) I think it would be better to route this x86/memblock eventually. That said, setting up temp linux-next branch for now sounds fine to me. hpa, what do you think?
I'm fine with routing this through -tip - the branch can be tip:core/memblock as this is really not just an x86 series - but if you could pre-test all the arch impact in linux-next that would be great ...
Thanks,
Ingo
Quoted 9 lines · Ingo Molnar
Quoted 6 lines · Tejun Heo
Hello,
This patchset was posted quite a while ago but got lost during the korg disturbance and I forgot about it too. Thankfully, benh pinged me about testing this patchset yesterday, so here's the refreshed version.
Quoted 6 lines
A bit scary - you should get it into linux-next i suspect - if that works out then we could then put it into tip:core/memblock if there are no objections from anyone.
It's not really an x86 tree and most of the changes are affecting non-x86 architectures, right?
They do look nice tho. I've asked some folks familiar with NUMA stuff here at IBM to give them a spin on power, haven't heard back yet.
Cheers,
Ben.