Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754639Ab1BGSp1 (ORCPT ); Mon, 7 Feb 2011 13:45:27 -0500 Received: from mail-qy0-f174.google.com ([209.85.216.174]:62902 "EHLO mail-qy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754615Ab1BGSpZ convert rfc822-to-8bit (ORCPT ); Mon, 7 Feb 2011 13:45:25 -0500 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type :content-transfer-encoding; b=LVTBzpQkHaAQcub3hkgnWJyO4z97a777h5yDOPXln9HNrg/tWmppvCqBSsDzCEUcJo v4z/xtI/LARCqJl3/DN1RsLjwe0btM2LDMv4U5Msi7ITX7qqUXm0sWxeJpAks5rAwZ57 yAl9Ko4rSNj7dXkwj+aLHn6ExpWonr7sChoUI= MIME-Version: 1.0 In-Reply-To: <1297092614-1906-1-git-send-email-namhyung@gmail.com> References: <1297092614-1906-1-git-send-email-namhyung@gmail.com> Date: Mon, 7 Feb 2011 10:45:23 -0800 X-Google-Sender-Auth: LZUyY-F_63njDqjrGEdAM-wu6Dg Message-ID: Subject: Re: [RFC] Split up mm/bootmem.c From: Yinghai Lu To: Namhyung Kim Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 29667 Lines: 891 On Mon, Feb 7, 2011 at 7:30 AM, Namhyung Kim wrote: > The bootmem code contained many #ifdefs in it so that it could be > splitted into two files for the readability. The split was quite > mechanical and only function need to be shared was free_bootmem_late. > > Tested on x86-64 and um which use nobootmem and bootmem respectively. > > Signed-off-by: Namhyung Kim https://lkml.org/lkml/2010/6/16/44 ... > --- > ?mm/Makefile ? ?| ? ?8 +- > ?mm/bootmem.c ? | ?164 +-------------------- > ?mm/nobootmem.c | ?445 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ?3 files changed, 454 insertions(+), 163 deletions(-) > ?create mode 100644 mm/nobootmem.c > > diff --git a/mm/Makefile b/mm/Makefile > index 2b1b575ae712..e9a074dbad15 100644 > --- a/mm/Makefile > +++ b/mm/Makefile > @@ -7,7 +7,7 @@ mmu-$(CONFIG_MMU) ? ? ? := fremap.o highmem.o madvise.o memory.o mincore.o \ > ? ? ? ? ? ? ? ? ? ? ? ? ? mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \ > ? ? ? ? ? ? ? ? ? ? ? ? ? vmalloc.o pagewalk.o pgtable-generic.o > > -obj-y ? ? ? ? ? ? ? ? ?:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ > +obj-y ? ? ? ? ? ? ? ? ?:= filemap.o mempool.o oom_kill.o fadvise.o \ > ? ? ? ? ? ? ? ? ? ? ? ? ? maccess.o page_alloc.o page-writeback.o \ > ? ? ? ? ? ? ? ? ? ? ? ? ? readahead.o swap.o truncate.o vmscan.o shmem.o \ > ? ? ? ? ? ? ? ? ? ? ? ? ? prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ > @@ -15,6 +15,12 @@ obj-y ? ? ? ? ? ? ? ? ? ? ? ?:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ > ? ? ? ? ? ? ? ? ? ? ? ? ? $(mmu-y) > ?obj-y += init-mm.o > > +ifeq ($(CONFIG_NO_BOOTMEM),y) > +obj-y += nobootmem.o > +else > +obj-y += bootmem.o > +endif > + > ?obj-$(CONFIG_HAVE_MEMBLOCK) += memblock.o > > ?obj-$(CONFIG_BOUNCE) ? += bounce.o > diff --git a/mm/bootmem.c b/mm/bootmem.c > index 13b0caa9793c..209be265ad94 100644 > --- a/mm/bootmem.c > +++ b/mm/bootmem.c > @@ -35,7 +35,6 @@ unsigned long max_pfn; > ?unsigned long saved_max_pfn; > ?#endif > > -#ifndef CONFIG_NO_BOOTMEM > ?bootmem_data_t bootmem_node_data[MAX_NUMNODES] __initdata; > > ?static struct list_head bdata_list __initdata = LIST_HEAD_INIT(bdata_list); > @@ -146,8 +145,8 @@ unsigned long __init init_bootmem(unsigned long start, unsigned long pages) > ? ? ? ?min_low_pfn = start; > ? ? ? ?return init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages); > ?} > -#endif > -/* > + > +/** > ?* free_bootmem_late - free bootmem pages directly to page allocator > ?* @addr: starting address of the range > ?* @size: size of the range in bytes > @@ -171,53 +170,6 @@ void __init free_bootmem_late(unsigned long addr, unsigned long size) > ? ? ? ?} > ?} > > -#ifdef CONFIG_NO_BOOTMEM > -static void __init __free_pages_memory(unsigned long start, unsigned long end) > -{ > - ? ? ? int i; > - ? ? ? unsigned long start_aligned, end_aligned; > - ? ? ? int order = ilog2(BITS_PER_LONG); > - > - ? ? ? start_aligned = (start + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1); > - ? ? ? end_aligned = end & ~(BITS_PER_LONG - 1); > - > - ? ? ? if (end_aligned <= start_aligned) { > - ? ? ? ? ? ? ? for (i = start; i < end; i++) > - ? ? ? ? ? ? ? ? ? ? ? __free_pages_bootmem(pfn_to_page(i), 0); > - > - ? ? ? ? ? ? ? return; > - ? ? ? } > - > - ? ? ? for (i = start; i < start_aligned; i++) > - ? ? ? ? ? ? ? __free_pages_bootmem(pfn_to_page(i), 0); > - > - ? ? ? for (i = start_aligned; i < end_aligned; i += BITS_PER_LONG) > - ? ? ? ? ? ? ? __free_pages_bootmem(pfn_to_page(i), order); > - > - ? ? ? for (i = end_aligned; i < end; i++) > - ? ? ? ? ? ? ? __free_pages_bootmem(pfn_to_page(i), 0); > -} > - > -unsigned long __init free_all_memory_core_early(int nodeid) > -{ > - ? ? ? int i; > - ? ? ? u64 start, end; > - ? ? ? unsigned long count = 0; > - ? ? ? struct range *range = NULL; > - ? ? ? int nr_range; > - > - ? ? ? nr_range = get_free_all_memory_range(&range, nodeid); > - > - ? ? ? for (i = 0; i < nr_range; i++) { > - ? ? ? ? ? ? ? start = range[i].start; > - ? ? ? ? ? ? ? end = range[i].end; > - ? ? ? ? ? ? ? count += end - start; > - ? ? ? ? ? ? ? __free_pages_memory(start, end); > - ? ? ? } > - > - ? ? ? return count; > -} > -#else > ?static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) > ?{ > ? ? ? ?int aligned; > @@ -278,7 +230,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) > > ? ? ? ?return count; > ?} > -#endif > > ?/** > ?* free_all_bootmem_node - release a node's free pages to the buddy allocator > @@ -289,12 +240,7 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) > ?unsigned long __init free_all_bootmem_node(pg_data_t *pgdat) > ?{ > ? ? ? ?register_page_bootmem_info_node(pgdat); > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? /* free_all_memory_core_early(MAX_NUMNODES) will be called later */ > - ? ? ? return 0; > -#else > ? ? ? ?return free_all_bootmem_core(pgdat->bdata); > -#endif > ?} > > ?/** > @@ -304,16 +250,6 @@ unsigned long __init free_all_bootmem_node(pg_data_t *pgdat) > ?*/ > ?unsigned long __init free_all_bootmem(void) > ?{ > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? /* > - ? ? ? ?* We need to use MAX_NUMNODES instead of NODE_DATA(0)->node_id > - ? ? ? ?* ?because in some case like Node0 doesnt have RAM installed > - ? ? ? ?* ?low ram will be on Node1 > - ? ? ? ?* Use MAX_NUMNODES will make sure all ranges in early_node_map[] > - ? ? ? ?* ?will be used instead of only Node0 related > - ? ? ? ?*/ > - ? ? ? return free_all_memory_core_early(MAX_NUMNODES); > -#else > ? ? ? ?unsigned long total_pages = 0; > ? ? ? ?bootmem_data_t *bdata; > > @@ -321,10 +257,8 @@ unsigned long __init free_all_bootmem(void) > ? ? ? ? ? ? ? ?total_pages += free_all_bootmem_core(bdata); > > ? ? ? ?return total_pages; > -#endif > ?} > > -#ifndef CONFIG_NO_BOOTMEM > ?static void __init __free(bootmem_data_t *bdata, > ? ? ? ? ? ? ? ? ? ? ? ?unsigned long sidx, unsigned long eidx) > ?{ > @@ -419,7 +353,6 @@ static int __init mark_bootmem(unsigned long start, unsigned long end, > ? ? ? ?} > ? ? ? ?BUG(); > ?} > -#endif > > ?/** > ?* free_bootmem_node - mark a page range as usable > @@ -434,10 +367,6 @@ static int __init mark_bootmem(unsigned long start, unsigned long end, > ?void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long size) > ?{ > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? kmemleak_free_part(__va(physaddr), size); > - ? ? ? memblock_x86_free_range(physaddr, physaddr + size); > -#else > ? ? ? ?unsigned long start, end; > > ? ? ? ?kmemleak_free_part(__va(physaddr), size); > @@ -446,7 +375,6 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, > ? ? ? ?end = PFN_DOWN(physaddr + size); > > ? ? ? ?mark_bootmem_node(pgdat->bdata, start, end, 0, 0); > -#endif > ?} > > ?/** > @@ -460,10 +388,6 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, > ?*/ > ?void __init free_bootmem(unsigned long addr, unsigned long size) > ?{ > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? kmemleak_free_part(__va(addr), size); > - ? ? ? memblock_x86_free_range(addr, addr + size); > -#else > ? ? ? ?unsigned long start, end; > > ? ? ? ?kmemleak_free_part(__va(addr), size); > @@ -472,7 +396,6 @@ void __init free_bootmem(unsigned long addr, unsigned long size) > ? ? ? ?end = PFN_DOWN(addr + size); > > ? ? ? ?mark_bootmem(start, end, 0, 0); > -#endif > ?} > > ?/** > @@ -489,17 +412,12 @@ void __init free_bootmem(unsigned long addr, unsigned long size) > ?int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long size, int flags) > ?{ > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? panic("no bootmem"); > - ? ? ? return 0; > -#else > ? ? ? ?unsigned long start, end; > > ? ? ? ?start = PFN_DOWN(physaddr); > ? ? ? ?end = PFN_UP(physaddr + size); > > ? ? ? ?return mark_bootmem_node(pgdat->bdata, start, end, 1, flags); > -#endif > ?} > > ?/** > @@ -515,20 +433,14 @@ int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, > ?int __init reserve_bootmem(unsigned long addr, unsigned long size, > ? ? ? ? ? ? ? ? ? ? ? ? ? ?int flags) > ?{ > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? panic("no bootmem"); > - ? ? ? return 0; > -#else > ? ? ? ?unsigned long start, end; > > ? ? ? ?start = PFN_DOWN(addr); > ? ? ? ?end = PFN_UP(addr + size); > > ? ? ? ?return mark_bootmem(start, end, 1, flags); > -#endif > ?} > > -#ifndef CONFIG_NO_BOOTMEM > ?int __weak __init reserve_bootmem_generic(unsigned long phys, unsigned long len, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int flags) > ?{ > @@ -685,33 +597,12 @@ static void * __init alloc_arch_preferred_bootmem(bootmem_data_t *bdata, > ?#endif > ? ? ? ?return NULL; > ?} > -#endif > > ?static void * __init ___alloc_bootmem_nopanic(unsigned long size, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long align, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long goal, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long limit) > ?{ > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? void *ptr; > - > - ? ? ? if (WARN_ON_ONCE(slab_is_available())) > - ? ? ? ? ? ? ? return kzalloc(size, GFP_NOWAIT); > - > -restart: > - > - ? ? ? ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, goal, limit); > - > - ? ? ? if (ptr) > - ? ? ? ? ? ? ? return ptr; > - > - ? ? ? if (goal != 0) { > - ? ? ? ? ? ? ? goal = 0; > - ? ? ? ? ? ? ? goto restart; > - ? ? ? } > - > - ? ? ? return NULL; > -#else > ? ? ? ?bootmem_data_t *bdata; > ? ? ? ?void *region; > > @@ -737,7 +628,6 @@ restart: > ? ? ? ?} > > ? ? ? ?return NULL; > -#endif > ?} > > ?/** > @@ -758,10 +648,6 @@ void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align, > ?{ > ? ? ? ?unsigned long limit = 0; > > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? limit = -1UL; > -#endif > - > ? ? ? ?return ___alloc_bootmem_nopanic(size, align, goal, limit); > ?} > > @@ -798,14 +684,9 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align, > ?{ > ? ? ? ?unsigned long limit = 0; > > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? limit = -1UL; > -#endif > - > ? ? ? ?return ___alloc_bootmem(size, align, goal, limit); > ?} > > -#ifndef CONFIG_NO_BOOTMEM > ?static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long size, unsigned long align, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long goal, unsigned long limit) > @@ -822,7 +703,6 @@ static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata, > > ? ? ? ?return ___alloc_bootmem(size, align, goal, limit); > ?} > -#endif > > ?/** > ?* __alloc_bootmem_node - allocate boot memory from a specific node > @@ -847,17 +727,7 @@ void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, > ? ? ? ?if (WARN_ON_ONCE(slab_is_available())) > ? ? ? ? ? ? ? ?return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); > > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? ptr = __alloc_memory_core_early(pgdat->node_id, size, align, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goal, -1ULL); > - ? ? ? if (ptr) > - ? ? ? ? ? ? ? return ptr; > - > - ? ? ? ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goal, -1ULL); > -#else > ? ? ? ?ptr = ___alloc_bootmem_node(pgdat->bdata, size, align, goal, 0); > -#endif > > ? ? ? ?return ptr; > ?} > @@ -880,13 +750,8 @@ void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size, > ? ? ? ? ? ? ? ?unsigned long new_goal; > > ? ? ? ? ? ? ? ?new_goal = MAX_DMA32_PFN << PAGE_SHIFT; > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? ? ? ? ? ptr = ?__alloc_memory_core_early(pgdat->node_id, size, align, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?new_goal, -1ULL); > -#else > ? ? ? ? ? ? ? ?ptr = alloc_bootmem_core(pgdat->bdata, size, align, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? new_goal, 0); > -#endif > ? ? ? ? ? ? ? ?if (ptr) > ? ? ? ? ? ? ? ? ? ? ? ?return ptr; > ? ? ? ?} > @@ -907,16 +772,6 @@ void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size, > ?void * __init alloc_bootmem_section(unsigned long size, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long section_nr) > ?{ > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? unsigned long pfn, goal, limit; > - > - ? ? ? pfn = section_nr_to_pfn(section_nr); > - ? ? ? goal = pfn << PAGE_SHIFT; > - ? ? ? limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT; > - > - ? ? ? return __alloc_memory_core_early(early_pfn_to_nid(pfn), size, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SMP_CACHE_BYTES, goal, limit); > -#else > ? ? ? ?bootmem_data_t *bdata; > ? ? ? ?unsigned long pfn, goal, limit; > > @@ -926,7 +781,6 @@ void * __init alloc_bootmem_section(unsigned long size, > ? ? ? ?bdata = &bootmem_node_data[early_pfn_to_nid(pfn)]; > > ? ? ? ?return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit); > -#endif > ?} > ?#endif > > @@ -938,16 +792,11 @@ void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size, > ? ? ? ?if (WARN_ON_ONCE(slab_is_available())) > ? ? ? ? ? ? ? ?return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); > > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? ptr = ?__alloc_memory_core_early(pgdat->node_id, size, align, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goal, -1ULL); > -#else > ? ? ? ?ptr = alloc_arch_preferred_bootmem(pgdat->bdata, size, align, goal, 0); > ? ? ? ?if (ptr) > ? ? ? ? ? ? ? ?return ptr; > > ? ? ? ?ptr = alloc_bootmem_core(pgdat->bdata, size, align, goal, 0); > -#endif > ? ? ? ?if (ptr) > ? ? ? ? ? ? ? ?return ptr; > > @@ -1000,16 +849,7 @@ void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size, > ? ? ? ?if (WARN_ON_ONCE(slab_is_available())) > ? ? ? ? ? ? ? ?return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); > > -#ifdef CONFIG_NO_BOOTMEM > - ? ? ? ptr = __alloc_memory_core_early(pgdat->node_id, size, align, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? goal, ARCH_LOW_ADDRESS_LIMIT); > - ? ? ? if (ptr) > - ? ? ? ? ? ? ? return ptr; > - ? ? ? ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? goal, ARCH_LOW_ADDRESS_LIMIT); > -#else > ? ? ? ?ptr = ___alloc_bootmem_node(pgdat->bdata, size, align, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goal, ARCH_LOW_ADDRESS_LIMIT); > -#endif > ? ? ? ?return ptr; > ?} > diff --git a/mm/nobootmem.c b/mm/nobootmem.c > new file mode 100644 > index 000000000000..e93c3475011b > --- /dev/null > +++ b/mm/nobootmem.c > @@ -0,0 +1,445 @@ > +/* > + * ?nobootmem - A boot-time physical memory allocator and configurator > + * > + * ?Copyright (C) 1999 Ingo Molnar > + * ? ? ? ? ? ? ? ?1999 Kanoj Sarcar, SGI > + * ? ? ? ? ? ? ? ?2008 Johannes Weiner > + * > + * ?Split out of bootmem.c by Namhyung Kim > + * > + * Access to this subsystem has to be serialized externally (which is true > + * for the boot process anyway). > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include "internal.h" > + > +unsigned long max_low_pfn; > +unsigned long min_low_pfn; > +unsigned long max_pfn; > + > +#ifdef CONFIG_CRASH_DUMP > +/* > + * If we have booted due to a crash, max_pfn will be a very low value. We need > + * to know the amount of memory that the previous kernel used. > + */ > +unsigned long saved_max_pfn; > +#endif > + > +/** > + * free_bootmem_late - free bootmem pages directly to page allocator > + * @addr: starting address of the range > + * @size: size of the range in bytes > + * > + * This is only useful when the bootmem allocator has already been torn > + * down, but we are still initializing the system. ?Pages are given directly > + * to the page allocator, no bootmem metadata is updated because it is gone. > + */ > +void __init free_bootmem_late(unsigned long addr, unsigned long size) > +{ > + ? ? ? unsigned long cursor, end; > + > + ? ? ? kmemleak_free_part(__va(addr), size); > + > + ? ? ? cursor = PFN_UP(addr); > + ? ? ? end = PFN_DOWN(addr + size); > + > + ? ? ? for (; cursor < end; cursor++) { > + ? ? ? ? ? ? ? __free_pages_bootmem(pfn_to_page(cursor), 0); > + ? ? ? ? ? ? ? totalram_pages++; > + ? ? ? } > +} > + > +static void __init __free_pages_memory(unsigned long start, unsigned long end) > +{ > + ? ? ? int i; > + ? ? ? unsigned long start_aligned, end_aligned; > + ? ? ? int order = ilog2(BITS_PER_LONG); > + > + ? ? ? start_aligned = (start + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1); > + ? ? ? end_aligned = end & ~(BITS_PER_LONG - 1); > + > + ? ? ? if (end_aligned <= start_aligned) { > + ? ? ? ? ? ? ? for (i = start; i < end; i++) > + ? ? ? ? ? ? ? ? ? ? ? __free_pages_bootmem(pfn_to_page(i), 0); > + > + ? ? ? ? ? ? ? return; > + ? ? ? } > + > + ? ? ? for (i = start; i < start_aligned; i++) > + ? ? ? ? ? ? ? __free_pages_bootmem(pfn_to_page(i), 0); > + > + ? ? ? for (i = start_aligned; i < end_aligned; i += BITS_PER_LONG) > + ? ? ? ? ? ? ? __free_pages_bootmem(pfn_to_page(i), order); > + > + ? ? ? for (i = end_aligned; i < end; i++) > + ? ? ? ? ? ? ? __free_pages_bootmem(pfn_to_page(i), 0); > +} > + > +unsigned long __init free_all_memory_core_early(int nodeid) > +{ > + ? ? ? int i; > + ? ? ? u64 start, end; > + ? ? ? unsigned long count = 0; > + ? ? ? struct range *range = NULL; > + ? ? ? int nr_range; > + > + ? ? ? nr_range = get_free_all_memory_range(&range, nodeid); > + > + ? ? ? for (i = 0; i < nr_range; i++) { > + ? ? ? ? ? ? ? start = range[i].start; > + ? ? ? ? ? ? ? end = range[i].end; > + ? ? ? ? ? ? ? count += end - start; > + ? ? ? ? ? ? ? __free_pages_memory(start, end); > + ? ? ? } > + > + ? ? ? return count; > +} > + > +/** > + * free_all_bootmem_node - release a node's free pages to the buddy allocator > + * @pgdat: node to be released > + * > + * Returns the number of pages actually released. > + */ > +unsigned long __init free_all_bootmem_node(pg_data_t *pgdat) > +{ > + ? ? ? register_page_bootmem_info_node(pgdat); > + > + ? ? ? /* free_all_memory_core_early(MAX_NUMNODES) will be called later */ > + ? ? ? return 0; > +} > + > +/** > + * free_all_bootmem - release free pages to the buddy allocator > + * > + * Returns the number of pages actually released. > + */ > +unsigned long __init free_all_bootmem(void) > +{ > + ? ? ? /* > + ? ? ? ?* We need to use MAX_NUMNODES instead of NODE_DATA(0)->node_id > + ? ? ? ?* ?because in some case like Node0 doesnt have RAM installed > + ? ? ? ?* ?low ram will be on Node1 > + ? ? ? ?* Use MAX_NUMNODES will make sure all ranges in early_node_map[] > + ? ? ? ?* ?will be used instead of only Node0 related > + ? ? ? ?*/ > + ? ? ? return free_all_memory_core_early(MAX_NUMNODES); > +} > + > +/** > + * free_bootmem_node - mark a page range as usable > + * @pgdat: node the range resides on > + * @physaddr: starting address of the range > + * @size: size of the range in bytes > + * > + * Partial pages will be considered reserved and left as they are. > + * > + * The range must reside completely on the specified node. > + */ > +void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long size) > +{ > + ? ? ? kmemleak_free_part(__va(physaddr), size); > + ? ? ? memblock_x86_free_range(physaddr, physaddr + size); > +} > + > +/** > + * free_bootmem - mark a page range as usable > + * @addr: starting address of the range > + * @size: size of the range in bytes > + * > + * Partial pages will be considered reserved and left as they are. > + * > + * The range must be contiguous but may span node boundaries. > + */ > +void __init free_bootmem(unsigned long addr, unsigned long size) > +{ > + ? ? ? kmemleak_free_part(__va(addr), size); > + ? ? ? memblock_x86_free_range(addr, addr + size); > +} > + > +/** > + * reserve_bootmem_node - mark a page range as reserved > + * @pgdat: node the range resides on > + * @physaddr: starting address of the range > + * @size: size of the range in bytes > + * @flags: reservation flags (see linux/bootmem.h) > + * > + * Partial pages will be reserved. > + * > + * The range must reside completely on the specified node. > + */ > +int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long size, int flags) > +{ > + ? ? ? panic("no bootmem"); > + ? ? ? return 0; > +} > + > +/** > + * reserve_bootmem - mark a page range as usable > + * @addr: starting address of the range > + * @size: size of the range in bytes > + * @flags: reservation flags (see linux/bootmem.h) > + * > + * Partial pages will be reserved. > + * > + * The range must be contiguous but may span node boundaries. > + */ > +int __init reserve_bootmem(unsigned long addr, unsigned long size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? int flags) > +{ > + ? ? ? panic("no bootmem"); > + ? ? ? return 0; > +} > + > +static void * __init ___alloc_bootmem_nopanic(unsigned long size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long align, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long goal, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long limit) > +{ > + ? ? ? void *ptr; > + > + ? ? ? if (WARN_ON_ONCE(slab_is_available())) > + ? ? ? ? ? ? ? return kzalloc(size, GFP_NOWAIT); > + > +restart: > + > + ? ? ? ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, goal, limit); > + > + ? ? ? if (ptr) > + ? ? ? ? ? ? ? return ptr; > + > + ? ? ? if (goal != 0) { > + ? ? ? ? ? ? ? goal = 0; > + ? ? ? ? ? ? ? goto restart; > + ? ? ? } > + > + ? ? ? return NULL; > +} > + > +/** > + * __alloc_bootmem_nopanic - allocate boot memory without panicking > + * @size: size of the request in bytes > + * @align: alignment of the region > + * @goal: preferred starting address of the region > + * > + * The goal is dropped if it can not be satisfied and the allocation will > + * fall back to memory below @goal. > + * > + * Allocation may happen on any node in the system. > + * > + * Returns NULL on failure. > + */ > +void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long goal) > +{ > + ? ? ? unsigned long limit = -1UL; > + > + ? ? ? return ___alloc_bootmem_nopanic(size, align, goal, limit); > +} > + > +static void * __init ___alloc_bootmem(unsigned long size, unsigned long align, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long goal, unsigned long limit) > +{ > + ? ? ? void *mem = ___alloc_bootmem_nopanic(size, align, goal, limit); > + > + ? ? ? if (mem) > + ? ? ? ? ? ? ? return mem; > + ? ? ? /* > + ? ? ? ?* Whoops, we cannot satisfy the allocation request. > + ? ? ? ?*/ > + ? ? ? printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size); > + ? ? ? panic("Out of memory"); > + ? ? ? return NULL; > +} > + > +/** > + * __alloc_bootmem - allocate boot memory > + * @size: size of the request in bytes > + * @align: alignment of the region > + * @goal: preferred starting address of the region > + * > + * The goal is dropped if it can not be satisfied and the allocation will > + * fall back to memory below @goal. > + * > + * Allocation may happen on any node in the system. > + * > + * The function panics if the request can not be satisfied. > + */ > +void * __init __alloc_bootmem(unsigned long size, unsigned long align, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long goal) > +{ > + ? ? ? unsigned long limit = -1UL; > + > + ? ? ? return ___alloc_bootmem(size, align, goal, limit); > +} > + > +/** > + * __alloc_bootmem_node - allocate boot memory from a specific node > + * @pgdat: node to allocate from > + * @size: size of the request in bytes > + * @align: alignment of the region > + * @goal: preferred starting address of the region > + * > + * The goal is dropped if it can not be satisfied and the allocation will > + * fall back to memory below @goal. > + * > + * Allocation may fall back to any node in the system if the specified node > + * can not hold the requested memory. > + * > + * The function panics if the request can not be satisfied. > + */ > +void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long align, unsigned long goal) > +{ > + ? ? ? void *ptr; > + > + ? ? ? if (WARN_ON_ONCE(slab_is_available())) > + ? ? ? ? ? ? ? return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); > + > + ? ? ? ptr = __alloc_memory_core_early(pgdat->node_id, size, align, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goal, -1ULL); > + ? ? ? if (ptr) > + ? ? ? ? ? ? ? return ptr; > + > + ? ? ? ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goal, -1ULL); > + > + ? ? ? return ptr; > +} > + > +void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long align, unsigned long goal) > +{ > +#ifdef MAX_DMA32_PFN > + ? ? ? unsigned long end_pfn; > + > + ? ? ? if (WARN_ON_ONCE(slab_is_available())) > + ? ? ? ? ? ? ? return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); > + > + ? ? ? /* update goal according ...MAX_DMA32_PFN */ > + ? ? ? end_pfn = pgdat->node_start_pfn + pgdat->node_spanned_pages; > + > + ? ? ? if (end_pfn > MAX_DMA32_PFN + (128 >> (20 - PAGE_SHIFT)) && > + ? ? ? ? ? (goal >> PAGE_SHIFT) < MAX_DMA32_PFN) { > + ? ? ? ? ? ? ? void *ptr; > + ? ? ? ? ? ? ? unsigned long new_goal; > + > + ? ? ? ? ? ? ? new_goal = MAX_DMA32_PFN << PAGE_SHIFT; > + ? ? ? ? ? ? ? ptr = ?__alloc_memory_core_early(pgdat->node_id, size, align, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?new_goal, -1ULL); > + ? ? ? ? ? ? ? if (ptr) > + ? ? ? ? ? ? ? ? ? ? ? return ptr; > + ? ? ? } > +#endif > + > + ? ? ? return __alloc_bootmem_node(pgdat, size, align, goal); > + > +} > + > +#ifdef CONFIG_SPARSEMEM > +/** > + * alloc_bootmem_section - allocate boot memory from a specific section > + * @size: size of the request in bytes > + * @section_nr: sparse map section to allocate from > + * > + * Return NULL on failure. > + */ > +void * __init alloc_bootmem_section(unsigned long size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long section_nr) > +{ > + ? ? ? unsigned long pfn, goal, limit; > + > + ? ? ? pfn = section_nr_to_pfn(section_nr); > + ? ? ? goal = pfn << PAGE_SHIFT; > + ? ? ? limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT; > + > + ? ? ? return __alloc_memory_core_early(early_pfn_to_nid(pfn), size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SMP_CACHE_BYTES, goal, limit); > +} > +#endif > + > +void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long align, unsigned long goal) > +{ > + ? ? ? void *ptr; > + > + ? ? ? if (WARN_ON_ONCE(slab_is_available())) > + ? ? ? ? ? ? ? return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); > + > + ? ? ? ptr = ?__alloc_memory_core_early(pgdat->node_id, size, align, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goal, -1ULL); > + ? ? ? if (ptr) > + ? ? ? ? ? ? ? return ptr; > + > + ? ? ? return __alloc_bootmem_nopanic(size, align, goal); > +} > + > +#ifndef ARCH_LOW_ADDRESS_LIMIT > +#define ARCH_LOW_ADDRESS_LIMIT 0xffffffffUL > +#endif > + > +/** > + * __alloc_bootmem_low - allocate low boot memory > + * @size: size of the request in bytes > + * @align: alignment of the region > + * @goal: preferred starting address of the region > + * > + * The goal is dropped if it can not be satisfied and the allocation will > + * fall back to memory below @goal. > + * > + * Allocation may happen on any node in the system. > + * > + * The function panics if the request can not be satisfied. > + */ > +void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long goal) > +{ > + ? ? ? return ___alloc_bootmem(size, align, goal, ARCH_LOW_ADDRESS_LIMIT); > +} > + > +/** > + * __alloc_bootmem_low_node - allocate low boot memory from a specific node > + * @pgdat: node to allocate from > + * @size: size of the request in bytes > + * @align: alignment of the region > + * @goal: preferred starting address of the region > + * > + * The goal is dropped if it can not be satisfied and the allocation will > + * fall back to memory below @goal. > + * > + * Allocation may fall back to any node in the system if the specified node > + * can not hold the requested memory. > + * > + * The function panics if the request can not be satisfied. > + */ > +void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long align, unsigned long goal) > +{ > + ? ? ? void *ptr; > + > + ? ? ? if (WARN_ON_ONCE(slab_is_available())) > + ? ? ? ? ? ? ? return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); > + > + ? ? ? ptr = __alloc_memory_core_early(pgdat->node_id, size, align, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? goal, ARCH_LOW_ADDRESS_LIMIT); > + ? ? ? if (ptr) > + ? ? ? ? ? ? ? return ptr; > + > + ? ? ? ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? goal, ARCH_LOW_ADDRESS_LIMIT); > + ? ? ? return ptr; > +} > -- > 1.7.3.4.600.g982838b0 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at ?http://vger.kernel.org/majordomo-info.html > Please read the FAQ at ?http://www.tux.org/lkml/ > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/