[PATCH 01/21] openrisc: prefer memblock APIs returning virtual address
The allocation of the page tables memory in openrics uses memblock_phys_alloc() and then converts the returned physical address to virtual one. Use memblock_alloc_raw() and add a panic() if the allocation fails. Signed-off-by: Mike Rapoport --- arch/openrisc/mm/init.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c index d157310..caeb418 100644 --- a/arch/openrisc/mm/init.c +++ b/arch/openrisc/mm/init.c @@ -105,7 +105,10 @@ static void __init map_ram(void) } /* Alloc one page for holding PTE's... */ - pte = (pte_t *) __va(memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE)); + pte = memblock_alloc_raw(PAGE_SIZE, PAGE_SIZE); + if (!pte) + panic("%s: Failed to allocate page for PTEs\n", + __func__); set_pmd(pme, __pmd(_KERNPG_TABLE + __pa(pte))); /* Fill the newly allocated page with PTE'S */ -- 2.7.4
[PATCH 04/21] memblock: drop memblock_alloc_base_nid()
The memblock_alloc_base_nid() is a oneliner wrapper for memblock_alloc_range_nid() without any side effect. Replace it's usage by the direct calls to memblock_alloc_range_nid(). Signed-off-by: Mike Rapoport --- include/linux/memblock.h | 3 --- mm/memblock.c| 15 --- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 60e100f..f7ef313 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -490,9 +490,6 @@ static inline bool memblock_bottom_up(void) phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end, enum memblock_flags flags); -phys_addr_t memblock_alloc_base_nid(phys_addr_t size, - phys_addr_t align, phys_addr_t max_addr, - int nid, enum memblock_flags flags); 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, diff --git a/mm/memblock.c b/mm/memblock.c index a32db30..c80029e 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1346,21 +1346,14 @@ phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align, flags); } -phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size, - phys_addr_t align, phys_addr_t max_addr, - int nid, enum memblock_flags flags) -{ - return memblock_alloc_range_nid(size, align, 0, max_addr, nid, flags); -} - phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, int nid) { enum memblock_flags flags = choose_memblock_flags(); phys_addr_t ret; again: - ret = memblock_alloc_base_nid(size, align, MEMBLOCK_ALLOC_ACCESSIBLE, - nid, flags); + ret = memblock_alloc_range_nid(size, align, 0, + MEMBLOCK_ALLOC_ACCESSIBLE, nid, flags); if (!ret && (flags & MEMBLOCK_MIRROR)) { flags &= ~MEMBLOCK_MIRROR; @@ -1371,8 +1364,8 @@ phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr) { - return memblock_alloc_base_nid(size, align, max_addr, NUMA_NO_NODE, - MEMBLOCK_NONE); + return memblock_alloc_range_nid(size, align, 0, max_addr, NUMA_NO_NODE, + MEMBLOCK_NONE); } phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr) -- 2.7.4
[PATCH 06/21] memblock: memblock_phys_alloc_try_nid(): don't panic
The memblock_phys_alloc_try_nid() function tries to allocate memory from the requested node and then falls back to allocation from any node in the system. The memblock_alloc_base() fallback used by this function panics if the allocation fails. Replace the memblock_alloc_base() fallback with the direct call to memblock_alloc_range_nid() and update the memblock_phys_alloc_try_nid() callers to check the returned value and panic in case of error. Signed-off-by: Mike Rapoport --- arch/arm64/mm/numa.c | 4 arch/powerpc/mm/numa.c | 4 mm/memblock.c | 4 +++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index ae34e3a..2c61ea4 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -237,6 +237,10 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn) pr_info("Initmem setup node %d []\n", nid); nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); + if (!nd_pa) + panic("Cannot allocate %zu bytes for node %d data\n", + nd_size, nid); + nd = __va(nd_pa); /* report and initialize */ diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 270cefb..8f2bbe1 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -788,6 +788,10 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn) int tnid; nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); + if (!nd_pa) + panic("Cannot allocate %zu bytes for node %d data\n", + nd_size, nid); + nd = __va(nd_pa); /* report and initialize */ diff --git a/mm/memblock.c b/mm/memblock.c index f019aee..8aabb1b 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1393,7 +1393,9 @@ phys_addr_t __init memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t ali if (res) return res; - return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE); + return memblock_alloc_range_nid(size, align, 0, + MEMBLOCK_ALLOC_ACCESSIBLE, + NUMA_NO_NODE, MEMBLOCK_NONE); } /** -- 2.7.4
[PATCH 09/21] memblock: drop memblock_alloc_base()
The memblock_alloc_base() function tries to allocate a memory up to the limit specified by its max_addr parameter and panics if the allocation fails. Replace its usage with memblock_phys_alloc_range() and make the callers check the return value and panic in case of error. Signed-off-by: Mike Rapoport --- arch/powerpc/kernel/rtas.c | 6 +- arch/powerpc/mm/hash_utils_64.c | 8 ++-- arch/s390/kernel/smp.c | 6 +- drivers/macintosh/smu.c | 2 +- include/linux/memblock.h| 2 -- mm/memblock.c | 14 -- 6 files changed, 17 insertions(+), 21 deletions(-) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index de35bd8f..fbc6761 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -1187,7 +1187,11 @@ void __init rtas_initialize(void) ibm_suspend_me_token = rtas_token("ibm,suspend-me"); } #endif - rtas_rmo_buf = memblock_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); + rtas_rmo_buf = memblock_phys_alloc_range(RTAS_RMOBUF_MAX, PAGE_SIZE, +0, rtas_region); + if (!rtas_rmo_buf) + panic("ERROR: RTAS: Failed to allocate %lx bytes below %pa\n", + PAGE_SIZE, &rtas_region); #ifdef CONFIG_RTAS_ERROR_LOGGING rtas_last_error_token = rtas_token("rtas-last-error"); diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index bc6be44..c7d5f48 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -882,8 +882,12 @@ static void __init htab_initialize(void) } #endif /* CONFIG_PPC_CELL */ - table = memblock_alloc_base(htab_size_bytes, htab_size_bytes, - limit); + table = memblock_phys_alloc_range(htab_size_bytes, + htab_size_bytes, + 0, limit); + if (!table) + panic("ERROR: Failed to allocate %pa bytes below %pa\n", + &htab_size_bytes, &limit); DBG("Hash table allocated at %lx, size: %lx\n", table, htab_size_bytes); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index f82b3d3..9061597 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -651,7 +651,11 @@ void __init smp_save_dump_cpus(void) /* No previous system present, normal boot. */ return; /* Allocate a page as dumping area for the store status sigps */ - page = memblock_alloc_base(PAGE_SIZE, PAGE_SIZE, 1UL << 31); + page = memblock_phys_alloc_range(PAGE_SIZE, PAGE_SIZE, 0, 1UL << 31); + if (!page) + panic("ERROR: Failed to allocate %x bytes below %lx\n", + PAGE_SIZE, 1UL << 31); + /* Set multi-threading state to the previous system. */ pcpu_set_smt(sclp.mtid_prev); boot_cpu_addr = stap(); diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 0a0b8e1..42cf68d 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -485,7 +485,7 @@ int __init smu_init (void) * SMU based G5s need some memory below 2Gb. Thankfully this is * called at a time where memblock is still available. */ - smu_cmdbuf_abs = memblock_alloc_base(4096, 4096, 0x8000UL); + smu_cmdbuf_abs = memblock_phys_alloc_range(4096, 4096, 0, 0x8000UL); if (smu_cmdbuf_abs == 0) { printk(KERN_ERR "SMU: Command buffer allocation failed !\n"); ret = -EINVAL; diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 768e2b4..6874fdc 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -494,8 +494,6 @@ static inline bool memblock_bottom_up(void) return memblock.bottom_up; } -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_reserved_size(void); phys_addr_t memblock_mem_size(unsigned long limit_pfn); diff --git a/mm/memblock.c b/mm/memblock.c index e5ffdcd..531fa77 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1363,20 +1363,6 @@ phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, return ret; } -phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr) -{ - phys_addr_t alloc; - - alloc = memblock_alloc_range_nid(size, align, 0, max_addr, NUMA_NO_NODE, - MEMBLOCK_NONE); - - if (alloc == 0) - panic("ERROR: Failed to allocate %pa bytes
[PATCH 11/21] memblock: make memblock_find_in_range_node() and choose_memblock_flags() static
These functions are not used outside memblock. Make them static. Signed-off-by: Mike Rapoport --- include/linux/memblock.h | 4 mm/memblock.c| 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index cf4cd9c..f5a83a1 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -111,9 +111,6 @@ void memblock_discard(void); #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 size, phys_addr_t align, - phys_addr_t start, phys_addr_t end, - int nid, enum memblock_flags flags); phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end, phys_addr_t size, phys_addr_t align); void memblock_allow_resize(void); @@ -130,7 +127,6 @@ int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); int memblock_mark_mirror(phys_addr_t base, phys_addr_t size); int memblock_mark_nomap(phys_addr_t base, phys_addr_t size); int memblock_clear_nomap(phys_addr_t base, phys_addr_t size); -enum memblock_flags choose_memblock_flags(void); unsigned long memblock_free_all(void); void reset_node_managed_pages(pg_data_t *pgdat); diff --git a/mm/memblock.c b/mm/memblock.c index 739f769..03b3929 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -125,7 +125,7 @@ static int memblock_can_resize __initdata_memblock; static int memblock_memory_in_slab __initdata_memblock = 0; static int memblock_reserved_in_slab __initdata_memblock = 0; -enum memblock_flags __init_memblock choose_memblock_flags(void) +static enum memblock_flags __init_memblock choose_memblock_flags(void) { return system_has_some_mirror ? MEMBLOCK_MIRROR : MEMBLOCK_NONE; } @@ -254,7 +254,7 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end, * Return: * Found address on success, 0 on failure. */ -phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size, +static phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end, int nid, enum memblock_flags flags) -- 2.7.4
[PATCH 15/21] sparc: add checks for the return value of memblock_alloc*()
Add panic() calls if memblock_alloc*() returns NULL. Most of the changes are simply addition of if(!ptr) panic(); statements after the calls to memblock_alloc*() variants. Exceptions are pcpu_populate_pte() and kernel_map_range() that were slightly refactored to accommodate the change. Signed-off-by: Mike Rapoport --- arch/sparc/kernel/prom_32.c | 2 ++ arch/sparc/kernel/setup_64.c | 6 ++ arch/sparc/kernel/smp_64.c | 12 arch/sparc/mm/init_64.c | 11 +++ arch/sparc/mm/srmmu.c| 8 5 files changed, 39 insertions(+) diff --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c index e7126ca..869b16c 100644 --- a/arch/sparc/kernel/prom_32.c +++ b/arch/sparc/kernel/prom_32.c @@ -33,6 +33,8 @@ void * __init prom_early_alloc(unsigned long size) void *ret; ret = memblock_alloc(size, SMP_CACHE_BYTES); + if (!ret) + panic("%s: Failed to allocate %lu bytes\n", __func__, size); prom_early_allocated += size; diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 51c4d12..fd2182a 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -624,8 +624,14 @@ void __init alloc_irqstack_bootmem(void) softirq_stack[i] = memblock_alloc_node(THREAD_SIZE, THREAD_SIZE, node); + if (!softirq_stack[i]) + panic("%s: Failed to allocate %lu bytes align=%lx nid=%d\n", + __func__, THREAD_SIZE, THREAD_SIZE, node); hardirq_stack[i] = memblock_alloc_node(THREAD_SIZE, THREAD_SIZE, node); + if (!hardirq_stack[i]) + panic("%s: Failed to allocate %lu bytes align=%lx nid=%d\n", + __func__, THREAD_SIZE, THREAD_SIZE, node); } } diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index f45d876..a8275fe 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -1628,6 +1628,8 @@ static void __init pcpu_populate_pte(unsigned long addr) pud_t *new; new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; pgd_populate(&init_mm, pgd, new); } @@ -1636,6 +1638,8 @@ static void __init pcpu_populate_pte(unsigned long addr) pmd_t *new; new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; pud_populate(&init_mm, pud, new); } @@ -1644,8 +1648,16 @@ static void __init pcpu_populate_pte(unsigned long addr) pte_t *new; new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; pmd_populate_kernel(&init_mm, pmd, new); } + + return; + +err_alloc: + panic("%s: Failed to allocate %lu bytes align=%lx from=%lx\n", + __func__, PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); } void __init setup_per_cpu_areas(void) diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index ef340e8..f2d70ff 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -1809,6 +1809,8 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; alloc_bytes += PAGE_SIZE; pgd_populate(&init_mm, pgd, new); } @@ -1822,6 +1824,8 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, } new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; alloc_bytes += PAGE_SIZE; pud_populate(&init_mm, pud, new); } @@ -1836,6 +1840,8 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, } new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; alloc_bytes += PAGE_SIZE; pmd_populate_kernel(&init_mm, pmd, new); } @@ -1855,6 +1861,11 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, } return allo
[PATCH 14/21] ia64: add checks for the return value of memblock_alloc*()
Add panic() calls if memblock_alloc*() returns NULL. Most of the changes are simply addition of if(!ptr) panic(); statements after the calls to memblock_alloc*() variants. Exceptions are create_mem_map_page_table() and ia64_log_init() that were slightly refactored to accommodate the change. Signed-off-by: Mike Rapoport --- arch/ia64/kernel/mca.c | 20 ++-- arch/ia64/mm/contig.c | 8 ++-- arch/ia64/mm/discontig.c| 4 arch/ia64/mm/init.c | 38 ++ arch/ia64/mm/tlb.c | 6 ++ arch/ia64/sn/kernel/io_common.c | 3 +++ arch/ia64/sn/kernel/setup.c | 12 +++- 7 files changed, 74 insertions(+), 17 deletions(-) diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 370bc34..5cabb3f 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -359,11 +359,6 @@ typedef struct ia64_state_log_s static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES]; -#define IA64_LOG_ALLOCATE(it, size) \ - {ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \ - (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES); \ - ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \ - (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES);} #define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock) #define IA64_LOG_LOCK(it) spin_lock_irqsave(&ia64_state_log[it].isl_lock, s) #define IA64_LOG_UNLOCK(it) spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s) @@ -378,6 +373,19 @@ static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES]; #define IA64_LOG_CURR_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)])) #define IA64_LOG_COUNT(it) ia64_state_log[it].isl_count +static inline void ia64_log_allocate(int it, u64 size) +{ + ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = + (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES); + if (!ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)]) + panic("%s: Failed to allocate %llu bytes\n", __func__, size); + + ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = + (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES); + if (!ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)]) + panic("%s: Failed to allocate %llu bytes\n", __func__, size); +} + /* * ia64_log_init * Reset the OS ia64 log buffer @@ -399,7 +407,7 @@ ia64_log_init(int sal_info_type) return; // set up OS data structures to hold error info - IA64_LOG_ALLOCATE(sal_info_type, max_size); + ia64_log_allocate(sal_info_type, max_size); } /* diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index 6e44723..d29fb6b 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -84,9 +84,13 @@ void *per_cpu_init(void) static inline void alloc_per_cpu_data(void) { - cpu_data = memblock_alloc_from(PERCPU_PAGE_SIZE * num_possible_cpus(), - PERCPU_PAGE_SIZE, + size_t size = PERCPU_PAGE_SIZE * num_possible_cpus(); + + cpu_data = memblock_alloc_from(size, PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); + if (!cpu_data) + panic("%s: Failed to allocate %lu bytes align=%lx from=%lx\n", + __func__, size, PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); } /** diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index f9c3675..05490dd 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -454,6 +454,10 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize) __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, bestnode); + if (!ptr) + panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d from=%lx\n", + __func__, pernodesize, PERCPU_PAGE_SIZE, bestnode, + __pa(MAX_DMA_ADDRESS)); return ptr; } diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 29d8415..e49200e 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -444,23 +444,45 @@ int __init create_mem_map_page_table(u64 start, u64 end, void *arg) for (address = start_page; address < end_page; address += PAGE_SIZE) { pgd = pgd_offset_k(address); - if (pgd_none(*pgd)) - pgd_populate(&init_mm, pgd, memblock_alloc_node(PAGE_SIZE, PAGE_SIZE, node)); + if (pgd_none(*pgd)) { + pud = memblock_alloc_node(PAGE_SIZE, PAGE_SIZE, node); + if (!pud) + goto err_all
[PATCH 16/21] mm/percpu: add checks for the return value of memblock_alloc*()
Add panic() calls if memblock_alloc() returns NULL. The panic() format duplicates the one used by memblock itself and in order to avoid explosion with long parameters list replace open coded allocation size calculations with a local variable. Signed-off-by: Mike Rapoport --- mm/percpu.c | 73 +++-- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/mm/percpu.c b/mm/percpu.c index db86282..5998b03 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -1086,6 +1086,7 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr, struct pcpu_chunk *chunk; unsigned long aligned_addr, lcm_align; int start_offset, offset_bits, region_size, region_bits; + size_t alloc_size; /* region calculations */ aligned_addr = tmp_addr & PAGE_MASK; @@ -1101,9 +1102,12 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr, region_size = ALIGN(start_offset + map_size, lcm_align); /* allocate chunk */ - chunk = memblock_alloc(sizeof(struct pcpu_chunk) + - BITS_TO_LONGS(region_size >> PAGE_SHIFT), - SMP_CACHE_BYTES); + alloc_size = sizeof(struct pcpu_chunk) + + BITS_TO_LONGS(region_size >> PAGE_SHIFT); + chunk = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!chunk) + panic("%s: Failed to allocate %zu bytes\n", __func__, + alloc_size); INIT_LIST_HEAD(&chunk->list); @@ -1114,12 +1118,25 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr, chunk->nr_pages = region_size >> PAGE_SHIFT; region_bits = pcpu_chunk_map_bits(chunk); - chunk->alloc_map = memblock_alloc(BITS_TO_LONGS(region_bits) * sizeof(chunk->alloc_map[0]), - SMP_CACHE_BYTES); - chunk->bound_map = memblock_alloc(BITS_TO_LONGS(region_bits + 1) * sizeof(chunk->bound_map[0]), - SMP_CACHE_BYTES); - chunk->md_blocks = memblock_alloc(pcpu_chunk_nr_blocks(chunk) * sizeof(chunk->md_blocks[0]), - SMP_CACHE_BYTES); + alloc_size = BITS_TO_LONGS(region_bits) * sizeof(chunk->alloc_map[0]); + chunk->alloc_map = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!chunk->alloc_map) + panic("%s: Failed to allocate %zu bytes\n", __func__, + alloc_size); + + alloc_size = + BITS_TO_LONGS(region_bits + 1) * sizeof(chunk->bound_map[0]); + chunk->bound_map = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!chunk->bound_map) + panic("%s: Failed to allocate %zu bytes\n", __func__, + alloc_size); + + alloc_size = pcpu_chunk_nr_blocks(chunk) * sizeof(chunk->md_blocks[0]); + chunk->md_blocks = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!chunk->md_blocks) + panic("%s: Failed to allocate %zu bytes\n", __func__, + alloc_size); + pcpu_init_md_blocks(chunk); /* manage populated page bitmap */ @@ -2044,6 +2061,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, int group, unit, i; int map_size; unsigned long tmp_addr; + size_t alloc_size; #define PCPU_SETUP_BUG_ON(cond)do { \ if (unlikely(cond)) { \ @@ -2075,14 +2093,29 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, PCPU_SETUP_BUG_ON(pcpu_verify_alloc_info(ai) < 0); /* process group information and build config tables accordingly */ - group_offsets = memblock_alloc(ai->nr_groups * sizeof(group_offsets[0]), - SMP_CACHE_BYTES); - group_sizes = memblock_alloc(ai->nr_groups * sizeof(group_sizes[0]), -SMP_CACHE_BYTES); - unit_map = memblock_alloc(nr_cpu_ids * sizeof(unit_map[0]), - SMP_CACHE_BYTES); - unit_off = memblock_alloc(nr_cpu_ids * sizeof(unit_off[0]), - SMP_CACHE_BYTES); + alloc_size = ai->nr_groups * sizeof(group_offsets[0]); + group_offsets = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!group_offsets) + panic("%s: Failed to allocate %zu bytes\n", __func__, + alloc_size); + + alloc_size = ai->nr_groups * sizeof(group_sizes[0]); + group_sizes = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!group_sizes) + panic("%s: Failed to allocate %zu bytes\n&q
[PATCH 21/21] memblock: drop memblock_alloc_*_nopanic() variants
As all the memblock allocation functions return NULL in case of error rather than panic(), the duplicates with _nopanic suffix can be removed. Signed-off-by: Mike Rapoport --- arch/arc/kernel/unwind.c | 3 +-- arch/sh/mm/init.c | 2 +- arch/x86/kernel/setup_percpu.c | 10 +- arch/x86/mm/kasan_init_64.c| 14 -- drivers/firmware/memmap.c | 2 +- drivers/usb/early/xhci-dbc.c | 2 +- include/linux/memblock.h | 35 --- kernel/dma/swiotlb.c | 2 +- kernel/printk/printk.c | 17 +++-- mm/memblock.c | 35 --- mm/page_alloc.c| 10 +- mm/page_ext.c | 2 +- mm/percpu.c| 11 --- mm/sparse.c| 6 ++ 14 files changed, 37 insertions(+), 114 deletions(-) diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c index d34f69e..271e9fa 100644 --- a/arch/arc/kernel/unwind.c +++ b/arch/arc/kernel/unwind.c @@ -181,8 +181,7 @@ static void init_unwind_hdr(struct unwind_table *table, */ static void *__init unw_hdr_alloc_early(unsigned long sz) { - return memblock_alloc_from_nopanic(sz, sizeof(unsigned int), - MAX_DMA_ADDRESS); + return memblock_alloc_from(sz, sizeof(unsigned int), MAX_DMA_ADDRESS); } static void *unw_hdr_alloc(unsigned long sz) diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index fceefd9..7062132 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -202,7 +202,7 @@ void __init allocate_pgdat(unsigned int nid) get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); #ifdef CONFIG_NEED_MULTIPLE_NODES - NODE_DATA(nid) = memblock_alloc_try_nid_nopanic( + NODE_DATA(nid) = memblock_alloc_try_nid( sizeof(struct pglist_data), SMP_CACHE_BYTES, MEMBLOCK_LOW_LIMIT, MEMBLOCK_ALLOC_ACCESSIBLE, nid); diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index e8796fc..0c5e9bf 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -106,22 +106,22 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size, void *ptr; if (!node_online(node) || !NODE_DATA(node)) { - ptr = memblock_alloc_from_nopanic(size, align, goal); + ptr = memblock_alloc_from(size, align, goal); pr_info("cpu %d has no node %d or node-local memory\n", cpu, node); pr_debug("per cpu data for cpu%d %lu bytes at %016lx\n", cpu, size, __pa(ptr)); } else { - ptr = memblock_alloc_try_nid_nopanic(size, align, goal, -MEMBLOCK_ALLOC_ACCESSIBLE, -node); + ptr = memblock_alloc_try_nid(size, align, goal, +MEMBLOCK_ALLOC_ACCESSIBLE, +node); pr_debug("per cpu data for cpu%d %lu bytes on node%d at %016lx\n", cpu, size, node, __pa(ptr)); } return ptr; #else - return memblock_alloc_from_nopanic(size, align, goal); + return memblock_alloc_from(size, align, goal); #endif } diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c index 462fde8..8dc0fc0 100644 --- a/arch/x86/mm/kasan_init_64.c +++ b/arch/x86/mm/kasan_init_64.c @@ -24,14 +24,16 @@ extern struct range pfn_mapped[E820_MAX_ENTRIES]; static p4d_t tmp_p4d_table[MAX_PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE); -static __init void *early_alloc(size_t size, int nid, bool panic) +static __init void *early_alloc(size_t size, int nid, bool should_panic) { - if (panic) - return memblock_alloc_try_nid(size, size, - __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, nid); - else - return memblock_alloc_try_nid_nopanic(size, size, + void *ptr = memblock_alloc_try_nid(size, size, __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, nid); + + if (!ptr && should_panic) + panic("%pS: Failed to allocate page, nid=%d from=%lx\n", + (void *)_RET_IP_, nid, __pa(MAX_DMA_ADDRESS)); + + return ptr; } static void __init kasan_populate_pmd(pmd_t *pmd, unsigned long addr, diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c index ec4fd25..d168c87 100644 --- a/drivers/firmware/memmap.c +++ b/drivers/firmware/memmap.c @@ -333,7 +333,7 @@ int __init firmware_map_add_early(u64 start, u64 end, const char *type) { struct firmware_map_entry *entry; - entry =
[PATCH 20/21] memblock: memblock_alloc_try_nid: don't panic
As all the memblock_alloc*() users are now checking the return value and panic() in case of error, the panic() call can be removed from the core memblock allocator, namely memblock_alloc_try_nid(). Signed-off-by: Mike Rapoport --- mm/memblock.c | 15 +-- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/mm/memblock.c b/mm/memblock.c index 03b3929..7164275 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1526,7 +1526,7 @@ void * __init memblock_alloc_try_nid_nopanic( } /** - * memblock_alloc_try_nid - allocate boot memory block with panicking + * memblock_alloc_try_nid - allocate boot memory block * @size: size of memory block to be allocated in bytes * @align: alignment of the region and block's size * @min_addr: the lower bound of the memory region from where the allocation @@ -1536,9 +1536,8 @@ void * __init memblock_alloc_try_nid_nopanic( * allocate only from memory limited by memblock.current_limit value * @nid: nid of the free area to find, %NUMA_NO_NODE for any node * - * Public panicking version of memblock_alloc_try_nid_nopanic() - * which provides debug information (including caller info), if enabled, - * and panics if the request can not be satisfied. + * Public function, provides additional debug information (including caller + * info), if enabled. This function zeroes the allocated memory. * * Return: * Virtual address of allocated memory block on success, NULL on failure. @@ -1555,14 +1554,10 @@ void * __init memblock_alloc_try_nid( &max_addr, (void *)_RET_IP_); ptr = memblock_alloc_internal(size, align, min_addr, max_addr, nid); - if (ptr) { + if (ptr) memset(ptr, 0, size); - return ptr; - } - panic("%s: Failed to allocate %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa\n", - __func__, (u64)size, (u64)align, nid, &min_addr, &max_addr); - return NULL; + return ptr; } /** -- 2.7.4
[PATCH 17/21] init/main: add checks for the return value of memblock_alloc*()
Add panic() calls if memblock_alloc() returns NULL. The panic() format duplicates the one used by memblock itself and in order to avoid explosion with long parameters list replace open coded allocation size calculations with a local variable. Signed-off-by: Mike Rapoport --- init/main.c | 26 -- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/init/main.c b/init/main.c index a56f65a..d58a365 100644 --- a/init/main.c +++ b/init/main.c @@ -373,12 +373,20 @@ static inline void smp_prepare_cpus(unsigned int maxcpus) { } */ static void __init setup_command_line(char *command_line) { - saved_command_line = - memblock_alloc(strlen(boot_command_line) + 1, SMP_CACHE_BYTES); - initcall_command_line = - memblock_alloc(strlen(boot_command_line) + 1, SMP_CACHE_BYTES); - static_command_line = memblock_alloc(strlen(command_line) + 1, -SMP_CACHE_BYTES); + size_t len = strlen(boot_command_line) + 1; + + saved_command_line = memblock_alloc(len, SMP_CACHE_BYTES); + if (!saved_command_line) + panic("%s: Failed to allocate %zu bytes\n", __func__, len); + + initcall_command_line = memblock_alloc(len, SMP_CACHE_BYTES); + if (!initcall_command_line) + panic("%s: Failed to allocate %zu bytes\n", __func__, len); + + static_command_line = memblock_alloc(len, SMP_CACHE_BYTES); + if (!static_command_line) + panic("%s: Failed to allocate %zu bytes\n", __func__, len); + strcpy(saved_command_line, boot_command_line); strcpy(static_command_line, command_line); } @@ -773,8 +781,14 @@ static int __init initcall_blacklist(char *str) pr_debug("blacklisting initcall %s\n", str_entry); entry = memblock_alloc(sizeof(*entry), SMP_CACHE_BYTES); + if (!entry) + panic("%s: Failed to allocate %zu bytes\n", + __func__, sizeof(*entry)); entry->buf = memblock_alloc(strlen(str_entry) + 1, SMP_CACHE_BYTES); + if (!entry->buf) + panic("%s: Failed to allocate %zu bytes\n", + __func__, strlen(str_entry) + 1); strcpy(entry->buf, str_entry); list_add(&entry->next, &blacklisted_initcalls); } -- 2.7.4
[PATCH 19/21] treewide: add checks for the return value of memblock_alloc*()
Add check for the return value of memblock_alloc*() functions and call panic() in case of error. The panic message repeats the one used by panicing memblock allocators with adjustment of parameters to include only relevant ones. The replacement was mostly automated with semantic patches like the one below with manual massaging of format strings. @@ expression ptr, size, align; @@ ptr = memblock_alloc(size, align); + if (!ptr) + panic("%s: Failed to allocate %lu bytes align=0x%lx\n", __func__, size, align); Signed-off-by: Mike Rapoport --- arch/alpha/kernel/core_cia.c | 3 +++ arch/alpha/kernel/core_marvel.c | 6 ++ arch/alpha/kernel/pci-noop.c | 11 ++- arch/alpha/kernel/pci.c | 11 ++- arch/alpha/kernel/pci_iommu.c | 12 arch/arc/mm/highmem.c | 4 arch/arm/kernel/setup.c | 6 ++ arch/arm/mm/mmu.c | 14 +- arch/arm64/kernel/setup.c | 9 ++--- arch/arm64/mm/kasan_init.c| 10 ++ arch/c6x/mm/dma-coherent.c| 4 arch/c6x/mm/init.c| 3 +++ arch/csky/mm/highmem.c| 5 + arch/h8300/mm/init.c | 3 +++ arch/m68k/atari/stram.c | 4 arch/m68k/mm/init.c | 3 +++ arch/m68k/mm/mcfmmu.c | 6 ++ arch/m68k/mm/motorola.c | 9 + arch/m68k/mm/sun3mmu.c| 6 ++ arch/m68k/sun3/sun3dvma.c | 3 +++ arch/microblaze/mm/init.c | 8 ++-- arch/mips/cavium-octeon/dma-octeon.c | 3 +++ arch/mips/kernel/setup.c | 3 +++ arch/mips/kernel/traps.c | 3 +++ arch/mips/mm/init.c | 5 + arch/nds32/mm/init.c | 12 arch/openrisc/mm/ioremap.c| 8 ++-- arch/powerpc/kernel/dt_cpu_ftrs.c | 5 + arch/powerpc/kernel/pci_32.c | 3 +++ arch/powerpc/kernel/setup-common.c| 3 +++ arch/powerpc/kernel/setup_64.c| 4 arch/powerpc/lib/alloc.c | 3 +++ arch/powerpc/mm/hash_utils_64.c | 3 +++ arch/powerpc/mm/mmu_context_nohash.c | 9 + arch/powerpc/mm/pgtable-book3e.c | 12 ++-- arch/powerpc/mm/pgtable-book3s64.c| 3 +++ arch/powerpc/mm/pgtable-radix.c | 9 - arch/powerpc/mm/ppc_mmu_32.c | 3 +++ arch/powerpc/platforms/pasemi/iommu.c | 3 +++ arch/powerpc/platforms/powermac/nvram.c | 3 +++ arch/powerpc/platforms/powernv/opal.c | 3 +++ arch/powerpc/platforms/powernv/pci-ioda.c | 8 arch/powerpc/platforms/ps3/setup.c| 3 +++ arch/powerpc/sysdev/msi_bitmap.c | 3 +++ arch/s390/kernel/setup.c | 13 + arch/s390/kernel/smp.c| 5 - arch/s390/kernel/topology.c | 6 ++ arch/s390/numa/mode_emu.c | 3 +++ arch/s390/numa/numa.c | 6 +- arch/s390/numa/toptree.c | 8 ++-- arch/sh/mm/init.c | 6 ++ arch/sh/mm/numa.c | 4 arch/um/drivers/net_kern.c| 3 +++ arch/um/drivers/vector_kern.c | 3 +++ arch/um/kernel/initrd.c | 2 ++ arch/um/kernel/mem.c | 16 arch/unicore32/kernel/setup.c | 4 arch/unicore32/mm/mmu.c | 15 +-- arch/x86/kernel/acpi/boot.c | 3 +++ arch/x86/kernel/apic/io_apic.c| 5 + arch/x86/kernel/e820.c| 3 +++ arch/x86/platform/olpc/olpc_dt.c | 3 +++ arch/x86/xen/p2m.c| 11 +-- arch/xtensa/mm/kasan_init.c | 4 arch/xtensa/mm/mmu.c | 3 +++ drivers/clk/ti/clk.c | 3 +++ drivers/macintosh/smu.c | 3 +++ drivers/of/fdt.c | 8 +++- drivers/of/unittest.c | 8 +++- drivers/xen/swiotlb-xen.c | 7 +-- kernel/power/snapshot.c | 3 +++ lib/cpumask.c | 3 +++ mm/kasan/init.c | 10 -- mm/sparse.c | 19 +-- 74 files changed, 415 insertions(+), 29 deletions(-) diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c index 466cd44..f489170 100644 --- a/arch/alpha/kernel/core_cia.c +++ b/arch/alpha/kernel/core_cia.c @@ -332,6 +332,9 @@ cia_prepare_tbia_workaround(int window) /* Use minimal 1K map. */ ppte = memb
[PATCH 13/21] arch: don't memset(0) memory returned by memblock_alloc()
memblock_alloc() already clears the allocated memory, no point in doing it twice. Signed-off-by: Mike Rapoport --- arch/c6x/mm/init.c | 1 - arch/h8300/mm/init.c| 1 - arch/ia64/kernel/mca.c | 2 -- arch/m68k/mm/mcfmmu.c | 1 - arch/microblaze/mm/init.c | 6 ++ arch/sparc/kernel/prom_32.c | 2 -- 6 files changed, 2 insertions(+), 11 deletions(-) diff --git a/arch/c6x/mm/init.c b/arch/c6x/mm/init.c index af5ada0..e83c046 100644 --- a/arch/c6x/mm/init.c +++ b/arch/c6x/mm/init.c @@ -40,7 +40,6 @@ void __init paging_init(void) empty_zero_page = (unsigned long) memblock_alloc(PAGE_SIZE, PAGE_SIZE); - memset((void *)empty_zero_page, 0, PAGE_SIZE); /* * Set up user data space diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c index 6519252..a157890 100644 --- a/arch/h8300/mm/init.c +++ b/arch/h8300/mm/init.c @@ -68,7 +68,6 @@ void __init paging_init(void) * to a couple of allocated pages. */ empty_zero_page = (unsigned long)memblock_alloc(PAGE_SIZE, PAGE_SIZE); - memset((void *)empty_zero_page, 0, PAGE_SIZE); /* * Set up SFC/DFC registers (user data space). diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 74d148b..370bc34 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -400,8 +400,6 @@ ia64_log_init(int sal_info_type) // set up OS data structures to hold error info IA64_LOG_ALLOCATE(sal_info_type, max_size); - memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size); - memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size); } /* diff --git a/arch/m68k/mm/mcfmmu.c b/arch/m68k/mm/mcfmmu.c index 0de4999..492f953 100644 --- a/arch/m68k/mm/mcfmmu.c +++ b/arch/m68k/mm/mcfmmu.c @@ -44,7 +44,6 @@ void __init paging_init(void) int i; empty_zero_page = (void *) memblock_alloc(PAGE_SIZE, PAGE_SIZE); - memset((void *) empty_zero_page, 0, PAGE_SIZE); pg_dir = swapper_pg_dir; memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir)); diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 44f4b89..bd1cd4b 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -376,10 +376,8 @@ void * __ref zalloc_maybe_bootmem(size_t size, gfp_t mask) if (mem_init_done) p = kzalloc(size, mask); - else { + else p = memblock_alloc(size, SMP_CACHE_BYTES); - if (p) - memset(p, 0, size); - } + return p; } diff --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c index 38940af..e7126ca 100644 --- a/arch/sparc/kernel/prom_32.c +++ b/arch/sparc/kernel/prom_32.c @@ -33,8 +33,6 @@ void * __init prom_early_alloc(unsigned long size) void *ret; ret = memblock_alloc(size, SMP_CACHE_BYTES); - if (ret != NULL) - memset(ret, 0, size); prom_early_allocated += size; -- 2.7.4
[PATCH 18/21] swiotlb: add checks for the return value of memblock_alloc*()
Add panic() calls if memblock_alloc() returns NULL. The panic() format duplicates the one used by memblock itself and in order to avoid explosion with long parameters list replace open coded allocation size calculations with a local variable. Signed-off-by: Mike Rapoport --- kernel/dma/swiotlb.c | 19 +-- 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index d636177..e78835c8 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -191,6 +191,7 @@ void __init swiotlb_update_mem_attributes(void) int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) { unsigned long i, bytes; + size_t alloc_size; bytes = nslabs << IO_TLB_SHIFT; @@ -203,12 +204,18 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE * between io_tlb_start and io_tlb_end. */ - io_tlb_list = memblock_alloc( - PAGE_ALIGN(io_tlb_nslabs * sizeof(int)), - PAGE_SIZE); - io_tlb_orig_addr = memblock_alloc( - PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)), - PAGE_SIZE); + alloc_size = PAGE_ALIGN(io_tlb_nslabs * sizeof(int)); + io_tlb_list = memblock_alloc(alloc_size, PAGE_SIZE); + if (!io_tlb_list) + panic("%s: Failed to allocate %lu bytes align=0x%lx\n", + __func__, alloc_size, PAGE_SIZE); + + alloc_size = PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)); + io_tlb_orig_addr = memblock_alloc(alloc_size, PAGE_SIZE); + if (!io_tlb_orig_addr) + panic("%s: Failed to allocate %lu bytes align=0x%lx\n", + __func__, alloc_size, PAGE_SIZE); + for (i = 0; i < io_tlb_nslabs; i++) { io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); io_tlb_orig_addr[i] = INVALID_PHYS_ADDR; -- 2.7.4
[PATCH 10/21] memblock: refactor internal allocation functions
Currently, memblock has several internal functions with overlapping functionality. They all call memblock_find_in_range_node() to find free memory and then reserve the allocated range and mark it with kmemleak. However, there is difference in the allocation constraints and in fallback strategies. The allocations returning physical address first attempt to find free memory on the specified node within mirrored memory regions, then retry on the same node without the requirement for memory mirroring and finally fall back to all available memory. The allocations returning virtual address start with clamping the allowed range to memblock.current_limit, attempt to allocate from the specified node from regions with mirroring and with user defined minimal address. If such allocation fails, next attempt is done with node restriction lifted. Next, the allocation is retried with minimal address reset to zero and at last without the requirement for mirrored regions. Let's consolidate various fallbacks handling and make them more consistent for physical and virtual variants. Most of the fallback handling is moved to memblock_alloc_range_nid() and it now handles node and mirror fallbacks. The memblock_alloc_internal() uses memblock_alloc_range_nid() to get a physical address of the allocated range and converts it to virtual address. The fallback for allocation below the specified minimal address remains in memblock_alloc_internal() because memblock_alloc_range_nid() is used by CMA with exact requirement for lower bounds. The memblock_phys_alloc_nid() function is completely dropped as it is not used anywhere outside memblock and its only usage can be replaced by a call to memblock_alloc_range_nid(). Signed-off-by: Mike Rapoport --- include/linux/memblock.h | 1 - mm/memblock.c| 173 +-- 2 files changed, 78 insertions(+), 96 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 6874fdc..cf4cd9c 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -371,7 +371,6 @@ static inline int memblock_get_region_node(const struct memblock_region *r) phys_addr_t memblock_phys_alloc_range(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end); -phys_addr_t memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, int nid); phys_addr_t memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid); static inline phys_addr_t memblock_phys_alloc(phys_addr_t size, diff --git a/mm/memblock.c b/mm/memblock.c index 531fa77..739f769 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1312,30 +1312,84 @@ __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone, #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */ +/** + * memblock_alloc_range_nid - allocate boot memory block + * @size: size of memory block to be allocated in bytes + * @align: alignment of the region and block's size + * @start: the lower bound of the memory region to allocate (phys address) + * @end: the upper bound of the memory region to allocate (phys address) + * @nid: nid of the free area to find, %NUMA_NO_NODE for any node + * + * The allocation is performed from memory region limited by + * memblock.current_limit if @max_addr == %MEMBLOCK_ALLOC_ACCESSIBLE. + * + * If the specified node can not hold the requested memory the + * allocation falls back to any node in the system + * + * For systems with memory mirroring, the allocation is attempted first + * from the regions with mirroring enabled and then retried from any + * memory region. + * + * In addition, function sets the min_count to 0 using kmemleak_alloc_phys for + * allocated boot memory block, so that it is never reported as leaks. + * + * Return: + * Physical address of allocated memory block on success, %0 on failure. + */ static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size, phys_addr_t align, phys_addr_t start, - phys_addr_t end, int nid, - enum memblock_flags flags) + phys_addr_t end, int nid) { + enum memblock_flags flags = choose_memblock_flags(); phys_addr_t found; + if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n")) + nid = NUMA_NO_NODE; + if (!align) { /* Can't use WARNs this early in boot on powerpc */ dump_stack(); align = SMP_CACHE_BYTES; } + if (end > memblock.current_limit) + end = memblock.current_limit; + +again: found = memblock_find_in_range_node(size, align, start, end, nid, flags); - if (found && !memblock_reserve(found, size)) { + if (found && !membloc
[PATCH 08/21] memblock: drop __memblock_alloc_base()
The __memblock_alloc_base() function tries to allocate a memory up to the limit specified by its max_addr parameter. Depending on the value of this parameter, the __memblock_alloc_base() can is replaced with the appropriate memblock_phys_alloc*() variant. Signed-off-by: Mike Rapoport --- arch/sh/kernel/machine_kexec.c | 3 ++- arch/x86/kernel/e820.c | 2 +- arch/x86/mm/numa.c | 12 drivers/of/of_reserved_mem.c | 7 ++- include/linux/memblock.h | 2 -- mm/memblock.c | 9 ++--- 6 files changed, 11 insertions(+), 24 deletions(-) diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index b9f9f1a..63d63a3 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -168,7 +168,8 @@ void __init reserve_crashkernel(void) crash_size = PAGE_ALIGN(resource_size(&crashk_res)); if (!crashk_res.start) { unsigned long max = memblock_end_of_DRAM() - memory_limit; - crashk_res.start = __memblock_alloc_base(crash_size, PAGE_SIZE, max); + crashk_res.start = memblock_phys_alloc_range(crash_size, +PAGE_SIZE, 0, max); if (!crashk_res.start) { pr_err("crashkernel allocation failed\n"); goto disable; diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 50895c2..9c0eb54 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -778,7 +778,7 @@ u64 __init e820__memblock_alloc_reserved(u64 size, u64 align) { u64 addr; - addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE); + addr = memblock_phys_alloc(size, align); if (addr) { e820__range_update_kexec(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED); pr_info("update e820_table_kexec for e820__memblock_alloc_reserved()\n"); diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 1308f54..f85ae42 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -195,15 +195,11 @@ static void __init alloc_node_data(int nid) * Allocate node data. Try node-local memory and then any node. * Never allocate in DMA zone. */ - nd_pa = memblock_phys_alloc_nid(nd_size, SMP_CACHE_BYTES, nid); + nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); if (!nd_pa) { - nd_pa = __memblock_alloc_base(nd_size, SMP_CACHE_BYTES, - MEMBLOCK_ALLOC_ACCESSIBLE); - if (!nd_pa) { - pr_err("Cannot find %zu bytes in any node (initial node: %d)\n", - nd_size, nid); - return; - } + pr_err("Cannot find %zu bytes in any node (initial node: %d)\n", + nd_size, nid); + return; } nd = __va(nd_pa); diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 1977ee0..499f16d 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -31,13 +31,10 @@ int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, phys_addr_t *res_base) { phys_addr_t base; - /* -* We use __memblock_alloc_base() because memblock_alloc_base() -* panic()s on allocation failure. -*/ + end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end; align = !align ? SMP_CACHE_BYTES : align; - base = __memblock_alloc_base(size, align, end); + base = memblock_phys_alloc_range(size, align, 0, end); if (!base) return -ENOMEM; diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 7883c74..768e2b4 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -496,8 +496,6 @@ static inline bool memblock_bottom_up(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_reserved_size(void); phys_addr_t memblock_mem_size(unsigned long limit_pfn); diff --git a/mm/memblock.c b/mm/memblock.c index 461e40a3..e5ffdcd 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1363,17 +1363,12 @@ phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, return ret; } -phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr) -{ - return memblock_alloc_range_nid(size, align, 0, max_addr, NUMA_NO_NODE, - MEMBLOCK_NONE); -} - phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align,
[PATCH 12/21] arch: use memblock_alloc() instead of memblock_alloc_from(size, align, 0)
The last parameter of memblock_alloc_from() is the lower limit for the memory allocation. When it is 0, the call is equivalent to memblock_alloc(). Signed-off-by: Mike Rapoport --- arch/alpha/kernel/core_cia.c | 2 +- arch/alpha/kernel/pci_iommu.c | 4 ++-- arch/alpha/kernel/setup.c | 2 +- arch/ia64/kernel/mca.c| 3 +-- arch/mips/kernel/traps.c | 2 +- arch/sparc/kernel/prom_32.c | 2 +- arch/sparc/mm/init_32.c | 2 +- arch/sparc/mm/srmmu.c | 10 +- 8 files changed, 13 insertions(+), 14 deletions(-) diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c index 867e873..466cd44 100644 --- a/arch/alpha/kernel/core_cia.c +++ b/arch/alpha/kernel/core_cia.c @@ -331,7 +331,7 @@ cia_prepare_tbia_workaround(int window) long i; /* Use minimal 1K map. */ - ppte = memblock_alloc_from(CIA_BROKEN_TBIA_SIZE, 32768, 0); + ppte = memblock_alloc(CIA_BROKEN_TBIA_SIZE, 32768); pte = (virt_to_phys(ppte) >> (PAGE_SHIFT - 1)) | 1; for (i = 0; i < CIA_BROKEN_TBIA_SIZE / sizeof(unsigned long); ++i) diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index aa0f50d..e4cf77b 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -87,13 +87,13 @@ iommu_arena_new_node(int nid, struct pci_controller *hose, dma_addr_t base, printk("%s: couldn't allocate arena ptes from node %d\n" "falling back to system-wide allocation\n", __func__, nid); - arena->ptes = memblock_alloc_from(mem_size, align, 0); + arena->ptes = memblock_alloc(mem_size, align); } #else /* CONFIG_DISCONTIGMEM */ arena = memblock_alloc(sizeof(*arena), SMP_CACHE_BYTES); - arena->ptes = memblock_alloc_from(mem_size, align, 0); + arena->ptes = memblock_alloc(mem_size, align); #endif /* CONFIG_DISCONTIGMEM */ diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 4b5b1b2..5d4c76a 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -293,7 +293,7 @@ move_initrd(unsigned long mem_limit) unsigned long size; size = initrd_end - initrd_start; - start = memblock_alloc_from(PAGE_ALIGN(size), PAGE_SIZE, 0); + start = memblock_alloc(PAGE_ALIGN(size), PAGE_SIZE); if (!start || __pa(start) + size > mem_limit) { initrd_start = initrd_end = 0; return NULL; diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 91bd1e1..74d148b 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -1835,8 +1835,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset, /* Caller prevents this from being called after init */ static void * __ref mca_bootmem(void) { - return memblock_alloc_from(sizeof(struct ia64_mca_cpu), - KERNEL_STACK_SIZE, 0); + return memblock_alloc(sizeof(struct ia64_mca_cpu), KERNEL_STACK_SIZE); } /* Do per-CPU MCA-related initialization. */ diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index c91097f..2bbdee5 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -2291,7 +2291,7 @@ void __init trap_init(void) phys_addr_t ebase_pa; ebase = (unsigned long) - memblock_alloc_from(size, 1 << fls(size), 0); + memblock_alloc(size, 1 << fls(size)); /* * Try to ensure ebase resides in KSeg0 if possible. diff --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c index 42d7f2a..38940af 100644 --- a/arch/sparc/kernel/prom_32.c +++ b/arch/sparc/kernel/prom_32.c @@ -32,7 +32,7 @@ void * __init prom_early_alloc(unsigned long size) { void *ret; - ret = memblock_alloc_from(size, SMP_CACHE_BYTES, 0UL); + ret = memblock_alloc(size, SMP_CACHE_BYTES); if (ret != NULL) memset(ret, 0, size); diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c index d900952..a8ff298 100644 --- a/arch/sparc/mm/init_32.c +++ b/arch/sparc/mm/init_32.c @@ -264,7 +264,7 @@ void __init mem_init(void) i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5); i += 1; sparc_valid_addr_bitmap = (unsigned long *) - memblock_alloc_from(i << 2, SMP_CACHE_BYTES, 0UL); + memblock_alloc(i << 2, SMP_CACHE_BYTES); if (sparc_valid_addr_bitmap == NULL) { prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n"); diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index b609362..a400ec3 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -303,13 +303,13 @@ static void __init srmmu_nocache_init(void) bitmap_bits = srmmu_nocache_size >> SR
[PATCH 05/21] memblock: emphasize that memblock_alloc_range() returns a physical address
Rename memblock_alloc_range() to memblock_phys_alloc_range() to emphasize that it returns a physical address. While on it, remove the 'enum memblock_flags' parameter from this function as its only user anyway sets it to MEMBLOCK_NONE, which is the default for the most of memblock allocations. Signed-off-by: Mike Rapoport --- include/linux/memblock.h | 5 ++--- mm/cma.c | 10 -- mm/memblock.c| 9 + 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index f7ef313..66dfdb3 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -369,6 +369,8 @@ static inline int memblock_get_region_node(const struct memblock_region *r) #define ARCH_LOW_ADDRESS_LIMIT 0xUL #endif +phys_addr_t memblock_phys_alloc_range(phys_addr_t size, phys_addr_t align, + phys_addr_t start, phys_addr_t end); phys_addr_t memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, int nid); phys_addr_t memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid); @@ -487,9 +489,6 @@ static inline bool memblock_bottom_up(void) return memblock.bottom_up; } -phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align, - phys_addr_t start, phys_addr_t end, - enum memblock_flags flags); 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, diff --git a/mm/cma.c b/mm/cma.c index c7b39dd..e4530ae 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -327,16 +327,14 @@ int __init cma_declare_contiguous(phys_addr_t base, * memory in case of failure. */ if (base < highmem_start && limit > highmem_start) { - addr = memblock_alloc_range(size, alignment, - highmem_start, limit, - MEMBLOCK_NONE); + addr = memblock_phys_alloc_range(size, alignment, +highmem_start, limit); limit = highmem_start; } if (!addr) { - addr = memblock_alloc_range(size, alignment, base, - limit, - MEMBLOCK_NONE); + addr = memblock_phys_alloc_range(size, alignment, base, +limit); if (!addr) { ret = -ENOMEM; goto err; diff --git a/mm/memblock.c b/mm/memblock.c index c80029e..f019aee 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1338,12 +1338,13 @@ static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size, return 0; } -phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align, - phys_addr_t start, phys_addr_t end, - enum memblock_flags flags) +phys_addr_t __init memblock_phys_alloc_range(phys_addr_t size, +phys_addr_t align, +phys_addr_t start, +phys_addr_t end) { return memblock_alloc_range_nid(size, align, start, end, NUMA_NO_NODE, - flags); + MEMBLOCK_NONE); } phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, int nid) -- 2.7.4
[PATCH 07/21] memblock: memblock_phys_alloc(): don't panic
Make the memblock_phys_alloc() function an inline wrapper for memblock_phys_alloc_range() and update the memblock_phys_alloc() callers to check the returned value and panic in case of error. Signed-off-by: Mike Rapoport --- arch/arm/mm/init.c | 4 arch/arm64/mm/mmu.c | 2 ++ arch/powerpc/sysdev/dart_iommu.c | 3 +++ arch/s390/kernel/crash_dump.c| 3 +++ arch/s390/kernel/setup.c | 3 +++ arch/sh/boards/mach-ap325rxa/setup.c | 3 +++ arch/sh/boards/mach-ecovec24/setup.c | 6 ++ arch/sh/boards/mach-kfr2r09/setup.c | 3 +++ arch/sh/boards/mach-migor/setup.c| 3 +++ arch/sh/boards/mach-se/7724/setup.c | 6 ++ arch/xtensa/mm/kasan_init.c | 3 +++ include/linux/memblock.h | 7 ++- mm/memblock.c| 5 - 13 files changed, 45 insertions(+), 6 deletions(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index b76b90e..15dddfe 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -206,6 +206,10 @@ phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align) BUG_ON(!arm_memblock_steal_permitted); phys = memblock_phys_alloc(size, align); + if (!phys) + panic("Failed to steal %pa bytes at %pS\n", + &size, (void *)_RET_IP_); + memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index b6f5aa5..a74e4be 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -104,6 +104,8 @@ static phys_addr_t __init early_pgtable_alloc(void) void *ptr; phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); + if (!phys) + panic("Failed to allocate page table page\n"); /* * The FIX_{PGD,PUD,PMD} slots may be in active use, but the FIX_PTE diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 25bc25f..b82c9ff 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -265,6 +265,9 @@ static void allocate_dart(void) * prefetching into invalid pages and corrupting data */ tmp = memblock_phys_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE); + if (!tmp) + panic("DART: table allocation failed\n"); + dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & DARTMAP_RPNMASK); diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 97eae38..f96a585 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -61,6 +61,9 @@ struct save_area * __init save_area_alloc(bool is_boot_cpu) struct save_area *sa; sa = (void *) memblock_phys_alloc(sizeof(*sa), 8); + if (!sa) + panic("Failed to allocate save area\n"); + if (is_boot_cpu) list_add(&sa->list, &dump_save_areas); else diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 72dd23e..da48397 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -968,6 +968,9 @@ static void __init setup_randomness(void) vmms = (struct sysinfo_3_2_2 *) memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); + if (!vmms) + panic("Failed to allocate memory for sysinfo structure\n"); + if (stsi(vmms, 3, 2, 2) == 0 && vmms->count) add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count); memblock_free((unsigned long) vmms, PAGE_SIZE); diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index d7ceab6..08a0cc9 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -558,6 +558,9 @@ static void __init ap325rxa_mv_mem_reserve(void) phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; phys = memblock_phys_alloc(size, PAGE_SIZE); + if (!phys) + panic("Failed to allocate CEU memory\n"); + memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index a3901806..fd264a6 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -1481,11 +1481,17 @@ static void __init ecovec_mv_mem_reserve(void) phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; phys = memblock_phys_alloc(size, PAGE_SIZE); + if (!phys) + panic("Failed to allocate CEU0 memory\n"); + memblock_free(phys, size); memblock_remove(phys, size); ceu0_dma_membase = phys; phys = memblock_phys_alloc(size, PAGE_SIZE); + if (!phys) + panic("Failed to allocate CEU1 memory\
[PATCH 02/21] powerpc: use memblock functions returning virtual address
From: Christophe Leroy Since only the virtual address of allocated blocks is used, lets use functions returning directly virtual address. Those functions have the advantage of also zeroing the block. [ MR: - updated error message in alloc_stack() to be more verbose - convereted several additional call sites ] Signed-off-by: Christophe Leroy Signed-off-by: Mike Rapoport --- arch/powerpc/kernel/dt_cpu_ftrs.c | 3 +-- arch/powerpc/kernel/irq.c | 5 - arch/powerpc/kernel/paca.c| 6 +- arch/powerpc/kernel/prom.c| 5 - arch/powerpc/kernel/setup_32.c| 26 -- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c index 8be3721..2554824 100644 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c @@ -813,7 +813,6 @@ static int __init process_cpufeatures_node(unsigned long node, int len; f = &dt_cpu_features[i]; - memset(f, 0, sizeof(struct dt_cpu_feature)); f->node = node; @@ -1008,7 +1007,7 @@ static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char /* Count and allocate space for cpu features */ of_scan_flat_dt_subnodes(node, count_cpufeatures_subnodes, &nr_dt_cpu_features); - dt_cpu_features = __va(memblock_phys_alloc(sizeof(struct dt_cpu_feature) * nr_dt_cpu_features, PAGE_SIZE)); + dt_cpu_features = memblock_alloc(sizeof(struct dt_cpu_feature) * nr_dt_cpu_features, PAGE_SIZE); cpufeatures_setup_start(isa); diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 916ddc4..4a44bc3 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -725,18 +725,15 @@ void exc_lvl_ctx_init(void) #endif #endif - memset((void *)critirq_ctx[cpu_nr], 0, THREAD_SIZE); tp = critirq_ctx[cpu_nr]; tp->cpu = cpu_nr; tp->preempt_count = 0; #ifdef CONFIG_BOOKE - memset((void *)dbgirq_ctx[cpu_nr], 0, THREAD_SIZE); tp = dbgirq_ctx[cpu_nr]; tp->cpu = cpu_nr; tp->preempt_count = 0; - memset((void *)mcheckirq_ctx[cpu_nr], 0, THREAD_SIZE); tp = mcheckirq_ctx[cpu_nr]; tp->cpu = cpu_nr; tp->preempt_count = HARDIRQ_OFFSET; @@ -754,12 +751,10 @@ void irq_ctx_init(void) int i; for_each_possible_cpu(i) { - memset((void *)softirq_ctx[i], 0, THREAD_SIZE); tp = softirq_ctx[i]; tp->cpu = i; klp_init_thread_info(tp); - memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); tp = hardirq_ctx[i]; tp->cpu = i; klp_init_thread_info(tp); diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 8c890c6..e7382ab 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c @@ -196,7 +196,11 @@ void __init allocate_paca_ptrs(void) paca_nr_cpu_ids = nr_cpu_ids; paca_ptrs_size = sizeof(struct paca_struct *) * nr_cpu_ids; - paca_ptrs = __va(memblock_phys_alloc(paca_ptrs_size, SMP_CACHE_BYTES)); + paca_ptrs = memblock_alloc_raw(paca_ptrs_size, SMP_CACHE_BYTES); + if (!paca_ptrs) + panic("Failed to allocate %d bytes for paca pointers\n", + paca_ptrs_size); + memset(paca_ptrs, 0x88, paca_ptrs_size); } diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index e97aaf2..c0ed4fa 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -127,7 +127,10 @@ static void __init move_device_tree(void) if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) || !memblock_is_memory(start + size - 1) || overlaps_crashkernel(start, size) || overlaps_initrd(start, size)) { - p = __va(memblock_phys_alloc(size, PAGE_SIZE)); + p = memblock_alloc_raw(size, PAGE_SIZE); + if (!p) + panic("Failed to allocate %lu bytes to move device tree\n", + size); memcpy(p, initial_boot_params, size); initial_boot_params = p; DBG("Moved device tree to 0x%px\n", p); diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 947f904..1f0b762 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -196,6 +196,17 @@ static int __init ppc_init(void) } arch_initcall(ppc_init); +static void *__init alloc_stack(void) +{ + void *ptr = memblock_alloc(THREAD_SIZE, THREAD_SIZE); + + if (!ptr) + panic("cannot allocate %d bytes for stack at %
[PATCH 00/21] Refine memblock API
Hi, Current memblock API is quite extensive and, which is more annoying, duplicated. Except the low-level functions that allow searching for a free memory region and marking it as reserved, memblock provides three (well, two and a half) sets of functions to allocate memory. There are several overlapping functions that return a physical address and there are functions that return virtual address. Those that return the virtual address may also clear the allocated memory. And, on top of all that, some allocators panic and some return NULL in case of error. This set tries to reduce the mess, and trim down the amount of memblock allocation methods. Patches 1-10 consolidate the functions that return physical address of the allocated memory Patches 11-13 are some trivial cleanups Patches 14-19 add checks for the return value of memblock_alloc*() and panics in case of errors. The patches 14-18 include some minor refactoring to have better readability of the resulting code and patch 19 is a mechanical addition of if (!ptr) panic(); after memblock_alloc*() calls. And, finally, patches 20 and 21 remove panic() calls memblock and _nopanic variants from memblock. Christophe Leroy (1): powerpc: use memblock functions returning virtual address Mike Rapoport (20): openrisc: prefer memblock APIs returning virtual address memblock: replace memblock_alloc_base(ANYWHERE) with memblock_phys_alloc memblock: drop memblock_alloc_base_nid() memblock: emphasize that memblock_alloc_range() returns a physical address memblock: memblock_phys_alloc_try_nid(): don't panic memblock: memblock_phys_alloc(): don't panic memblock: drop __memblock_alloc_base() memblock: drop memblock_alloc_base() memblock: refactor internal allocation functions memblock: make memblock_find_in_range_node() and choose_memblock_flags() static arch: use memblock_alloc() instead of memblock_alloc_from(size, align, 0) arch: don't memset(0) memory returned by memblock_alloc() ia64: add checks for the return value of memblock_alloc*() sparc: add checks for the return value of memblock_alloc*() mm/percpu: add checks for the return value of memblock_alloc*() init/main: add checks for the return value of memblock_alloc*() swiotlb: add checks for the return value of memblock_alloc*() treewide: add checks for the return value of memblock_alloc*() memblock: memblock_alloc_try_nid: don't panic memblock: drop memblock_alloc_*_nopanic() variants arch/alpha/kernel/core_cia.c | 5 +- arch/alpha/kernel/core_marvel.c | 6 + arch/alpha/kernel/pci-noop.c | 11 +- arch/alpha/kernel/pci.c | 11 +- arch/alpha/kernel/pci_iommu.c | 16 +- arch/alpha/kernel/setup.c | 2 +- arch/arc/kernel/unwind.c | 3 +- arch/arc/mm/highmem.c | 4 + arch/arm/kernel/setup.c | 6 + arch/arm/mm/init.c| 6 +- arch/arm/mm/mmu.c | 14 +- arch/arm64/kernel/setup.c | 9 +- arch/arm64/mm/kasan_init.c| 10 ++ arch/arm64/mm/mmu.c | 2 + arch/arm64/mm/numa.c | 4 + arch/c6x/mm/dma-coherent.c| 4 + arch/c6x/mm/init.c| 4 +- arch/csky/mm/highmem.c| 5 + arch/h8300/mm/init.c | 4 +- arch/ia64/kernel/mca.c| 25 +-- arch/ia64/mm/contig.c | 8 +- arch/ia64/mm/discontig.c | 4 + arch/ia64/mm/init.c | 38 - arch/ia64/mm/tlb.c| 6 + arch/ia64/sn/kernel/io_common.c | 3 + arch/ia64/sn/kernel/setup.c | 12 +- arch/m68k/atari/stram.c | 4 + arch/m68k/mm/init.c | 3 + arch/m68k/mm/mcfmmu.c | 7 +- arch/m68k/mm/motorola.c | 9 ++ arch/m68k/mm/sun3mmu.c| 6 + arch/m68k/sun3/sun3dvma.c | 3 + arch/microblaze/mm/init.c | 10 +- arch/mips/cavium-octeon/dma-octeon.c | 3 + arch/mips/kernel/setup.c | 3 + arch/mips/kernel/traps.c | 5 +- arch/mips/mm/init.c | 5 + arch/nds32/mm/init.c | 12 ++ arch/openrisc/mm/init.c | 5 +- arch/openrisc/mm/ioremap.c| 8 +- arch/powerpc/kernel/dt_cpu_ftrs.c | 8 +- arch/powerpc/kernel/irq.c | 5 - arch/powerpc/kernel/paca.c| 6 +- arch/powerpc/kernel/pci_32.c | 3 + arch/powerpc/kernel/prom.c| 5 +- arch/powerpc/kernel/rtas.c| 6 +- arch/powerpc/kernel/setup-common.c| 3 + arch/powerpc/kernel/setup_32.c| 2
[PATCH 03/21] memblock: replace memblock_alloc_base(ANYWHERE) with memblock_phys_alloc
The calls to memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE) and memblock_phys_alloc(size, align) are equivalent as both try to allocate 'size' bytes with 'align' alignment anywhere in the memory and panic if hte allocation fails. The conversion is done using the following semantic patch: @@ expression size, align; @@ - memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE) + memblock_phys_alloc(size, align) Signed-off-by: Mike Rapoport --- arch/arm/mm/init.c | 2 +- arch/sh/boards/mach-ap325rxa/setup.c | 2 +- arch/sh/boards/mach-ecovec24/setup.c | 4 ++-- arch/sh/boards/mach-kfr2r09/setup.c | 2 +- arch/sh/boards/mach-migor/setup.c| 2 +- arch/sh/boards/mach-se/7724/setup.c | 4 ++-- arch/xtensa/mm/kasan_init.c | 3 +-- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 478ea8b..b76b90e 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -205,7 +205,7 @@ phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align) BUG_ON(!arm_memblock_steal_permitted); - phys = memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, align); memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index 8f234d04..d7ceab6 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -557,7 +557,7 @@ static void __init ap325rxa_mv_mem_reserve(void) phys_addr_t phys; phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 22b4106..a3901806 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -1480,12 +1480,12 @@ static void __init ecovec_mv_mem_reserve(void) phys_addr_t phys; phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); ceu0_dma_membase = phys; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); ceu1_dma_membase = phys; diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 203d249..55bdf4a 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -631,7 +631,7 @@ static void __init kfr2r09_mv_mem_reserve(void) phys_addr_t phys; phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index f4ad33c..ba7eee6 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -630,7 +630,7 @@ static void __init migor_mv_mem_reserve(void) phys_addr_t phys; phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index fdbec22a..4696e10 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -965,12 +965,12 @@ static void __init ms7724se_mv_mem_reserve(void) phys_addr_t phys; phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); ceu0_dma_membase = phys; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); ceu1_dma_membase = phys; diff --git a/arch/xtensa/mm/kasan_init.c b/arch/xtensa/mm/kasan_init.c index 1734cda..48dbb03 100644 --- a/arch/xtensa/mm/kasan_init.c +++ b/arch/xtensa/mm/kasan_init.c @@ -52,8 +52,7 @@ static void __init populate(void *start, void *end) for (k = 0; k < PTRS_PER_PTE; ++k, ++j) {
[PATCH v2 01/21] openrisc: prefer memblock APIs returning virtual address
The allocation of the page tables memory in openrics uses memblock_phys_alloc() and then converts the returned physical address to virtual one. Use memblock_alloc_raw() and add a panic() if the allocation fails. Signed-off-by: Mike Rapoport --- arch/openrisc/mm/init.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c index d157310..caeb418 100644 --- a/arch/openrisc/mm/init.c +++ b/arch/openrisc/mm/init.c @@ -105,7 +105,10 @@ static void __init map_ram(void) } /* Alloc one page for holding PTE's... */ - pte = (pte_t *) __va(memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE)); + pte = memblock_alloc_raw(PAGE_SIZE, PAGE_SIZE); + if (!pte) + panic("%s: Failed to allocate page for PTEs\n", + __func__); set_pmd(pme, __pmd(_KERNPG_TABLE + __pa(pte))); /* Fill the newly allocated page with PTE'S */ -- 2.7.4
[PATCH v2 03/21] memblock: replace memblock_alloc_base(ANYWHERE) with memblock_phys_alloc
The calls to memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE) and memblock_phys_alloc(size, align) are equivalent as both try to allocate 'size' bytes with 'align' alignment anywhere in the memory and panic if hte allocation fails. The conversion is done using the following semantic patch: @@ expression size, align; @@ - memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE) + memblock_phys_alloc(size, align) Signed-off-by: Mike Rapoport --- arch/arm/mm/init.c | 2 +- arch/sh/boards/mach-ap325rxa/setup.c | 2 +- arch/sh/boards/mach-ecovec24/setup.c | 4 ++-- arch/sh/boards/mach-kfr2r09/setup.c | 2 +- arch/sh/boards/mach-migor/setup.c| 2 +- arch/sh/boards/mach-se/7724/setup.c | 4 ++-- arch/xtensa/mm/kasan_init.c | 3 +-- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 478ea8b..b76b90e 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -205,7 +205,7 @@ phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align) BUG_ON(!arm_memblock_steal_permitted); - phys = memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, align); memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index 8f234d04..d7ceab6 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -557,7 +557,7 @@ static void __init ap325rxa_mv_mem_reserve(void) phys_addr_t phys; phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 22b4106..a3901806 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -1480,12 +1480,12 @@ static void __init ecovec_mv_mem_reserve(void) phys_addr_t phys; phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); ceu0_dma_membase = phys; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); ceu1_dma_membase = phys; diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 203d249..55bdf4a 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -631,7 +631,7 @@ static void __init kfr2r09_mv_mem_reserve(void) phys_addr_t phys; phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index f4ad33c..ba7eee6 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -630,7 +630,7 @@ static void __init migor_mv_mem_reserve(void) phys_addr_t phys; phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index fdbec22a..4696e10 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -965,12 +965,12 @@ static void __init ms7724se_mv_mem_reserve(void) phys_addr_t phys; phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); ceu0_dma_membase = phys; - phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE); + phys = memblock_phys_alloc(size, PAGE_SIZE); memblock_free(phys, size); memblock_remove(phys, size); ceu1_dma_membase = phys; diff --git a/arch/xtensa/mm/kasan_init.c b/arch/xtensa/mm/kasan_init.c index 1734cda..48dbb03 100644 --- a/arch/xtensa/mm/kasan_init.c +++ b/arch/xtensa/mm/kasan_init.c @@ -52,8 +52,7 @@ static void __init populate(void *start, void *end) for (k = 0; k < PTRS_PER_PTE; ++k, ++j) {
[PATCH v2 09/21] memblock: drop memblock_alloc_base()
The memblock_alloc_base() function tries to allocate a memory up to the limit specified by its max_addr parameter and panics if the allocation fails. Replace its usage with memblock_phys_alloc_range() and make the callers check the return value and panic in case of error. Signed-off-by: Mike Rapoport --- arch/powerpc/kernel/rtas.c | 6 +- arch/powerpc/mm/hash_utils_64.c | 8 ++-- arch/s390/kernel/smp.c | 6 +- drivers/macintosh/smu.c | 2 +- include/linux/memblock.h| 2 -- mm/memblock.c | 14 -- 6 files changed, 17 insertions(+), 21 deletions(-) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index de35bd8f..fbc6761 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -1187,7 +1187,11 @@ void __init rtas_initialize(void) ibm_suspend_me_token = rtas_token("ibm,suspend-me"); } #endif - rtas_rmo_buf = memblock_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); + rtas_rmo_buf = memblock_phys_alloc_range(RTAS_RMOBUF_MAX, PAGE_SIZE, +0, rtas_region); + if (!rtas_rmo_buf) + panic("ERROR: RTAS: Failed to allocate %lx bytes below %pa\n", + PAGE_SIZE, &rtas_region); #ifdef CONFIG_RTAS_ERROR_LOGGING rtas_last_error_token = rtas_token("rtas-last-error"); diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index bc6be44..c7d5f48 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -882,8 +882,12 @@ static void __init htab_initialize(void) } #endif /* CONFIG_PPC_CELL */ - table = memblock_alloc_base(htab_size_bytes, htab_size_bytes, - limit); + table = memblock_phys_alloc_range(htab_size_bytes, + htab_size_bytes, + 0, limit); + if (!table) + panic("ERROR: Failed to allocate %pa bytes below %pa\n", + &htab_size_bytes, &limit); DBG("Hash table allocated at %lx, size: %lx\n", table, htab_size_bytes); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index f82b3d3..9061597 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -651,7 +651,11 @@ void __init smp_save_dump_cpus(void) /* No previous system present, normal boot. */ return; /* Allocate a page as dumping area for the store status sigps */ - page = memblock_alloc_base(PAGE_SIZE, PAGE_SIZE, 1UL << 31); + page = memblock_phys_alloc_range(PAGE_SIZE, PAGE_SIZE, 0, 1UL << 31); + if (!page) + panic("ERROR: Failed to allocate %x bytes below %lx\n", + PAGE_SIZE, 1UL << 31); + /* Set multi-threading state to the previous system. */ pcpu_set_smt(sclp.mtid_prev); boot_cpu_addr = stap(); diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 0a0b8e1..42cf68d 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -485,7 +485,7 @@ int __init smu_init (void) * SMU based G5s need some memory below 2Gb. Thankfully this is * called at a time where memblock is still available. */ - smu_cmdbuf_abs = memblock_alloc_base(4096, 4096, 0x8000UL); + smu_cmdbuf_abs = memblock_phys_alloc_range(4096, 4096, 0, 0x8000UL); if (smu_cmdbuf_abs == 0) { printk(KERN_ERR "SMU: Command buffer allocation failed !\n"); ret = -EINVAL; diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 768e2b4..6874fdc 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -494,8 +494,6 @@ static inline bool memblock_bottom_up(void) return memblock.bottom_up; } -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_reserved_size(void); phys_addr_t memblock_mem_size(unsigned long limit_pfn); diff --git a/mm/memblock.c b/mm/memblock.c index e5ffdcd..531fa77 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1363,20 +1363,6 @@ phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, return ret; } -phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr) -{ - phys_addr_t alloc; - - alloc = memblock_alloc_range_nid(size, align, 0, max_addr, NUMA_NO_NODE, - MEMBLOCK_NONE); - - if (alloc == 0) - panic("ERROR: Failed to allocate %pa bytes
[PATCH v2 14/21] ia64: add checks for the return value of memblock_alloc*()
Add panic() calls if memblock_alloc*() returns NULL. Most of the changes are simply addition of if(!ptr) panic(); statements after the calls to memblock_alloc*() variants. Exceptions are create_mem_map_page_table() and ia64_log_init() that were slightly refactored to accommodate the change. Signed-off-by: Mike Rapoport --- arch/ia64/kernel/mca.c | 20 ++-- arch/ia64/mm/contig.c | 8 ++-- arch/ia64/mm/discontig.c| 4 arch/ia64/mm/init.c | 38 ++ arch/ia64/mm/tlb.c | 6 ++ arch/ia64/sn/kernel/io_common.c | 3 +++ arch/ia64/sn/kernel/setup.c | 12 +++- 7 files changed, 74 insertions(+), 17 deletions(-) diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 370bc34..5cabb3f 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -359,11 +359,6 @@ typedef struct ia64_state_log_s static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES]; -#define IA64_LOG_ALLOCATE(it, size) \ - {ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \ - (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES); \ - ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \ - (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES);} #define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock) #define IA64_LOG_LOCK(it) spin_lock_irqsave(&ia64_state_log[it].isl_lock, s) #define IA64_LOG_UNLOCK(it) spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s) @@ -378,6 +373,19 @@ static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES]; #define IA64_LOG_CURR_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)])) #define IA64_LOG_COUNT(it) ia64_state_log[it].isl_count +static inline void ia64_log_allocate(int it, u64 size) +{ + ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = + (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES); + if (!ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)]) + panic("%s: Failed to allocate %llu bytes\n", __func__, size); + + ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = + (ia64_err_rec_t *)memblock_alloc(size, SMP_CACHE_BYTES); + if (!ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)]) + panic("%s: Failed to allocate %llu bytes\n", __func__, size); +} + /* * ia64_log_init * Reset the OS ia64 log buffer @@ -399,7 +407,7 @@ ia64_log_init(int sal_info_type) return; // set up OS data structures to hold error info - IA64_LOG_ALLOCATE(sal_info_type, max_size); + ia64_log_allocate(sal_info_type, max_size); } /* diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index 6e44723..d29fb6b 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -84,9 +84,13 @@ void *per_cpu_init(void) static inline void alloc_per_cpu_data(void) { - cpu_data = memblock_alloc_from(PERCPU_PAGE_SIZE * num_possible_cpus(), - PERCPU_PAGE_SIZE, + size_t size = PERCPU_PAGE_SIZE * num_possible_cpus(); + + cpu_data = memblock_alloc_from(size, PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); + if (!cpu_data) + panic("%s: Failed to allocate %lu bytes align=%lx from=%lx\n", + __func__, size, PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); } /** diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index f9c3675..05490dd 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -454,6 +454,10 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize) __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, bestnode); + if (!ptr) + panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d from=%lx\n", + __func__, pernodesize, PERCPU_PAGE_SIZE, bestnode, + __pa(MAX_DMA_ADDRESS)); return ptr; } diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 29d8415..e49200e 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -444,23 +444,45 @@ int __init create_mem_map_page_table(u64 start, u64 end, void *arg) for (address = start_page; address < end_page; address += PAGE_SIZE) { pgd = pgd_offset_k(address); - if (pgd_none(*pgd)) - pgd_populate(&init_mm, pgd, memblock_alloc_node(PAGE_SIZE, PAGE_SIZE, node)); + if (pgd_none(*pgd)) { + pud = memblock_alloc_node(PAGE_SIZE, PAGE_SIZE, node); + if (!pud) + goto err_all
[PATCH v2 19/21] treewide: add checks for the return value of memblock_alloc*()
Add check for the return value of memblock_alloc*() functions and call panic() in case of error. The panic message repeats the one used by panicing memblock allocators with adjustment of parameters to include only relevant ones. The replacement was mostly automated with semantic patches like the one below with manual massaging of format strings. @@ expression ptr, size, align; @@ ptr = memblock_alloc(size, align); + if (!ptr) + panic("%s: Failed to allocate %lu bytes align=0x%lx\n", __func__, size, align); Signed-off-by: Mike Rapoport Reviewed-by: Guo Ren # c-sky Acked-by: Paul Burton # MIPS Acked-by: Heiko Carstens # s390 Reviewed-by: Juergen Gross # Xen --- arch/alpha/kernel/core_cia.c | 3 +++ arch/alpha/kernel/core_marvel.c | 6 ++ arch/alpha/kernel/pci-noop.c | 13 +++-- arch/alpha/kernel/pci.c | 11 ++- arch/alpha/kernel/pci_iommu.c | 12 arch/arc/mm/highmem.c | 4 arch/arm/kernel/setup.c | 6 ++ arch/arm/mm/mmu.c | 14 +- arch/arm64/kernel/setup.c | 8 +--- arch/arm64/mm/kasan_init.c| 10 ++ arch/c6x/mm/dma-coherent.c| 4 arch/c6x/mm/init.c| 3 +++ arch/csky/mm/highmem.c| 5 + arch/h8300/mm/init.c | 3 +++ arch/m68k/atari/stram.c | 4 arch/m68k/mm/init.c | 3 +++ arch/m68k/mm/mcfmmu.c | 6 ++ arch/m68k/mm/motorola.c | 9 + arch/m68k/mm/sun3mmu.c| 6 ++ arch/m68k/sun3/sun3dvma.c | 3 +++ arch/microblaze/mm/init.c | 8 ++-- arch/mips/cavium-octeon/dma-octeon.c | 3 +++ arch/mips/kernel/setup.c | 3 +++ arch/mips/kernel/traps.c | 3 +++ arch/mips/mm/init.c | 5 + arch/nds32/mm/init.c | 12 arch/openrisc/mm/ioremap.c| 8 ++-- arch/powerpc/kernel/dt_cpu_ftrs.c | 5 + arch/powerpc/kernel/pci_32.c | 3 +++ arch/powerpc/kernel/setup-common.c| 3 +++ arch/powerpc/kernel/setup_64.c| 4 arch/powerpc/lib/alloc.c | 3 +++ arch/powerpc/mm/hash_utils_64.c | 3 +++ arch/powerpc/mm/mmu_context_nohash.c | 9 + arch/powerpc/mm/pgtable-book3e.c | 12 ++-- arch/powerpc/mm/pgtable-book3s64.c| 3 +++ arch/powerpc/mm/pgtable-radix.c | 9 - arch/powerpc/mm/ppc_mmu_32.c | 3 +++ arch/powerpc/platforms/pasemi/iommu.c | 3 +++ arch/powerpc/platforms/powermac/nvram.c | 3 +++ arch/powerpc/platforms/powernv/opal.c | 3 +++ arch/powerpc/platforms/powernv/pci-ioda.c | 8 arch/powerpc/platforms/ps3/setup.c| 3 +++ arch/powerpc/sysdev/msi_bitmap.c | 3 +++ arch/s390/kernel/setup.c | 13 + arch/s390/kernel/smp.c| 5 - arch/s390/kernel/topology.c | 6 ++ arch/s390/numa/mode_emu.c | 3 +++ arch/s390/numa/numa.c | 6 +- arch/sh/mm/init.c | 6 ++ arch/sh/mm/numa.c | 4 arch/um/drivers/net_kern.c| 3 +++ arch/um/drivers/vector_kern.c | 3 +++ arch/um/kernel/initrd.c | 2 ++ arch/um/kernel/mem.c | 16 arch/unicore32/kernel/setup.c | 4 arch/unicore32/mm/mmu.c | 15 +-- arch/x86/kernel/acpi/boot.c | 3 +++ arch/x86/kernel/apic/io_apic.c| 5 + arch/x86/kernel/e820.c| 3 +++ arch/x86/platform/olpc/olpc_dt.c | 3 +++ arch/x86/xen/p2m.c| 11 +-- arch/xtensa/mm/kasan_init.c | 4 arch/xtensa/mm/mmu.c | 3 +++ drivers/clk/ti/clk.c | 3 +++ drivers/macintosh/smu.c | 3 +++ drivers/of/fdt.c | 8 +++- drivers/of/unittest.c | 8 +++- drivers/xen/swiotlb-xen.c | 7 +-- kernel/power/snapshot.c | 3 +++ lib/cpumask.c | 3 +++ mm/kasan/init.c | 10 -- mm/sparse.c | 19 +-- 73 files changed, 409 insertions(+), 28 deletions(-) diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c index 466cd44..f489170 100644 --- a/arch/alpha/kernel/core_cia.c +++ b/arch/alpha/kernel/core_cia.c @@ -33
[PATCH v2 20/21] memblock: memblock_alloc_try_nid: don't panic
As all the memblock_alloc*() users are now checking the return value and panic() in case of error, the panic() call can be removed from the core memblock allocator, namely memblock_alloc_try_nid(). Signed-off-by: Mike Rapoport --- mm/memblock.c | 15 +-- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/mm/memblock.c b/mm/memblock.c index 03b3929..7164275 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1526,7 +1526,7 @@ void * __init memblock_alloc_try_nid_nopanic( } /** - * memblock_alloc_try_nid - allocate boot memory block with panicking + * memblock_alloc_try_nid - allocate boot memory block * @size: size of memory block to be allocated in bytes * @align: alignment of the region and block's size * @min_addr: the lower bound of the memory region from where the allocation @@ -1536,9 +1536,8 @@ void * __init memblock_alloc_try_nid_nopanic( * allocate only from memory limited by memblock.current_limit value * @nid: nid of the free area to find, %NUMA_NO_NODE for any node * - * Public panicking version of memblock_alloc_try_nid_nopanic() - * which provides debug information (including caller info), if enabled, - * and panics if the request can not be satisfied. + * Public function, provides additional debug information (including caller + * info), if enabled. This function zeroes the allocated memory. * * Return: * Virtual address of allocated memory block on success, NULL on failure. @@ -1555,14 +1554,10 @@ void * __init memblock_alloc_try_nid( &max_addr, (void *)_RET_IP_); ptr = memblock_alloc_internal(size, align, min_addr, max_addr, nid); - if (ptr) { + if (ptr) memset(ptr, 0, size); - return ptr; - } - panic("%s: Failed to allocate %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa\n", - __func__, (u64)size, (u64)align, nid, &min_addr, &max_addr); - return NULL; + return ptr; } /** -- 2.7.4
[PATCH v2 06/21] memblock: memblock_phys_alloc_try_nid(): don't panic
The memblock_phys_alloc_try_nid() function tries to allocate memory from the requested node and then falls back to allocation from any node in the system. The memblock_alloc_base() fallback used by this function panics if the allocation fails. Replace the memblock_alloc_base() fallback with the direct call to memblock_alloc_range_nid() and update the memblock_phys_alloc_try_nid() callers to check the returned value and panic in case of error. Signed-off-by: Mike Rapoport --- arch/arm64/mm/numa.c | 4 arch/powerpc/mm/numa.c | 4 mm/memblock.c | 4 +++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index ae34e3a..2c61ea4 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -237,6 +237,10 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn) pr_info("Initmem setup node %d []\n", nid); nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); + if (!nd_pa) + panic("Cannot allocate %zu bytes for node %d data\n", + nd_size, nid); + nd = __va(nd_pa); /* report and initialize */ diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 270cefb..8f2bbe1 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -788,6 +788,10 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn) int tnid; nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); + if (!nd_pa) + panic("Cannot allocate %zu bytes for node %d data\n", + nd_size, nid); + nd = __va(nd_pa); /* report and initialize */ diff --git a/mm/memblock.c b/mm/memblock.c index f019aee..8aabb1b 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1393,7 +1393,9 @@ phys_addr_t __init memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t ali if (res) return res; - return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE); + return memblock_alloc_range_nid(size, align, 0, + MEMBLOCK_ALLOC_ACCESSIBLE, + NUMA_NO_NODE, MEMBLOCK_NONE); } /** -- 2.7.4
[PATCH v2 21/21] memblock: drop memblock_alloc_*_nopanic() variants
As all the memblock allocation functions return NULL in case of error rather than panic(), the duplicates with _nopanic suffix can be removed. Signed-off-by: Mike Rapoport Acked-by: Greg Kroah-Hartman --- arch/arc/kernel/unwind.c | 3 +-- arch/sh/mm/init.c | 2 +- arch/x86/kernel/setup_percpu.c | 10 +- arch/x86/mm/kasan_init_64.c| 14 -- drivers/firmware/memmap.c | 2 +- drivers/usb/early/xhci-dbc.c | 2 +- include/linux/memblock.h | 35 --- kernel/dma/swiotlb.c | 2 +- kernel/printk/printk.c | 9 + mm/memblock.c | 35 --- mm/page_alloc.c| 10 +- mm/page_ext.c | 2 +- mm/percpu.c| 11 --- mm/sparse.c| 6 ++ 14 files changed, 31 insertions(+), 112 deletions(-) diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c index d34f69e..271e9fa 100644 --- a/arch/arc/kernel/unwind.c +++ b/arch/arc/kernel/unwind.c @@ -181,8 +181,7 @@ static void init_unwind_hdr(struct unwind_table *table, */ static void *__init unw_hdr_alloc_early(unsigned long sz) { - return memblock_alloc_from_nopanic(sz, sizeof(unsigned int), - MAX_DMA_ADDRESS); + return memblock_alloc_from(sz, sizeof(unsigned int), MAX_DMA_ADDRESS); } static void *unw_hdr_alloc(unsigned long sz) diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index fceefd9..7062132 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -202,7 +202,7 @@ void __init allocate_pgdat(unsigned int nid) get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); #ifdef CONFIG_NEED_MULTIPLE_NODES - NODE_DATA(nid) = memblock_alloc_try_nid_nopanic( + NODE_DATA(nid) = memblock_alloc_try_nid( sizeof(struct pglist_data), SMP_CACHE_BYTES, MEMBLOCK_LOW_LIMIT, MEMBLOCK_ALLOC_ACCESSIBLE, nid); diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index e8796fc..0c5e9bf 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -106,22 +106,22 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size, void *ptr; if (!node_online(node) || !NODE_DATA(node)) { - ptr = memblock_alloc_from_nopanic(size, align, goal); + ptr = memblock_alloc_from(size, align, goal); pr_info("cpu %d has no node %d or node-local memory\n", cpu, node); pr_debug("per cpu data for cpu%d %lu bytes at %016lx\n", cpu, size, __pa(ptr)); } else { - ptr = memblock_alloc_try_nid_nopanic(size, align, goal, -MEMBLOCK_ALLOC_ACCESSIBLE, -node); + ptr = memblock_alloc_try_nid(size, align, goal, +MEMBLOCK_ALLOC_ACCESSIBLE, +node); pr_debug("per cpu data for cpu%d %lu bytes on node%d at %016lx\n", cpu, size, node, __pa(ptr)); } return ptr; #else - return memblock_alloc_from_nopanic(size, align, goal); + return memblock_alloc_from(size, align, goal); #endif } diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c index 462fde8..8dc0fc0 100644 --- a/arch/x86/mm/kasan_init_64.c +++ b/arch/x86/mm/kasan_init_64.c @@ -24,14 +24,16 @@ extern struct range pfn_mapped[E820_MAX_ENTRIES]; static p4d_t tmp_p4d_table[MAX_PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE); -static __init void *early_alloc(size_t size, int nid, bool panic) +static __init void *early_alloc(size_t size, int nid, bool should_panic) { - if (panic) - return memblock_alloc_try_nid(size, size, - __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, nid); - else - return memblock_alloc_try_nid_nopanic(size, size, + void *ptr = memblock_alloc_try_nid(size, size, __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, nid); + + if (!ptr && should_panic) + panic("%pS: Failed to allocate page, nid=%d from=%lx\n", + (void *)_RET_IP_, nid, __pa(MAX_DMA_ADDRESS)); + + return ptr; } static void __init kasan_populate_pmd(pmd_t *pmd, unsigned long addr, diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c index ec4fd25..d168c87 100644 --- a/drivers/firmware/memmap.c +++ b/drivers/firmware/memmap.c @@ -333,7 +333,7 @@ int __init firmware_map_add_early(u64 start, u64 end, const char *type) { struct firmware_map_entry *entry
[PATCH v2 17/21] init/main: add checks for the return value of memblock_alloc*()
Add panic() calls if memblock_alloc() returns NULL. The panic() format duplicates the one used by memblock itself and in order to avoid explosion with long parameters list replace open coded allocation size calculations with a local variable. Signed-off-by: Mike Rapoport --- init/main.c | 26 -- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/init/main.c b/init/main.c index a56f65a..d58a365 100644 --- a/init/main.c +++ b/init/main.c @@ -373,12 +373,20 @@ static inline void smp_prepare_cpus(unsigned int maxcpus) { } */ static void __init setup_command_line(char *command_line) { - saved_command_line = - memblock_alloc(strlen(boot_command_line) + 1, SMP_CACHE_BYTES); - initcall_command_line = - memblock_alloc(strlen(boot_command_line) + 1, SMP_CACHE_BYTES); - static_command_line = memblock_alloc(strlen(command_line) + 1, -SMP_CACHE_BYTES); + size_t len = strlen(boot_command_line) + 1; + + saved_command_line = memblock_alloc(len, SMP_CACHE_BYTES); + if (!saved_command_line) + panic("%s: Failed to allocate %zu bytes\n", __func__, len); + + initcall_command_line = memblock_alloc(len, SMP_CACHE_BYTES); + if (!initcall_command_line) + panic("%s: Failed to allocate %zu bytes\n", __func__, len); + + static_command_line = memblock_alloc(len, SMP_CACHE_BYTES); + if (!static_command_line) + panic("%s: Failed to allocate %zu bytes\n", __func__, len); + strcpy(saved_command_line, boot_command_line); strcpy(static_command_line, command_line); } @@ -773,8 +781,14 @@ static int __init initcall_blacklist(char *str) pr_debug("blacklisting initcall %s\n", str_entry); entry = memblock_alloc(sizeof(*entry), SMP_CACHE_BYTES); + if (!entry) + panic("%s: Failed to allocate %zu bytes\n", + __func__, sizeof(*entry)); entry->buf = memblock_alloc(strlen(str_entry) + 1, SMP_CACHE_BYTES); + if (!entry->buf) + panic("%s: Failed to allocate %zu bytes\n", + __func__, strlen(str_entry) + 1); strcpy(entry->buf, str_entry); list_add(&entry->next, &blacklisted_initcalls); } -- 2.7.4
[PATCH v2 10/21] memblock: refactor internal allocation functions
Currently, memblock has several internal functions with overlapping functionality. They all call memblock_find_in_range_node() to find free memory and then reserve the allocated range and mark it with kmemleak. However, there is difference in the allocation constraints and in fallback strategies. The allocations returning physical address first attempt to find free memory on the specified node within mirrored memory regions, then retry on the same node without the requirement for memory mirroring and finally fall back to all available memory. The allocations returning virtual address start with clamping the allowed range to memblock.current_limit, attempt to allocate from the specified node from regions with mirroring and with user defined minimal address. If such allocation fails, next attempt is done with node restriction lifted. Next, the allocation is retried with minimal address reset to zero and at last without the requirement for mirrored regions. Let's consolidate various fallbacks handling and make them more consistent for physical and virtual variants. Most of the fallback handling is moved to memblock_alloc_range_nid() and it now handles node and mirror fallbacks. The memblock_alloc_internal() uses memblock_alloc_range_nid() to get a physical address of the allocated range and converts it to virtual address. The fallback for allocation below the specified minimal address remains in memblock_alloc_internal() because memblock_alloc_range_nid() is used by CMA with exact requirement for lower bounds. The memblock_phys_alloc_nid() function is completely dropped as it is not used anywhere outside memblock and its only usage can be replaced by a call to memblock_alloc_range_nid(). Signed-off-by: Mike Rapoport --- include/linux/memblock.h | 1 - mm/memblock.c| 173 +-- 2 files changed, 78 insertions(+), 96 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 6874fdc..cf4cd9c 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -371,7 +371,6 @@ static inline int memblock_get_region_node(const struct memblock_region *r) phys_addr_t memblock_phys_alloc_range(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end); -phys_addr_t memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, int nid); phys_addr_t memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid); static inline phys_addr_t memblock_phys_alloc(phys_addr_t size, diff --git a/mm/memblock.c b/mm/memblock.c index 531fa77..739f769 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1312,30 +1312,84 @@ __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone, #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */ +/** + * memblock_alloc_range_nid - allocate boot memory block + * @size: size of memory block to be allocated in bytes + * @align: alignment of the region and block's size + * @start: the lower bound of the memory region to allocate (phys address) + * @end: the upper bound of the memory region to allocate (phys address) + * @nid: nid of the free area to find, %NUMA_NO_NODE for any node + * + * The allocation is performed from memory region limited by + * memblock.current_limit if @max_addr == %MEMBLOCK_ALLOC_ACCESSIBLE. + * + * If the specified node can not hold the requested memory the + * allocation falls back to any node in the system + * + * For systems with memory mirroring, the allocation is attempted first + * from the regions with mirroring enabled and then retried from any + * memory region. + * + * In addition, function sets the min_count to 0 using kmemleak_alloc_phys for + * allocated boot memory block, so that it is never reported as leaks. + * + * Return: + * Physical address of allocated memory block on success, %0 on failure. + */ static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size, phys_addr_t align, phys_addr_t start, - phys_addr_t end, int nid, - enum memblock_flags flags) + phys_addr_t end, int nid) { + enum memblock_flags flags = choose_memblock_flags(); phys_addr_t found; + if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n")) + nid = NUMA_NO_NODE; + if (!align) { /* Can't use WARNs this early in boot on powerpc */ dump_stack(); align = SMP_CACHE_BYTES; } + if (end > memblock.current_limit) + end = memblock.current_limit; + +again: found = memblock_find_in_range_node(size, align, start, end, nid, flags); - if (found && !memblock_reserve(found, size)) { + if (found && !membloc
[PATCH v2 18/21] swiotlb: add checks for the return value of memblock_alloc*()
Add panic() calls if memblock_alloc() returns NULL. The panic() format duplicates the one used by memblock itself and in order to avoid explosion with long parameters list replace open coded allocation size calculations with a local variable. Signed-off-by: Mike Rapoport --- kernel/dma/swiotlb.c | 19 +-- 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index d636177..e78835c8 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -191,6 +191,7 @@ void __init swiotlb_update_mem_attributes(void) int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) { unsigned long i, bytes; + size_t alloc_size; bytes = nslabs << IO_TLB_SHIFT; @@ -203,12 +204,18 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE * between io_tlb_start and io_tlb_end. */ - io_tlb_list = memblock_alloc( - PAGE_ALIGN(io_tlb_nslabs * sizeof(int)), - PAGE_SIZE); - io_tlb_orig_addr = memblock_alloc( - PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)), - PAGE_SIZE); + alloc_size = PAGE_ALIGN(io_tlb_nslabs * sizeof(int)); + io_tlb_list = memblock_alloc(alloc_size, PAGE_SIZE); + if (!io_tlb_list) + panic("%s: Failed to allocate %lu bytes align=0x%lx\n", + __func__, alloc_size, PAGE_SIZE); + + alloc_size = PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)); + io_tlb_orig_addr = memblock_alloc(alloc_size, PAGE_SIZE); + if (!io_tlb_orig_addr) + panic("%s: Failed to allocate %lu bytes align=0x%lx\n", + __func__, alloc_size, PAGE_SIZE); + for (i = 0; i < io_tlb_nslabs; i++) { io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); io_tlb_orig_addr[i] = INVALID_PHYS_ADDR; -- 2.7.4
[PATCH v2 15/21] sparc: add checks for the return value of memblock_alloc*()
Add panic() calls if memblock_alloc*() returns NULL. Most of the changes are simply addition of if(!ptr) panic(); statements after the calls to memblock_alloc*() variants. Exceptions are pcpu_populate_pte() and kernel_map_range() that were slightly refactored to accommodate the change. Signed-off-by: Mike Rapoport Acked-by: David S. Miller --- arch/sparc/kernel/prom_32.c | 2 ++ arch/sparc/kernel/setup_64.c | 6 ++ arch/sparc/kernel/smp_64.c | 12 arch/sparc/mm/init_64.c | 11 +++ arch/sparc/mm/srmmu.c| 8 5 files changed, 39 insertions(+) diff --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c index e7126ca..869b16c 100644 --- a/arch/sparc/kernel/prom_32.c +++ b/arch/sparc/kernel/prom_32.c @@ -33,6 +33,8 @@ void * __init prom_early_alloc(unsigned long size) void *ret; ret = memblock_alloc(size, SMP_CACHE_BYTES); + if (!ret) + panic("%s: Failed to allocate %lu bytes\n", __func__, size); prom_early_allocated += size; diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 51c4d12..fd2182a 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -624,8 +624,14 @@ void __init alloc_irqstack_bootmem(void) softirq_stack[i] = memblock_alloc_node(THREAD_SIZE, THREAD_SIZE, node); + if (!softirq_stack[i]) + panic("%s: Failed to allocate %lu bytes align=%lx nid=%d\n", + __func__, THREAD_SIZE, THREAD_SIZE, node); hardirq_stack[i] = memblock_alloc_node(THREAD_SIZE, THREAD_SIZE, node); + if (!hardirq_stack[i]) + panic("%s: Failed to allocate %lu bytes align=%lx nid=%d\n", + __func__, THREAD_SIZE, THREAD_SIZE, node); } } diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index f45d876..a8275fe 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -1628,6 +1628,8 @@ static void __init pcpu_populate_pte(unsigned long addr) pud_t *new; new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; pgd_populate(&init_mm, pgd, new); } @@ -1636,6 +1638,8 @@ static void __init pcpu_populate_pte(unsigned long addr) pmd_t *new; new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; pud_populate(&init_mm, pud, new); } @@ -1644,8 +1648,16 @@ static void __init pcpu_populate_pte(unsigned long addr) pte_t *new; new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; pmd_populate_kernel(&init_mm, pmd, new); } + + return; + +err_alloc: + panic("%s: Failed to allocate %lu bytes align=%lx from=%lx\n", + __func__, PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); } void __init setup_per_cpu_areas(void) diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index ef340e8..f2d70ff 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -1809,6 +1809,8 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; alloc_bytes += PAGE_SIZE; pgd_populate(&init_mm, pgd, new); } @@ -1822,6 +1824,8 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, } new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; alloc_bytes += PAGE_SIZE; pud_populate(&init_mm, pud, new); } @@ -1836,6 +1840,8 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, } new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + if (!new) + goto err_alloc; alloc_bytes += PAGE_SIZE; pmd_populate_kernel(&init_mm, pmd, new); } @@ -1855,6 +1861,11 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
[PATCH v2 16/21] mm/percpu: add checks for the return value of memblock_alloc*()
Add panic() calls if memblock_alloc() returns NULL. The panic() format duplicates the one used by memblock itself and in order to avoid explosion with long parameters list replace open coded allocation size calculations with a local variable. Signed-off-by: Mike Rapoport --- mm/percpu.c | 73 +++-- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/mm/percpu.c b/mm/percpu.c index db86282..5998b03 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -1086,6 +1086,7 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr, struct pcpu_chunk *chunk; unsigned long aligned_addr, lcm_align; int start_offset, offset_bits, region_size, region_bits; + size_t alloc_size; /* region calculations */ aligned_addr = tmp_addr & PAGE_MASK; @@ -1101,9 +1102,12 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr, region_size = ALIGN(start_offset + map_size, lcm_align); /* allocate chunk */ - chunk = memblock_alloc(sizeof(struct pcpu_chunk) + - BITS_TO_LONGS(region_size >> PAGE_SHIFT), - SMP_CACHE_BYTES); + alloc_size = sizeof(struct pcpu_chunk) + + BITS_TO_LONGS(region_size >> PAGE_SHIFT); + chunk = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!chunk) + panic("%s: Failed to allocate %zu bytes\n", __func__, + alloc_size); INIT_LIST_HEAD(&chunk->list); @@ -1114,12 +1118,25 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr, chunk->nr_pages = region_size >> PAGE_SHIFT; region_bits = pcpu_chunk_map_bits(chunk); - chunk->alloc_map = memblock_alloc(BITS_TO_LONGS(region_bits) * sizeof(chunk->alloc_map[0]), - SMP_CACHE_BYTES); - chunk->bound_map = memblock_alloc(BITS_TO_LONGS(region_bits + 1) * sizeof(chunk->bound_map[0]), - SMP_CACHE_BYTES); - chunk->md_blocks = memblock_alloc(pcpu_chunk_nr_blocks(chunk) * sizeof(chunk->md_blocks[0]), - SMP_CACHE_BYTES); + alloc_size = BITS_TO_LONGS(region_bits) * sizeof(chunk->alloc_map[0]); + chunk->alloc_map = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!chunk->alloc_map) + panic("%s: Failed to allocate %zu bytes\n", __func__, + alloc_size); + + alloc_size = + BITS_TO_LONGS(region_bits + 1) * sizeof(chunk->bound_map[0]); + chunk->bound_map = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!chunk->bound_map) + panic("%s: Failed to allocate %zu bytes\n", __func__, + alloc_size); + + alloc_size = pcpu_chunk_nr_blocks(chunk) * sizeof(chunk->md_blocks[0]); + chunk->md_blocks = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!chunk->md_blocks) + panic("%s: Failed to allocate %zu bytes\n", __func__, + alloc_size); + pcpu_init_md_blocks(chunk); /* manage populated page bitmap */ @@ -2044,6 +2061,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, int group, unit, i; int map_size; unsigned long tmp_addr; + size_t alloc_size; #define PCPU_SETUP_BUG_ON(cond)do { \ if (unlikely(cond)) { \ @@ -2075,14 +2093,29 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, PCPU_SETUP_BUG_ON(pcpu_verify_alloc_info(ai) < 0); /* process group information and build config tables accordingly */ - group_offsets = memblock_alloc(ai->nr_groups * sizeof(group_offsets[0]), - SMP_CACHE_BYTES); - group_sizes = memblock_alloc(ai->nr_groups * sizeof(group_sizes[0]), -SMP_CACHE_BYTES); - unit_map = memblock_alloc(nr_cpu_ids * sizeof(unit_map[0]), - SMP_CACHE_BYTES); - unit_off = memblock_alloc(nr_cpu_ids * sizeof(unit_off[0]), - SMP_CACHE_BYTES); + alloc_size = ai->nr_groups * sizeof(group_offsets[0]); + group_offsets = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!group_offsets) + panic("%s: Failed to allocate %zu bytes\n", __func__, + alloc_size); + + alloc_size = ai->nr_groups * sizeof(group_sizes[0]); + group_sizes = memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!group_sizes) + panic("%s: Failed to allocate %zu bytes\n&q
[PATCH v2 12/21] arch: use memblock_alloc() instead of memblock_alloc_from(size, align, 0)
The last parameter of memblock_alloc_from() is the lower limit for the memory allocation. When it is 0, the call is equivalent to memblock_alloc(). Signed-off-by: Mike Rapoport Acked-by: Paul Burton # MIPS part --- arch/alpha/kernel/core_cia.c | 2 +- arch/alpha/kernel/pci_iommu.c | 4 ++-- arch/alpha/kernel/setup.c | 2 +- arch/ia64/kernel/mca.c| 3 +-- arch/mips/kernel/traps.c | 2 +- arch/sparc/kernel/prom_32.c | 2 +- arch/sparc/mm/init_32.c | 2 +- arch/sparc/mm/srmmu.c | 10 +- 8 files changed, 13 insertions(+), 14 deletions(-) diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c index 867e873..466cd44 100644 --- a/arch/alpha/kernel/core_cia.c +++ b/arch/alpha/kernel/core_cia.c @@ -331,7 +331,7 @@ cia_prepare_tbia_workaround(int window) long i; /* Use minimal 1K map. */ - ppte = memblock_alloc_from(CIA_BROKEN_TBIA_SIZE, 32768, 0); + ppte = memblock_alloc(CIA_BROKEN_TBIA_SIZE, 32768); pte = (virt_to_phys(ppte) >> (PAGE_SHIFT - 1)) | 1; for (i = 0; i < CIA_BROKEN_TBIA_SIZE / sizeof(unsigned long); ++i) diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index aa0f50d..e4cf77b 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -87,13 +87,13 @@ iommu_arena_new_node(int nid, struct pci_controller *hose, dma_addr_t base, printk("%s: couldn't allocate arena ptes from node %d\n" "falling back to system-wide allocation\n", __func__, nid); - arena->ptes = memblock_alloc_from(mem_size, align, 0); + arena->ptes = memblock_alloc(mem_size, align); } #else /* CONFIG_DISCONTIGMEM */ arena = memblock_alloc(sizeof(*arena), SMP_CACHE_BYTES); - arena->ptes = memblock_alloc_from(mem_size, align, 0); + arena->ptes = memblock_alloc(mem_size, align); #endif /* CONFIG_DISCONTIGMEM */ diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 4b5b1b2..5d4c76a 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -293,7 +293,7 @@ move_initrd(unsigned long mem_limit) unsigned long size; size = initrd_end - initrd_start; - start = memblock_alloc_from(PAGE_ALIGN(size), PAGE_SIZE, 0); + start = memblock_alloc(PAGE_ALIGN(size), PAGE_SIZE); if (!start || __pa(start) + size > mem_limit) { initrd_start = initrd_end = 0; return NULL; diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 91bd1e1..74d148b 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -1835,8 +1835,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset, /* Caller prevents this from being called after init */ static void * __ref mca_bootmem(void) { - return memblock_alloc_from(sizeof(struct ia64_mca_cpu), - KERNEL_STACK_SIZE, 0); + return memblock_alloc(sizeof(struct ia64_mca_cpu), KERNEL_STACK_SIZE); } /* Do per-CPU MCA-related initialization. */ diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index c91097f..2bbdee5 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -2291,7 +2291,7 @@ void __init trap_init(void) phys_addr_t ebase_pa; ebase = (unsigned long) - memblock_alloc_from(size, 1 << fls(size), 0); + memblock_alloc(size, 1 << fls(size)); /* * Try to ensure ebase resides in KSeg0 if possible. diff --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c index 42d7f2a..38940af 100644 --- a/arch/sparc/kernel/prom_32.c +++ b/arch/sparc/kernel/prom_32.c @@ -32,7 +32,7 @@ void * __init prom_early_alloc(unsigned long size) { void *ret; - ret = memblock_alloc_from(size, SMP_CACHE_BYTES, 0UL); + ret = memblock_alloc(size, SMP_CACHE_BYTES); if (ret != NULL) memset(ret, 0, size); diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c index d900952..a8ff298 100644 --- a/arch/sparc/mm/init_32.c +++ b/arch/sparc/mm/init_32.c @@ -264,7 +264,7 @@ void __init mem_init(void) i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5); i += 1; sparc_valid_addr_bitmap = (unsigned long *) - memblock_alloc_from(i << 2, SMP_CACHE_BYTES, 0UL); + memblock_alloc(i << 2, SMP_CACHE_BYTES); if (sparc_valid_addr_bitmap == NULL) { prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n"); diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index b609362..a400ec3 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -303,13 +303,13 @@ static void __init srmmu_nocache_init(void) bitmap_bits = srmmu_nocac
[PATCH v2 13/21] arch: don't memset(0) memory returned by memblock_alloc()
memblock_alloc() already clears the allocated memory, no point in doing it twice. Signed-off-by: Mike Rapoport Acked-by: Geert Uytterhoeven # m68k --- arch/c6x/mm/init.c | 1 - arch/h8300/mm/init.c| 1 - arch/ia64/kernel/mca.c | 2 -- arch/m68k/mm/mcfmmu.c | 1 - arch/microblaze/mm/init.c | 6 ++ arch/sparc/kernel/prom_32.c | 2 -- 6 files changed, 2 insertions(+), 11 deletions(-) diff --git a/arch/c6x/mm/init.c b/arch/c6x/mm/init.c index af5ada0..e83c046 100644 --- a/arch/c6x/mm/init.c +++ b/arch/c6x/mm/init.c @@ -40,7 +40,6 @@ void __init paging_init(void) empty_zero_page = (unsigned long) memblock_alloc(PAGE_SIZE, PAGE_SIZE); - memset((void *)empty_zero_page, 0, PAGE_SIZE); /* * Set up user data space diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c index 6519252..a157890 100644 --- a/arch/h8300/mm/init.c +++ b/arch/h8300/mm/init.c @@ -68,7 +68,6 @@ void __init paging_init(void) * to a couple of allocated pages. */ empty_zero_page = (unsigned long)memblock_alloc(PAGE_SIZE, PAGE_SIZE); - memset((void *)empty_zero_page, 0, PAGE_SIZE); /* * Set up SFC/DFC registers (user data space). diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 74d148b..370bc34 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -400,8 +400,6 @@ ia64_log_init(int sal_info_type) // set up OS data structures to hold error info IA64_LOG_ALLOCATE(sal_info_type, max_size); - memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size); - memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size); } /* diff --git a/arch/m68k/mm/mcfmmu.c b/arch/m68k/mm/mcfmmu.c index 0de4999..492f953 100644 --- a/arch/m68k/mm/mcfmmu.c +++ b/arch/m68k/mm/mcfmmu.c @@ -44,7 +44,6 @@ void __init paging_init(void) int i; empty_zero_page = (void *) memblock_alloc(PAGE_SIZE, PAGE_SIZE); - memset((void *) empty_zero_page, 0, PAGE_SIZE); pg_dir = swapper_pg_dir; memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir)); diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 44f4b89..bd1cd4b 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -376,10 +376,8 @@ void * __ref zalloc_maybe_bootmem(size_t size, gfp_t mask) if (mem_init_done) p = kzalloc(size, mask); - else { + else p = memblock_alloc(size, SMP_CACHE_BYTES); - if (p) - memset(p, 0, size); - } + return p; } diff --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c index 38940af..e7126ca 100644 --- a/arch/sparc/kernel/prom_32.c +++ b/arch/sparc/kernel/prom_32.c @@ -33,8 +33,6 @@ void * __init prom_early_alloc(unsigned long size) void *ret; ret = memblock_alloc(size, SMP_CACHE_BYTES); - if (ret != NULL) - memset(ret, 0, size); prom_early_allocated += size; -- 2.7.4
[PATCH v2 11/21] memblock: make memblock_find_in_range_node() and choose_memblock_flags() static
These functions are not used outside memblock. Make them static. Signed-off-by: Mike Rapoport --- include/linux/memblock.h | 4 mm/memblock.c| 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index cf4cd9c..f5a83a1 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -111,9 +111,6 @@ void memblock_discard(void); #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 size, phys_addr_t align, - phys_addr_t start, phys_addr_t end, - int nid, enum memblock_flags flags); phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end, phys_addr_t size, phys_addr_t align); void memblock_allow_resize(void); @@ -130,7 +127,6 @@ int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); int memblock_mark_mirror(phys_addr_t base, phys_addr_t size); int memblock_mark_nomap(phys_addr_t base, phys_addr_t size); int memblock_clear_nomap(phys_addr_t base, phys_addr_t size); -enum memblock_flags choose_memblock_flags(void); unsigned long memblock_free_all(void); void reset_node_managed_pages(pg_data_t *pgdat); diff --git a/mm/memblock.c b/mm/memblock.c index 739f769..03b3929 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -125,7 +125,7 @@ static int memblock_can_resize __initdata_memblock; static int memblock_memory_in_slab __initdata_memblock = 0; static int memblock_reserved_in_slab __initdata_memblock = 0; -enum memblock_flags __init_memblock choose_memblock_flags(void) +static enum memblock_flags __init_memblock choose_memblock_flags(void) { return system_has_some_mirror ? MEMBLOCK_MIRROR : MEMBLOCK_NONE; } @@ -254,7 +254,7 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end, * Return: * Found address on success, 0 on failure. */ -phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size, +static phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end, int nid, enum memblock_flags flags) -- 2.7.4
[PATCH v2 08/21] memblock: drop __memblock_alloc_base()
The __memblock_alloc_base() function tries to allocate a memory up to the limit specified by its max_addr parameter. Depending on the value of this parameter, the __memblock_alloc_base() can is replaced with the appropriate memblock_phys_alloc*() variant. Signed-off-by: Mike Rapoport Acked-by: Rob Herring --- arch/sh/kernel/machine_kexec.c | 3 ++- arch/x86/kernel/e820.c | 2 +- arch/x86/mm/numa.c | 12 drivers/of/of_reserved_mem.c | 7 ++- include/linux/memblock.h | 2 -- mm/memblock.c | 9 ++--- 6 files changed, 11 insertions(+), 24 deletions(-) diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index b9f9f1a..63d63a3 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -168,7 +168,8 @@ void __init reserve_crashkernel(void) crash_size = PAGE_ALIGN(resource_size(&crashk_res)); if (!crashk_res.start) { unsigned long max = memblock_end_of_DRAM() - memory_limit; - crashk_res.start = __memblock_alloc_base(crash_size, PAGE_SIZE, max); + crashk_res.start = memblock_phys_alloc_range(crash_size, +PAGE_SIZE, 0, max); if (!crashk_res.start) { pr_err("crashkernel allocation failed\n"); goto disable; diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 50895c2..9c0eb54 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -778,7 +778,7 @@ u64 __init e820__memblock_alloc_reserved(u64 size, u64 align) { u64 addr; - addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE); + addr = memblock_phys_alloc(size, align); if (addr) { e820__range_update_kexec(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED); pr_info("update e820_table_kexec for e820__memblock_alloc_reserved()\n"); diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 1308f54..f85ae42 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -195,15 +195,11 @@ static void __init alloc_node_data(int nid) * Allocate node data. Try node-local memory and then any node. * Never allocate in DMA zone. */ - nd_pa = memblock_phys_alloc_nid(nd_size, SMP_CACHE_BYTES, nid); + nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); if (!nd_pa) { - nd_pa = __memblock_alloc_base(nd_size, SMP_CACHE_BYTES, - MEMBLOCK_ALLOC_ACCESSIBLE); - if (!nd_pa) { - pr_err("Cannot find %zu bytes in any node (initial node: %d)\n", - nd_size, nid); - return; - } + pr_err("Cannot find %zu bytes in any node (initial node: %d)\n", + nd_size, nid); + return; } nd = __va(nd_pa); diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 1977ee0..499f16d 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -31,13 +31,10 @@ int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, phys_addr_t *res_base) { phys_addr_t base; - /* -* We use __memblock_alloc_base() because memblock_alloc_base() -* panic()s on allocation failure. -*/ + end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end; align = !align ? SMP_CACHE_BYTES : align; - base = __memblock_alloc_base(size, align, end); + base = memblock_phys_alloc_range(size, align, 0, end); if (!base) return -ENOMEM; diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 7883c74..768e2b4 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -496,8 +496,6 @@ static inline bool memblock_bottom_up(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_reserved_size(void); phys_addr_t memblock_mem_size(unsigned long limit_pfn); diff --git a/mm/memblock.c b/mm/memblock.c index 461e40a3..e5ffdcd 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1363,17 +1363,12 @@ phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, return ret; } -phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr) -{ - return memblock_alloc_range_nid(size, align, 0, max_addr, NUMA_NO_NODE, - MEMBLOCK_NONE); -} - phys_addr_t __init memblock_alloc_base(phys_addr_t si
[PATCH v2 07/21] memblock: memblock_phys_alloc(): don't panic
Make the memblock_phys_alloc() function an inline wrapper for memblock_phys_alloc_range() and update the memblock_phys_alloc() callers to check the returned value and panic in case of error. Signed-off-by: Mike Rapoport --- arch/arm/mm/init.c | 4 arch/arm64/mm/mmu.c | 2 ++ arch/powerpc/sysdev/dart_iommu.c | 3 +++ arch/s390/kernel/crash_dump.c| 3 +++ arch/s390/kernel/setup.c | 3 +++ arch/sh/boards/mach-ap325rxa/setup.c | 3 +++ arch/sh/boards/mach-ecovec24/setup.c | 6 ++ arch/sh/boards/mach-kfr2r09/setup.c | 3 +++ arch/sh/boards/mach-migor/setup.c| 3 +++ arch/sh/boards/mach-se/7724/setup.c | 6 ++ arch/xtensa/mm/kasan_init.c | 3 +++ include/linux/memblock.h | 7 ++- mm/memblock.c| 5 - 13 files changed, 45 insertions(+), 6 deletions(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index b76b90e..15dddfe 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -206,6 +206,10 @@ phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align) BUG_ON(!arm_memblock_steal_permitted); phys = memblock_phys_alloc(size, align); + if (!phys) + panic("Failed to steal %pa bytes at %pS\n", + &size, (void *)_RET_IP_); + memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index b6f5aa5..a74e4be 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -104,6 +104,8 @@ static phys_addr_t __init early_pgtable_alloc(void) void *ptr; phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); + if (!phys) + panic("Failed to allocate page table page\n"); /* * The FIX_{PGD,PUD,PMD} slots may be in active use, but the FIX_PTE diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 25bc25f..b82c9ff 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -265,6 +265,9 @@ static void allocate_dart(void) * prefetching into invalid pages and corrupting data */ tmp = memblock_phys_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE); + if (!tmp) + panic("DART: table allocation failed\n"); + dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & DARTMAP_RPNMASK); diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 97eae38..f96a585 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -61,6 +61,9 @@ struct save_area * __init save_area_alloc(bool is_boot_cpu) struct save_area *sa; sa = (void *) memblock_phys_alloc(sizeof(*sa), 8); + if (!sa) + panic("Failed to allocate save area\n"); + if (is_boot_cpu) list_add(&sa->list, &dump_save_areas); else diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 72dd23e..da48397 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -968,6 +968,9 @@ static void __init setup_randomness(void) vmms = (struct sysinfo_3_2_2 *) memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); + if (!vmms) + panic("Failed to allocate memory for sysinfo structure\n"); + if (stsi(vmms, 3, 2, 2) == 0 && vmms->count) add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count); memblock_free((unsigned long) vmms, PAGE_SIZE); diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index d7ceab6..08a0cc9 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -558,6 +558,9 @@ static void __init ap325rxa_mv_mem_reserve(void) phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; phys = memblock_phys_alloc(size, PAGE_SIZE); + if (!phys) + panic("Failed to allocate CEU memory\n"); + memblock_free(phys, size); memblock_remove(phys, size); diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index a3901806..fd264a6 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -1481,11 +1481,17 @@ static void __init ecovec_mv_mem_reserve(void) phys_addr_t size = CEU_BUFFER_MEMORY_SIZE; phys = memblock_phys_alloc(size, PAGE_SIZE); + if (!phys) + panic("Failed to allocate CEU0 memory\n"); + memblock_free(phys, size); memblock_remove(phys, size); ceu0_dma_membase = phys; phys = memblock_phys_alloc(size, PAGE_SIZE); + if (!phys) + panic("Failed to allocate CEU1 memory\
[PATCH v2 04/21] memblock: drop memblock_alloc_base_nid()
The memblock_alloc_base_nid() is a oneliner wrapper for memblock_alloc_range_nid() without any side effect. Replace it's usage by the direct calls to memblock_alloc_range_nid(). Signed-off-by: Mike Rapoport --- include/linux/memblock.h | 3 --- mm/memblock.c| 15 --- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 60e100f..f7ef313 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -490,9 +490,6 @@ static inline bool memblock_bottom_up(void) phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end, enum memblock_flags flags); -phys_addr_t memblock_alloc_base_nid(phys_addr_t size, - phys_addr_t align, phys_addr_t max_addr, - int nid, enum memblock_flags flags); 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, diff --git a/mm/memblock.c b/mm/memblock.c index a32db30..c80029e 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1346,21 +1346,14 @@ phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align, flags); } -phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size, - phys_addr_t align, phys_addr_t max_addr, - int nid, enum memblock_flags flags) -{ - return memblock_alloc_range_nid(size, align, 0, max_addr, nid, flags); -} - phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, int nid) { enum memblock_flags flags = choose_memblock_flags(); phys_addr_t ret; again: - ret = memblock_alloc_base_nid(size, align, MEMBLOCK_ALLOC_ACCESSIBLE, - nid, flags); + ret = memblock_alloc_range_nid(size, align, 0, + MEMBLOCK_ALLOC_ACCESSIBLE, nid, flags); if (!ret && (flags & MEMBLOCK_MIRROR)) { flags &= ~MEMBLOCK_MIRROR; @@ -1371,8 +1364,8 @@ phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr) { - return memblock_alloc_base_nid(size, align, max_addr, NUMA_NO_NODE, - MEMBLOCK_NONE); + return memblock_alloc_range_nid(size, align, 0, max_addr, NUMA_NO_NODE, + MEMBLOCK_NONE); } phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr) -- 2.7.4
[PATCH v2 05/21] memblock: emphasize that memblock_alloc_range() returns a physical address
Rename memblock_alloc_range() to memblock_phys_alloc_range() to emphasize that it returns a physical address. While on it, remove the 'enum memblock_flags' parameter from this function as its only user anyway sets it to MEMBLOCK_NONE, which is the default for the most of memblock allocations. Signed-off-by: Mike Rapoport --- include/linux/memblock.h | 5 ++--- mm/cma.c | 10 -- mm/memblock.c| 9 + 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index f7ef313..66dfdb3 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -369,6 +369,8 @@ static inline int memblock_get_region_node(const struct memblock_region *r) #define ARCH_LOW_ADDRESS_LIMIT 0xUL #endif +phys_addr_t memblock_phys_alloc_range(phys_addr_t size, phys_addr_t align, + phys_addr_t start, phys_addr_t end); phys_addr_t memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, int nid); phys_addr_t memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid); @@ -487,9 +489,6 @@ static inline bool memblock_bottom_up(void) return memblock.bottom_up; } -phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align, - phys_addr_t start, phys_addr_t end, - enum memblock_flags flags); 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, diff --git a/mm/cma.c b/mm/cma.c index c7b39dd..e4530ae 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -327,16 +327,14 @@ int __init cma_declare_contiguous(phys_addr_t base, * memory in case of failure. */ if (base < highmem_start && limit > highmem_start) { - addr = memblock_alloc_range(size, alignment, - highmem_start, limit, - MEMBLOCK_NONE); + addr = memblock_phys_alloc_range(size, alignment, +highmem_start, limit); limit = highmem_start; } if (!addr) { - addr = memblock_alloc_range(size, alignment, base, - limit, - MEMBLOCK_NONE); + addr = memblock_phys_alloc_range(size, alignment, base, +limit); if (!addr) { ret = -ENOMEM; goto err; diff --git a/mm/memblock.c b/mm/memblock.c index c80029e..f019aee 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1338,12 +1338,13 @@ static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size, return 0; } -phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align, - phys_addr_t start, phys_addr_t end, - enum memblock_flags flags) +phys_addr_t __init memblock_phys_alloc_range(phys_addr_t size, +phys_addr_t align, +phys_addr_t start, +phys_addr_t end) { return memblock_alloc_range_nid(size, align, start, end, NUMA_NO_NODE, - flags); + MEMBLOCK_NONE); } phys_addr_t __init memblock_phys_alloc_nid(phys_addr_t size, phys_addr_t align, int nid) -- 2.7.4
[PATCH v2 00/21] Refine memblock API
Hi, Current memblock API is quite extensive and, which is more annoying, duplicated. Except the low-level functions that allow searching for a free memory region and marking it as reserved, memblock provides three (well, two and a half) sets of functions to allocate memory. There are several overlapping functions that return a physical address and there are functions that return virtual address. Those that return the virtual address may also clear the allocated memory. And, on top of all that, some allocators panic and some return NULL in case of error. This set tries to reduce the mess, and trim down the amount of memblock allocation methods. Patches 1-10 consolidate the functions that return physical address of the allocated memory Patches 11-13 are some trivial cleanups Patches 14-19 add checks for the return value of memblock_alloc*() and panics in case of errors. The patches 14-18 include some minor refactoring to have better readability of the resulting code and patch 19 is a mechanical addition of if (!ptr) panic(); after memblock_alloc*() calls. And, finally, patches 20 and 21 remove panic() calls memblock and _nopanic variants from memblock. v2 changes: * replace some more %lu with %zu * remove panics where they are not needed in s390 and in printk * collect Acked-by and Reviewed-by. Christophe Leroy (1): powerpc: use memblock functions returning virtual address Mike Rapoport (20): openrisc: prefer memblock APIs returning virtual address memblock: replace memblock_alloc_base(ANYWHERE) with memblock_phys_alloc memblock: drop memblock_alloc_base_nid() memblock: emphasize that memblock_alloc_range() returns a physical address memblock: memblock_phys_alloc_try_nid(): don't panic memblock: memblock_phys_alloc(): don't panic memblock: drop __memblock_alloc_base() memblock: drop memblock_alloc_base() memblock: refactor internal allocation functions memblock: make memblock_find_in_range_node() and choose_memblock_flags() static arch: use memblock_alloc() instead of memblock_alloc_from(size, align, 0) arch: don't memset(0) memory returned by memblock_alloc() ia64: add checks for the return value of memblock_alloc*() sparc: add checks for the return value of memblock_alloc*() mm/percpu: add checks for the return value of memblock_alloc*() init/main: add checks for the return value of memblock_alloc*() swiotlb: add checks for the return value of memblock_alloc*() treewide: add checks for the return value of memblock_alloc*() memblock: memblock_alloc_try_nid: don't panic memblock: drop memblock_alloc_*_nopanic() variants arch/alpha/kernel/core_cia.c | 5 +- arch/alpha/kernel/core_marvel.c | 6 + arch/alpha/kernel/pci-noop.c | 13 +- arch/alpha/kernel/pci.c | 11 +- arch/alpha/kernel/pci_iommu.c | 16 +- arch/alpha/kernel/setup.c | 2 +- arch/arc/kernel/unwind.c | 3 +- arch/arc/mm/highmem.c | 4 + arch/arm/kernel/setup.c | 6 + arch/arm/mm/init.c| 6 +- arch/arm/mm/mmu.c | 14 +- arch/arm64/kernel/setup.c | 8 +- arch/arm64/mm/kasan_init.c| 10 ++ arch/arm64/mm/mmu.c | 2 + arch/arm64/mm/numa.c | 4 + arch/c6x/mm/dma-coherent.c| 4 + arch/c6x/mm/init.c| 4 +- arch/csky/mm/highmem.c| 5 + arch/h8300/mm/init.c | 4 +- arch/ia64/kernel/mca.c| 25 +-- arch/ia64/mm/contig.c | 8 +- arch/ia64/mm/discontig.c | 4 + arch/ia64/mm/init.c | 38 - arch/ia64/mm/tlb.c| 6 + arch/ia64/sn/kernel/io_common.c | 3 + arch/ia64/sn/kernel/setup.c | 12 +- arch/m68k/atari/stram.c | 4 + arch/m68k/mm/init.c | 3 + arch/m68k/mm/mcfmmu.c | 7 +- arch/m68k/mm/motorola.c | 9 ++ arch/m68k/mm/sun3mmu.c| 6 + arch/m68k/sun3/sun3dvma.c | 3 + arch/microblaze/mm/init.c | 10 +- arch/mips/cavium-octeon/dma-octeon.c | 3 + arch/mips/kernel/setup.c | 3 + arch/mips/kernel/traps.c | 5 +- arch/mips/mm/init.c | 5 + arch/nds32/mm/init.c | 12 ++ arch/openrisc/mm/init.c | 5 +- arch/openrisc/mm/ioremap.c| 8 +- arch/powerpc/kernel/dt_cpu_ftrs.c | 8 +- arch/powerpc/kernel/irq.c | 5 - arch/powerpc/kernel/paca.c| 6 +- arch/powerpc/kernel/pci_32.c | 3 + arch/powerpc/kernel/prom.c| 5 +- arch/p
[PATCH v2 02/21] powerpc: use memblock functions returning virtual address
From: Christophe Leroy Since only the virtual address of allocated blocks is used, lets use functions returning directly virtual address. Those functions have the advantage of also zeroing the block. [ MR: - updated error message in alloc_stack() to be more verbose - convereted several additional call sites ] Signed-off-by: Christophe Leroy Signed-off-by: Mike Rapoport --- arch/powerpc/kernel/dt_cpu_ftrs.c | 3 +-- arch/powerpc/kernel/irq.c | 5 - arch/powerpc/kernel/paca.c| 6 +- arch/powerpc/kernel/prom.c| 5 - arch/powerpc/kernel/setup_32.c| 26 -- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c index 8be3721..2554824 100644 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c @@ -813,7 +813,6 @@ static int __init process_cpufeatures_node(unsigned long node, int len; f = &dt_cpu_features[i]; - memset(f, 0, sizeof(struct dt_cpu_feature)); f->node = node; @@ -1008,7 +1007,7 @@ static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char /* Count and allocate space for cpu features */ of_scan_flat_dt_subnodes(node, count_cpufeatures_subnodes, &nr_dt_cpu_features); - dt_cpu_features = __va(memblock_phys_alloc(sizeof(struct dt_cpu_feature) * nr_dt_cpu_features, PAGE_SIZE)); + dt_cpu_features = memblock_alloc(sizeof(struct dt_cpu_feature) * nr_dt_cpu_features, PAGE_SIZE); cpufeatures_setup_start(isa); diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 916ddc4..4a44bc3 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -725,18 +725,15 @@ void exc_lvl_ctx_init(void) #endif #endif - memset((void *)critirq_ctx[cpu_nr], 0, THREAD_SIZE); tp = critirq_ctx[cpu_nr]; tp->cpu = cpu_nr; tp->preempt_count = 0; #ifdef CONFIG_BOOKE - memset((void *)dbgirq_ctx[cpu_nr], 0, THREAD_SIZE); tp = dbgirq_ctx[cpu_nr]; tp->cpu = cpu_nr; tp->preempt_count = 0; - memset((void *)mcheckirq_ctx[cpu_nr], 0, THREAD_SIZE); tp = mcheckirq_ctx[cpu_nr]; tp->cpu = cpu_nr; tp->preempt_count = HARDIRQ_OFFSET; @@ -754,12 +751,10 @@ void irq_ctx_init(void) int i; for_each_possible_cpu(i) { - memset((void *)softirq_ctx[i], 0, THREAD_SIZE); tp = softirq_ctx[i]; tp->cpu = i; klp_init_thread_info(tp); - memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); tp = hardirq_ctx[i]; tp->cpu = i; klp_init_thread_info(tp); diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 8c890c6..e7382ab 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c @@ -196,7 +196,11 @@ void __init allocate_paca_ptrs(void) paca_nr_cpu_ids = nr_cpu_ids; paca_ptrs_size = sizeof(struct paca_struct *) * nr_cpu_ids; - paca_ptrs = __va(memblock_phys_alloc(paca_ptrs_size, SMP_CACHE_BYTES)); + paca_ptrs = memblock_alloc_raw(paca_ptrs_size, SMP_CACHE_BYTES); + if (!paca_ptrs) + panic("Failed to allocate %d bytes for paca pointers\n", + paca_ptrs_size); + memset(paca_ptrs, 0x88, paca_ptrs_size); } diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index e97aaf2..c0ed4fa 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -127,7 +127,10 @@ static void __init move_device_tree(void) if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) || !memblock_is_memory(start + size - 1) || overlaps_crashkernel(start, size) || overlaps_initrd(start, size)) { - p = __va(memblock_phys_alloc(size, PAGE_SIZE)); + p = memblock_alloc_raw(size, PAGE_SIZE); + if (!p) + panic("Failed to allocate %lu bytes to move device tree\n", + size); memcpy(p, initial_boot_params, size); initial_boot_params = p; DBG("Moved device tree to 0x%px\n", p); diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 947f904..1f0b762 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -196,6 +196,17 @@ static int __init ppc_init(void) } arch_initcall(ppc_init); +static void *__init alloc_stack(void) +{ + void *ptr = memblock_alloc(THREAD_SIZE, THREAD_SIZE); + + if (!ptr) + panic("cannot allocate %d bytes for stack at %
Re: [PATCH v2 06/21] memblock: memblock_phys_alloc_try_nid(): don't panic
On Fri, Jan 25, 2019 at 05:45:02PM +, Catalin Marinas wrote: > On Mon, Jan 21, 2019 at 10:03:53AM +0200, Mike Rapoport wrote: > > diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c > > index ae34e3a..2c61ea4 100644 > > --- a/arch/arm64/mm/numa.c > > +++ b/arch/arm64/mm/numa.c > > @@ -237,6 +237,10 @@ static void __init setup_node_data(int nid, u64 > > start_pfn, u64 end_pfn) > > pr_info("Initmem setup node %d []\n", nid); > > > > nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); > > + if (!nd_pa) > > + panic("Cannot allocate %zu bytes for node %d data\n", > > + nd_size, nid); > > + > > nd = __va(nd_pa); > > > > /* report and initialize */ > > Does it mean that memblock_phys_alloc_try_nid() never returns valid > physical memory starting at 0? Yes, it does. memblock_find_in_range_node() that is used by all allocation methods skips the first page [1]. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/memblock.c#n257 > -- > Catalin > -- Sincerely yours, Mike.
Re: [PATCH v2 19/21] treewide: add checks for the return value of memblock_alloc*()
On Thu, Jan 31, 2019 at 07:07:46AM +0100, Christophe Leroy wrote: > > > Le 21/01/2019 à 09:04, Mike Rapoport a écrit : > >Add check for the return value of memblock_alloc*() functions and call > >panic() in case of error. > >The panic message repeats the one used by panicing memblock allocators with > >adjustment of parameters to include only relevant ones. > > > >The replacement was mostly automated with semantic patches like the one > >below with manual massaging of format strings. > > > >@@ > >expression ptr, size, align; > >@@ > >ptr = memblock_alloc(size, align); > >+ if (!ptr) > >+panic("%s: Failed to allocate %lu bytes align=0x%lx\n", __func__, > >size, align); > > > >Signed-off-by: Mike Rapoport > >Reviewed-by: Guo Ren # c-sky > >Acked-by: Paul Burton # MIPS > >Acked-by: Heiko Carstens # s390 > >Reviewed-by: Juergen Gross # Xen > >--- > > [...] > > >diff --git a/mm/sparse.c b/mm/sparse.c > >index 7ea5dc6..ad94242 100644 > >--- a/mm/sparse.c > >+++ b/mm/sparse.c > > [...] > > >@@ -425,6 +436,10 @@ static void __init sparse_buffer_init(unsigned long > >size, int nid) > > memblock_alloc_try_nid_raw(size, PAGE_SIZE, > > __pa(MAX_DMA_ADDRESS), > > MEMBLOCK_ALLOC_ACCESSIBLE, nid); > >+if (!sparsemap_buf) > >+panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d > >from=%lx\n", > >+ __func__, size, PAGE_SIZE, nid, __pa(MAX_DMA_ADDRESS)); > >+ > > memblock_alloc_try_nid_raw() does not panic (help explicitly says: Does not > zero allocated memory, does not panic if request cannot be satisfied.). "Does not panic" does not mean it always succeeds. > Stephen Rothwell reports a boot failure due to this change. Please see my reply on that thread. > Christophe > > > sparsemap_buf_end = sparsemap_buf + size; > > } > > > -- Sincerely yours, Mike.
Re: [PATCH v2 19/21] treewide: add checks for the return value of memblock_alloc*()
On Thu, Jan 31, 2019 at 08:07:29AM +0100, Christophe Leroy wrote: > > > Le 31/01/2019 à 07:44, Christophe Leroy a écrit : > > > > > >Le 31/01/2019 à 07:41, Mike Rapoport a écrit : > >>On Thu, Jan 31, 2019 at 07:07:46AM +0100, Christophe Leroy wrote: > >>> > >>> > >>>Le 21/01/2019 à 09:04, Mike Rapoport a écrit : > >>>>Add check for the return value of memblock_alloc*() functions and call > >>>>panic() in case of error. > >>>>The panic message repeats the one used by panicing memblock > >>>>allocators with > >>>>adjustment of parameters to include only relevant ones. > >>>> > >>>>The replacement was mostly automated with semantic patches like the one > >>>>below with manual massaging of format strings. > >>>> > >>>>@@ > >>>>expression ptr, size, align; > >>>>@@ > >>>>ptr = memblock_alloc(size, align); > >>>>+ if (!ptr) > >>>>+ panic("%s: Failed to allocate %lu bytes align=0x%lx\n", __func__, > >>>>size, align); > >>>> > >>>>Signed-off-by: Mike Rapoport > >>>>Reviewed-by: Guo Ren # c-sky > >>>>Acked-by: Paul Burton # MIPS > >>>>Acked-by: Heiko Carstens # s390 > >>>>Reviewed-by: Juergen Gross # Xen > >>>>--- > >>> > >>>[...] > >>> > >>>>diff --git a/mm/sparse.c b/mm/sparse.c > >>>>index 7ea5dc6..ad94242 100644 > >>>>--- a/mm/sparse.c > >>>>+++ b/mm/sparse.c > >>> > >>>[...] > >>> > >>>>@@ -425,6 +436,10 @@ static void __init sparse_buffer_init(unsigned > >>>>long size, int nid) > >>>> memblock_alloc_try_nid_raw(size, PAGE_SIZE, > >>>> __pa(MAX_DMA_ADDRESS), > >>>> MEMBLOCK_ALLOC_ACCESSIBLE, nid); > >>>>+ if (!sparsemap_buf) > >>>>+ panic("%s: Failed to allocate %lu bytes align=0x%lx nid=%d > >>>>from=%lx\n", > >>>>+ __func__, size, PAGE_SIZE, nid, __pa(MAX_DMA_ADDRESS)); > >>>>+ > >>> > >>>memblock_alloc_try_nid_raw() does not panic (help explicitly says: > >>>Does not > >>>zero allocated memory, does not panic if request cannot be satisfied.). > >> > >>"Does not panic" does not mean it always succeeds. > > > >I agree, but at least here you are changing the behaviour by making it > >panic explicitly. Are we sure there are not cases where the system could > >just continue functionning ? Maybe a WARN_ON() would be enough there ? > > Looking more in details, it looks like everything is done to live with > sparsemap_buf NULL, all functions using it check it so having it NULL > shouldn't imply a panic I believe, see code below. You are right, I'm preparing the fix right now. > static void *sparsemap_buf __meminitdata; > static void *sparsemap_buf_end __meminitdata; > > static void __init sparse_buffer_init(unsigned long size, int nid) > { > WARN_ON(sparsemap_buf); /* forgot to call sparse_buffer_fini()? */ > sparsemap_buf = > memblock_alloc_try_nid_raw(size, PAGE_SIZE, > __pa(MAX_DMA_ADDRESS), > MEMBLOCK_ALLOC_ACCESSIBLE, nid); > sparsemap_buf_end = sparsemap_buf + size; > } > > static void __init sparse_buffer_fini(void) > { > unsigned long size = sparsemap_buf_end - sparsemap_buf; > > if (sparsemap_buf && size > 0) > memblock_free_early(__pa(sparsemap_buf), size); > sparsemap_buf = NULL; > } > > void * __meminit sparse_buffer_alloc(unsigned long size) > { > void *ptr = NULL; > > if (sparsemap_buf) { > ptr = PTR_ALIGN(sparsemap_buf, size); > if (ptr + size > sparsemap_buf_end) > ptr = NULL; > else > sparsemap_buf = ptr + size; > } > return ptr; > } > > > Christophe > -- Sincerely yours, Mike.
Re: [PATCH v2 10/21] memblock: refactor internal allocation functions
On Sun, Feb 03, 2019 at 08:39:20PM +1100, Michael Ellerman wrote: > Mike Rapoport writes: > > > Currently, memblock has several internal functions with overlapping > > functionality. They all call memblock_find_in_range_node() to find free > > memory and then reserve the allocated range and mark it with kmemleak. > > However, there is difference in the allocation constraints and in fallback > > strategies. > > > > The allocations returning physical address first attempt to find free > > memory on the specified node within mirrored memory regions, then retry on > > the same node without the requirement for memory mirroring and finally fall > > back to all available memory. > > > > The allocations returning virtual address start with clamping the allowed > > range to memblock.current_limit, attempt to allocate from the specified > > node from regions with mirroring and with user defined minimal address. If > > such allocation fails, next attempt is done with node restriction lifted. > > Next, the allocation is retried with minimal address reset to zero and at > > last without the requirement for mirrored regions. > > > > Let's consolidate various fallbacks handling and make them more consistent > > for physical and virtual variants. Most of the fallback handling is moved > > to memblock_alloc_range_nid() and it now handles node and mirror fallbacks. > > > > The memblock_alloc_internal() uses memblock_alloc_range_nid() to get a > > physical address of the allocated range and converts it to virtual address. > > > > The fallback for allocation below the specified minimal address remains in > > memblock_alloc_internal() because memblock_alloc_range_nid() is used by CMA > > with exact requirement for lower bounds. > > This is causing problems on some of my machines. > > I see NODE_DATA allocations falling back to node 0 when they shouldn't, > or didn't previously. > > eg, before: > > 57990190: (116011251): numa: NODE_DATA [mem 0xfffe4980-0xfffebfff] > 58152042: (116373087): numa: NODE_DATA [mem 0x8fff90980-0x8fff97fff] > > after: > > 16356872061562: (6296877055): numa: NODE_DATA [mem 0xfffe4980-0xfffebfff] > 16356872079279: (6296894772): numa: NODE_DATA [mem 0xfffcd300-0xfffd497f] > 16356872096376: (6296911869): numa: NODE_DATA(1) on node 0 > > > On some of my other systems it does that, and then panics because it > can't allocate anything at all: > > [0.00] numa: NODE_DATA [mem 0x7ffcaee80-0x7ffcb3fff] > [0.00] numa: NODE_DATA [mem 0x7ffc99d00-0x7ffc9ee7f] > [0.00] numa: NODE_DATA(1) on node 0 > [0.00] Kernel panic - not syncing: Cannot allocate 20864 bytes for > node 16 data > [0.00] CPU: 0 PID: 0 Comm: swapper Not tainted > 5.0.0-rc4-gccN-next-20190201-gdc4c899 #1 > [0.00] Call Trace: > [0.00] [c11cfca0] [c0c11044] dump_stack+0xe8/0x164 > (unreliable) > [0.00] [c11cfcf0] [c00fdd6c] panic+0x17c/0x3e0 > [0.00] [c11cfd90] [c0f61bc8] initmem_init+0x128/0x260 > [0.00] [c11cfe60] [c0f57940] setup_arch+0x398/0x418 > [0.00] [c11cfee0] [c0f50a94] start_kernel+0xa0/0x684 > [0.00] [c11cff90] [c000af70] > start_here_common+0x1c/0x52c > [0.00] Rebooting in 180 seconds.. > > > So there's something going wrong there, I haven't had time to dig into > it though (Sunday night here). I'll try to see if I can reproduce it with qemu. > cheers > -- Sincerely yours, Mike.