On Mon, Jan 14, 2019 at 3:51 PM Mike Rapoport <rppt@xxxxxxxxxxxxx> wrote: > > Hi Pingfan, > > On Fri, Jan 11, 2019 at 01:12:53PM +0800, Pingfan Liu wrote: > > During boot time, there is requirement to tell whether a series of func > > call will consume memory or not. For some reason, a temporary memory > > resource can be loan to those func through memblock allocator, but at a > > check point, all of the loan memory should be turned back. > > A typical using style: > > -1. find a usable range by memblock_find_in_range(), said, [A,B] > > -2. before calling a series of func, memblock_set_current_limit(A,B,true) > > -3. call funcs > > -4. memblock_find_in_range(A,B,B-A,1), if failed, then some memory is not > > turned back. > > -5. reset the original limit > > > > E.g. in the case of hotmovable memory, some acpi routines should be called, > > and they are not allowed to own some movable memory. Although at present > > these functions do not consume memory, but later, if changed without > > awareness, they may do. With the above method, the allocation can be > > detected, and pr_warn() to ask people to resolve it. > > To ensure there were that a sequence of function calls didn't create new > memblock allocations you can simply check the number of the reserved > regions before and after that sequence. > Yes, thank you point out it. > Still, I'm not sure it would be practical to try tracking what code that's called > from x86::setup_arch() did memory allocation. > Probably a better approach is to verify no memory ended up in the movable > areas after their extents are known. > It is a probability problem whether allocated memory sit on hotmovable memory or not. And if warning based on the verification, then it is also a probability problem and maybe we will miss it. Thanks and regards, Pingfan > > Signed-off-by: Pingfan Liu <kernelfans@xxxxxxxxx> > > Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > > Cc: Ingo Molnar <mingo@xxxxxxxxxx> > > Cc: Borislav Petkov <bp@xxxxxxxxx> > > Cc: "H. Peter Anvin" <hpa@xxxxxxxxx> > > Cc: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx> > > Cc: Andy Lutomirski <luto@xxxxxxxxxx> > > Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx> > > Cc: "Rafael J. Wysocki" <rjw@xxxxxxxxxxxxx> > > Cc: Len Brown <lenb@xxxxxxxxxx> > > Cc: Yinghai Lu <yinghai@xxxxxxxxxx> > > Cc: Tejun Heo <tj@xxxxxxxxxx> > > Cc: Chao Fan <fanc.fnst@xxxxxxxxxxxxxx> > > Cc: Baoquan He <bhe@xxxxxxxxxx> > > Cc: Juergen Gross <jgross@xxxxxxxx> > > Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> > > Cc: Mike Rapoport <rppt@xxxxxxxxxxxxxxxxxx> > > Cc: Vlastimil Babka <vbabka@xxxxxxx> > > Cc: Michal Hocko <mhocko@xxxxxxxx> > > Cc: x86@xxxxxxxxxx > > Cc: linux-acpi@xxxxxxxxxxxxxxx > > Cc: linux-mm@xxxxxxxxx > > --- > > arch/arm/mm/init.c | 3 ++- > > arch/arm/mm/mmu.c | 4 ++-- > > arch/arm/mm/nommu.c | 2 +- > > arch/csky/kernel/setup.c | 2 +- > > arch/microblaze/mm/init.c | 2 +- > > arch/mips/kernel/setup.c | 2 +- > > arch/powerpc/mm/40x_mmu.c | 6 ++++-- > > arch/powerpc/mm/44x_mmu.c | 2 +- > > arch/powerpc/mm/8xx_mmu.c | 2 +- > > arch/powerpc/mm/fsl_booke_mmu.c | 5 +++-- > > arch/powerpc/mm/hash_utils_64.c | 4 ++-- > > arch/powerpc/mm/init_32.c | 2 +- > > arch/powerpc/mm/pgtable-radix.c | 2 +- > > arch/powerpc/mm/ppc_mmu_32.c | 8 ++++++-- > > arch/powerpc/mm/tlb_nohash.c | 6 ++++-- > > arch/unicore32/mm/mmu.c | 2 +- > > arch/x86/kernel/setup.c | 2 +- > > arch/xtensa/mm/init.c | 2 +- > > include/linux/memblock.h | 10 +++++++--- > > mm/memblock.c | 23 ++++++++++++++++++----- > > 20 files changed, 59 insertions(+), 32 deletions(-) > > > > diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c > > index 32e4845..58a4342 100644 > > --- a/arch/arm/mm/init.c > > +++ b/arch/arm/mm/init.c > > @@ -93,7 +93,8 @@ __tagtable(ATAG_INITRD2, parse_tag_initrd2); > > static void __init find_limits(unsigned long *min, unsigned long *max_low, > > unsigned long *max_high) > > { > > - *max_low = PFN_DOWN(memblock_get_current_limit()); > > + memblock_get_current_limit(NULL, max_low); > > + *max_low = PFN_DOWN(*max_low); > > *min = PFN_UP(memblock_start_of_DRAM()); > > *max_high = PFN_DOWN(memblock_end_of_DRAM()); > > } > > diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c > > index f5cc1cc..9025418 100644 > > --- a/arch/arm/mm/mmu.c > > +++ b/arch/arm/mm/mmu.c > > @@ -1240,7 +1240,7 @@ void __init adjust_lowmem_bounds(void) > > } > > } > > > > - memblock_set_current_limit(memblock_limit); > > + memblock_set_current_limit(0, memblock_limit, false); > > } > > > > static inline void prepare_page_table(void) > > @@ -1625,7 +1625,7 @@ void __init paging_init(const struct machine_desc *mdesc) > > > > prepare_page_table(); > > map_lowmem(); > > - memblock_set_current_limit(arm_lowmem_limit); > > + memblock_set_current_limit(0, arm_lowmem_limit, false); > > dma_contiguous_remap(); > > early_fixmap_shutdown(); > > devicemaps_init(mdesc); > > diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c > > index 7d67c70..721535c 100644 > > --- a/arch/arm/mm/nommu.c > > +++ b/arch/arm/mm/nommu.c > > @@ -138,7 +138,7 @@ void __init adjust_lowmem_bounds(void) > > adjust_lowmem_bounds_mpu(); > > end = memblock_end_of_DRAM(); > > high_memory = __va(end - 1) + 1; > > - memblock_set_current_limit(end); > > + memblock_set_current_limit(0, end, false); > > } > > > > /* > > diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c > > index dff8b89..e6f88bf 100644 > > --- a/arch/csky/kernel/setup.c > > +++ b/arch/csky/kernel/setup.c > > @@ -100,7 +100,7 @@ static void __init csky_memblock_init(void) > > > > highend_pfn = max_pfn; > > #endif > > - memblock_set_current_limit(PFN_PHYS(max_low_pfn)); > > + memblock_set_current_limit(0, PFN_PHYS(max_low_pfn), false); > > > > dma_contiguous_reserve(0); > > > > diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c > > index b17fd8a..cee99da 100644 > > --- a/arch/microblaze/mm/init.c > > +++ b/arch/microblaze/mm/init.c > > @@ -353,7 +353,7 @@ asmlinkage void __init mmu_init(void) > > /* Shortly after that, the entire linear mapping will be available */ > > /* This will also cause that unflatten device tree will be allocated > > * inside 768MB limit */ > > - memblock_set_current_limit(memory_start + lowmem_size - 1); > > + memblock_set_current_limit(0, memory_start + lowmem_size - 1, false); > > } > > > > /* This is only called until mem_init is done. */ > > diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c > > index 8c6c48ed..62dabe1 100644 > > --- a/arch/mips/kernel/setup.c > > +++ b/arch/mips/kernel/setup.c > > @@ -862,7 +862,7 @@ static void __init arch_mem_init(char **cmdline_p) > > * with memblock_reserve; memblock_alloc* can be used > > * only after this point > > */ > > - memblock_set_current_limit(PFN_PHYS(max_low_pfn)); > > + memblock_set_current_limit(0, PFN_PHYS(max_low_pfn), false); > > > > #ifdef CONFIG_PROC_VMCORE > > if (setup_elfcorehdr && setup_elfcorehdr_size) { > > diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c > > index 61ac468..427bb56 100644 > > --- a/arch/powerpc/mm/40x_mmu.c > > +++ b/arch/powerpc/mm/40x_mmu.c > > @@ -141,7 +141,7 @@ unsigned long __init mmu_mapin_ram(unsigned long top) > > * coverage with normal-sized pages (or other reasons) do not > > * attempt to allocate outside the allowed range. > > */ > > - memblock_set_current_limit(mapped); > > + memblock_set_current_limit(0, mapped, false); > > > > return mapped; > > } > > @@ -155,5 +155,7 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base, > > BUG_ON(first_memblock_base != 0); > > > > /* 40x can only access 16MB at the moment (see head_40x.S) */ > > - memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000)); > > + memblock_set_current_limit(0, > > + min_t(u64, first_memblock_size, 0x00800000), > > + false); > > } > > diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c > > index 12d9251..3cf127d 100644 > > --- a/arch/powerpc/mm/44x_mmu.c > > +++ b/arch/powerpc/mm/44x_mmu.c > > @@ -225,7 +225,7 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base, > > > > /* 44x has a 256M TLB entry pinned at boot */ > > size = (min_t(u64, first_memblock_size, PPC_PIN_SIZE)); > > - memblock_set_current_limit(first_memblock_base + size); > > + memblock_set_current_limit(0, first_memblock_base + size, false); > > } > > > > #ifdef CONFIG_SMP > > diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c > > index 01b7f51..c75bca6 100644 > > --- a/arch/powerpc/mm/8xx_mmu.c > > +++ b/arch/powerpc/mm/8xx_mmu.c > > @@ -135,7 +135,7 @@ unsigned long __init mmu_mapin_ram(unsigned long top) > > * attempt to allocate outside the allowed range. > > */ > > if (mapped) > > - memblock_set_current_limit(mapped); > > + memblock_set_current_limit(0, mapped, false); > > > > block_mapped_ram = mapped; > > > > diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c > > index 080d49b..3be24b8 100644 > > --- a/arch/powerpc/mm/fsl_booke_mmu.c > > +++ b/arch/powerpc/mm/fsl_booke_mmu.c > > @@ -252,7 +252,8 @@ void __init adjust_total_lowmem(void) > > pr_cont("%lu Mb, residual: %dMb\n", tlbcam_sz(tlbcam_index - 1) >> 20, > > (unsigned int)((total_lowmem - __max_low_memory) >> 20)); > > > > - memblock_set_current_limit(memstart_addr + __max_low_memory); > > + memblock_set_current_limit(0, > > + memstart_addr + __max_low_memory, false); > > } > > > > void setup_initial_memory_limit(phys_addr_t first_memblock_base, > > @@ -261,7 +262,7 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base, > > phys_addr_t limit = first_memblock_base + first_memblock_size; > > > > /* 64M mapped initially according to head_fsl_booke.S */ > > - memblock_set_current_limit(min_t(u64, limit, 0x04000000)); > > + memblock_set_current_limit(0, min_t(u64, limit, 0x04000000), false); > > } > > > > #ifdef CONFIG_RELOCATABLE > > diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c > > index 0cc7fbc..30fba80 100644 > > --- a/arch/powerpc/mm/hash_utils_64.c > > +++ b/arch/powerpc/mm/hash_utils_64.c > > @@ -925,7 +925,7 @@ static void __init htab_initialize(void) > > BUG_ON(htab_bolt_mapping(base, base + size, __pa(base), > > prot, mmu_linear_psize, mmu_kernel_ssize)); > > } > > - memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE); > > + memblock_set_current_limit(0, MEMBLOCK_ALLOC_ANYWHERE, false); > > > > /* > > * If we have a memory_limit and we've allocated TCEs then we need to > > @@ -1867,7 +1867,7 @@ void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base, > > ppc64_rma_size = min_t(u64, ppc64_rma_size, 0x40000000); > > > > /* Finally limit subsequent allocations */ > > - memblock_set_current_limit(ppc64_rma_size); > > + memblock_set_current_limit(0, ppc64_rma_size, false); > > } else { > > ppc64_rma_size = ULONG_MAX; > > } > > diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c > > index 3e59e5d..863d710 100644 > > --- a/arch/powerpc/mm/init_32.c > > +++ b/arch/powerpc/mm/init_32.c > > @@ -183,5 +183,5 @@ void __init MMU_init(void) > > #endif > > > > /* Shortly after that, the entire linear mapping will be available */ > > - memblock_set_current_limit(lowmem_end_addr); > > + memblock_set_current_limit(0, lowmem_end_addr, false); > > } > > diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c > > index 9311560..8cd5f2d 100644 > > --- a/arch/powerpc/mm/pgtable-radix.c > > +++ b/arch/powerpc/mm/pgtable-radix.c > > @@ -603,7 +603,7 @@ void __init radix__early_init_mmu(void) > > radix_init_pseries(); > > } > > > > - memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE); > > + memblock_set_current_limit(0, MEMBLOCK_ALLOC_ANYWHERE, false); > > > > radix_init_iamr(); > > radix_init_pgtable(); > > diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c > > index f6f575b..80927ad 100644 > > --- a/arch/powerpc/mm/ppc_mmu_32.c > > +++ b/arch/powerpc/mm/ppc_mmu_32.c > > @@ -283,7 +283,11 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base, > > > > /* 601 can only access 16MB at the moment */ > > if (PVR_VER(mfspr(SPRN_PVR)) == 1) > > - memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01000000)); > > + memblock_set_current_limit(0, > > + min_t(u64, first_memblock_size, 0x01000000), > > + false); > > else /* Anything else has 256M mapped */ > > - memblock_set_current_limit(min_t(u64, first_memblock_size, 0x10000000)); > > + memblock_set_current_limit(0, > > + min_t(u64, first_memblock_size, 0x10000000), > > + false); > > } > > diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c > > index ae5d568..d074362 100644 > > --- a/arch/powerpc/mm/tlb_nohash.c > > +++ b/arch/powerpc/mm/tlb_nohash.c > > @@ -735,7 +735,7 @@ static void __init early_mmu_set_memory_limit(void) > > * reduces the memory available to Linux. We need to > > * do this because highmem is not supported on 64-bit. > > */ > > - memblock_enforce_memory_limit(linear_map_top); > > + memblock_enforce_memory_limit(0, linear_map_top, false); > > } > > #endif > > > > @@ -792,7 +792,9 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base, > > ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000); > > > > /* Finally limit subsequent allocations */ > > - memblock_set_current_limit(first_memblock_base + ppc64_rma_size); > > + memblock_set_current_limit(0, > > + first_memblock_base + ppc64_rma_size, > > + false); > > } > > #else /* ! CONFIG_PPC64 */ > > void __init early_init_mmu(void) > > diff --git a/arch/unicore32/mm/mmu.c b/arch/unicore32/mm/mmu.c > > index 040a8c2..6d62529 100644 > > --- a/arch/unicore32/mm/mmu.c > > +++ b/arch/unicore32/mm/mmu.c > > @@ -286,7 +286,7 @@ static void __init sanity_check_meminfo(void) > > int i, j; > > > > lowmem_limit = __pa(vmalloc_min - 1) + 1; > > - memblock_set_current_limit(lowmem_limit); > > + memblock_set_current_limit(0, lowmem_limit, false); > > > > for (i = 0, j = 0; i < meminfo.nr_banks; i++) { > > struct membank *bank = &meminfo.bank[j]; > > diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c > > index dc8fc5d..a0122cd 100644 > > --- a/arch/x86/kernel/setup.c > > +++ b/arch/x86/kernel/setup.c > > @@ -1130,7 +1130,7 @@ void __init setup_arch(char **cmdline_p) > > memblock_set_bottom_up(true); > > #endif > > init_mem_mapping(); > > - memblock_set_current_limit(get_max_mapped()); > > + memblock_set_current_limit(0, get_max_mapped(), false); > > > > idt_setup_early_pf(); > > > > diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c > > index 30a48bb..b924387 100644 > > --- a/arch/xtensa/mm/init.c > > +++ b/arch/xtensa/mm/init.c > > @@ -60,7 +60,7 @@ void __init bootmem_init(void) > > max_pfn = PFN_DOWN(memblock_end_of_DRAM()); > > max_low_pfn = min(max_pfn, MAX_LOW_PFN); > > > > - memblock_set_current_limit(PFN_PHYS(max_low_pfn)); > > + memblock_set_current_limit(0, PFN_PHYS(max_low_pfn), false); > > dma_contiguous_reserve(PFN_PHYS(max_low_pfn)); > > > > memblock_dump_all(); > > diff --git a/include/linux/memblock.h b/include/linux/memblock.h > > index aee299a..49676f0 100644 > > --- a/include/linux/memblock.h > > +++ b/include/linux/memblock.h > > @@ -88,6 +88,8 @@ struct memblock_type { > > */ > > struct memblock { > > bool bottom_up; /* is bottom up direction? */ > > + bool enforce_checking; > > + phys_addr_t start_limit; > > phys_addr_t current_limit; > > struct memblock_type memory; > > struct memblock_type reserved; > > @@ -482,12 +484,14 @@ static inline void memblock_dump_all(void) > > * memblock_set_current_limit - Set the current allocation limit to allow > > * limiting allocations to what is currently > > * accessible during boot > > - * @limit: New limit value (physical address) > > + * [start_limit, end_limit]: New limit value (physical address) > > + * enforcing: whether check against the limit boundary or not > > */ > > -void memblock_set_current_limit(phys_addr_t limit); > > +void memblock_set_current_limit(phys_addr_t start_limit, > > + phys_addr_t end_limit, bool enforcing); > > > > > > -phys_addr_t memblock_get_current_limit(void); > > +bool memblock_get_current_limit(phys_addr_t *start, phys_addr_t *end); > > > > /* > > * pfn conversion functions > > diff --git a/mm/memblock.c b/mm/memblock.c > > index 81ae63c..b792be0 100644 > > --- a/mm/memblock.c > > +++ b/mm/memblock.c > > @@ -116,6 +116,8 @@ struct memblock memblock __initdata_memblock = { > > #endif > > > > .bottom_up = false, > > + .enforce_checking = false, > > + .start_limit = 0, > > .current_limit = MEMBLOCK_ALLOC_ANYWHERE, > > }; > > > > @@ -261,8 +263,11 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size, > > { > > phys_addr_t kernel_end, ret; > > > > + if (unlikely(memblock.enforce_checking)) { > > + start = memblock.start_limit; > > + end = memblock.current_limit; > > /* pump up @end */ > > - if (end == MEMBLOCK_ALLOC_ACCESSIBLE) > > + } else if (end == MEMBLOCK_ALLOC_ACCESSIBLE) > > end = memblock.current_limit; > > > > /* avoid allocating the first page */ > > @@ -1826,14 +1831,22 @@ void __init_memblock memblock_trim_memory(phys_addr_t align) > > } > > } > > > > -void __init_memblock memblock_set_current_limit(phys_addr_t limit) > > +void __init_memblock memblock_set_current_limit(phys_addr_t start, > > + phys_addr_t end, bool enforcing) > > { > > - memblock.current_limit = limit; > > + memblock.start_limit = start; > > + memblock.current_limit = end; > > + memblock.enforce_checking = enforcing; > > } > > > > -phys_addr_t __init_memblock memblock_get_current_limit(void) > > +bool __init_memblock memblock_get_current_limit(phys_addr_t *start, > > + phys_addr_t *end) > > { > > - return memblock.current_limit; > > + if (start) > > + *start = memblock.start_limit; > > + if (end) > > + *end = memblock.current_limit; > > + return memblock.enforce_checking; > > } > > > > static void __init_memblock memblock_dump(struct memblock_type *type) > > -- > > 2.7.4 > > > > -- > Sincerely yours, > Mike. >