From: Mike Rapoport <hidden> Date: 2018-12-03 15:48:41
Hi,
These patches simplify some of the early memory allocations by replacing
usage of older memblock APIs with newer and shinier ones.
Quite a few places in the arch/ code allocated memory using a memblock API
that returns a physical address of the allocated area, then converted this
physical address to a virtual one and then used memset(0) to clear the
allocated range.
More recent memblock APIs do all the three steps in one call and their
usage simplifies the code.
It's important to note that regardless of API used, the core allocation is
nearly identical for any set of memblock allocators: first it tries to find
a free memory with all the constraints specified by the caller and then
falls back to the allocation with some or all constraints disabled.
The first three patches perform the conversion of call sites that have
exact requirements for the node and the possible memory range.
The fourth patch is a bit one-off as it simplifies openrisc's
implementation of pte_alloc_one_kernel(), and not only the memblock usage.
The fifth patch takes care of simpler cases when the allocation can be
satisfied with a simple call to memblock_alloc().
The sixth patch removes one-liner wrappers for memblock_alloc on arm and
unicore32, as suggested by Christoph.
v2:
* added Ack from Stafford Horne for openrisc changes
* entirely drop early_alloc wrappers on arm and unicore32, as per Christoph
Hellwig
Mike Rapoport (6):
powerpc: prefer memblock APIs returning virtual address
microblaze: prefer memblock API returning virtual address
sh: prefer memblock APIs returning virtual address
openrisc: simplify pte_alloc_one_kernel()
arch: simplify several early memory allocations
arm, unicore32: remove early_alloc*() wrappers
arch/arm/mm/mmu.c | 13 +++----------
arch/c6x/mm/dma-coherent.c | 9 ++-------
arch/microblaze/mm/init.c | 5 +++--
arch/nds32/mm/init.c | 12 ++++--------
arch/openrisc/mm/ioremap.c | 11 ++++-------
arch/powerpc/kernel/paca.c | 14 ++++++--------
arch/powerpc/kernel/setup-common.c | 4 ++--
arch/powerpc/kernel/setup_64.c | 21 ++++++++++-----------
arch/powerpc/mm/hash_utils_64.c | 6 +++---
arch/powerpc/mm/pgtable-book3e.c | 8 ++------
arch/powerpc/mm/pgtable-book3s64.c | 5 +----
arch/powerpc/mm/pgtable-radix.c | 24 +++++++++---------------
arch/powerpc/mm/pgtable_32.c | 4 +---
arch/powerpc/mm/ppc_mmu_32.c | 3 +--
arch/powerpc/platforms/pasemi/iommu.c | 5 +++--
arch/powerpc/platforms/powernv/opal.c | 3 +--
arch/powerpc/platforms/pseries/setup.c | 11 +++++++----
arch/powerpc/sysdev/dart_iommu.c | 5 +++--
arch/sh/mm/init.c | 18 +++++-------------
arch/sh/mm/numa.c | 5 ++---
arch/sparc/kernel/prom_64.c | 7 ++-----
arch/sparc/mm/init_64.c | 9 +++------
arch/unicore32/mm/mmu.c | 14 ++++----------
23 files changed, 81 insertions(+), 135 deletions(-)
From: Mike Rapoport <hidden> Date: 2018-12-03 15:47:56
Rather than use the memblock_alloc_base that returns a physical address and
then convert this address to the virtual one, use appropriate memblock
function that returns a virtual address.
There is a small functional change in the allocation of then NODE_DATA().
Instead of panicing if the local allocation failed, the non-local
allocation attempt will be made.
Signed-off-by: Mike Rapoport <redacted>
---
arch/sh/mm/init.c | 18 +++++-------------
arch/sh/mm/numa.c | 5 ++---
2 files changed, 7 insertions(+), 16 deletions(-)
@@ -192,24 +192,16 @@ void __init page_table_range_init(unsigned long start, unsigned long end,void__initallocate_pgdat(unsignedintnid){unsignedlongstart_pfn,end_pfn;-#ifdef CONFIG_NEED_MULTIPLE_NODES-unsignedlongphys;-#endifget_pfn_range_for_nid(nid,&start_pfn,&end_pfn);#ifdef CONFIG_NEED_MULTIPLE_NODES-phys=__memblock_alloc_base(sizeof(structpglist_data),-SMP_CACHE_BYTES,end_pfn<<PAGE_SHIFT);-/* Retry with all of system memory */-if(!phys)-phys=__memblock_alloc_base(sizeof(structpglist_data),-SMP_CACHE_BYTES,memblock_end_of_DRAM());-if(!phys)+NODE_DATA(nid)=memblock_alloc_try_nid_nopanic(+sizeof(structpglist_data),+SMP_CACHE_BYTES,MEMBLOCK_LOW_LIMIT,+MEMBLOCK_ALLOC_ACCESSIBLE,nid);+if(!NODE_DATA(nid))panic("Can't allocate pgdat for node %d\n",nid);--NODE_DATA(nid)=__va(phys);-memset(NODE_DATA(nid),0,sizeof(structpglist_data));#endifNODE_DATA(nid)->node_start_pfn=start_pfn;
From: Mike Rapoport <hidden> Date: 2018-12-03 15:48:01
Rather than use the memblock_alloc_base that returns a physical address and
then convert this address to the virtual one, use appropriate memblock
function that returns a virtual address.
Signed-off-by: Mike Rapoport <redacted>
---
arch/microblaze/mm/init.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
From: Mike Rapoport <hidden> Date: 2018-12-03 15:48:11
On arm and unicore32i the early_alloc_aligned() and and early_alloc() are
oneliner wrappers for memblock_alloc.
Replace their usage with direct call to memblock_alloc.
Suggested-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Mike Rapoport <redacted>
---
arch/arm/mm/mmu.c | 11 +++--------
arch/unicore32/mm/mmu.c | 12 ++++--------
2 files changed, 7 insertions(+), 16 deletions(-)
From: Mike Rapoport <hidden> Date: 2018-12-03 15:49:40
There are a several places that allocate memory using memblock APIs that
return a physical address, convert the returned address to the virtual
address and frequently also memset(0) the allocated range.
Update these places to use memblock allocators already returning a virtual
address; use memblock functions that clear the allocated memory instead of
calling memset(0).
Signed-off-by: Mike Rapoport <redacted>
---
arch/powerpc/kernel/paca.c | 14 ++++++--------
arch/powerpc/kernel/setup_64.c | 21 ++++++++++-----------
arch/powerpc/mm/hash_utils_64.c | 6 +++---
arch/powerpc/mm/pgtable-book3e.c | 8 ++------
arch/powerpc/mm/pgtable-book3s64.c | 5 +----
arch/powerpc/mm/pgtable-radix.c | 24 +++++++++---------------
arch/powerpc/platforms/pasemi/iommu.c | 5 +++--
arch/powerpc/platforms/pseries/setup.c | 11 +++++++----
arch/powerpc/sysdev/dart_iommu.c | 5 +++--
9 files changed, 44 insertions(+), 55 deletions(-)
@@ -195,11 +195,8 @@ void __init mmu_partition_table_init(void)unsignedlongptcr;BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT>36),"Partition table size too large.");-partition_tb=__va(memblock_alloc_base(patb_size,patb_size,-MEMBLOCK_ALLOC_ANYWHERE));-/* Initialize the Partition Table with no entries */-memset((void*)partition_tb,0,patb_size);+partition_tb=memblock_alloc(patb_size,patb_size);/**updatepartitiontablecontrolregister,
@@ -51,24 +51,18 @@ static int native_register_process_table(unsigned long base, unsigned long pg_szstatic__refvoid*early_alloc_pgtable(unsignedlongsize,intnid,unsignedlongregion_start,unsignedlongregion_end){-unsignedlongpa=0;+phys_addr_tmin_addr=MEMBLOCK_LOW_LIMIT;+phys_addr_tmax_addr=MEMBLOCK_ALLOC_ANYWHERE;void*pt;-if(region_start||region_end)/* has region hint */-pa=memblock_alloc_range(size,size,region_start,region_end,-MEMBLOCK_NONE);-elseif(nid!=-1)/* has node hint */-pa=memblock_alloc_base_nid(size,size,-MEMBLOCK_ALLOC_ANYWHERE,-nid,MEMBLOCK_NONE);+if(region_start)+min_addr=region_start;+if(region_end)+max_addr=region_end;-if(!pa)-pa=memblock_alloc_base(size,size,MEMBLOCK_ALLOC_ANYWHERE);--BUG_ON(!pa);--pt=__va(pa);-memset(pt,0,size);+pt=memblock_alloc_try_nid_nopanic(size,size,min_addr,max_addr,+nid);+BUG_ON(!pt);returnpt;}
@@ -140,8 +142,9 @@ static void __init fwnmi_init(void)#ifdef CONFIG_PPC_BOOK3S_64/* Allocate per cpu slb area to save old slb contents during MCE */size=sizeof(structslb_entry)*mmu_slb_size*nr_cpus;-slb_ptr=__va(memblock_alloc_base(size,sizeof(structslb_entry),-ppc64_rma_size));+slb_ptr=memblock_alloc_try_nid_raw(size,sizeof(structslb_entry),+MEMBLOCK_LOW_LIMIT,ppc64_rma_size,+NUMA_NO_NODE);for_each_possible_cpu(i)paca_ptrs[i]->mce_faulty_slbs=slb_ptr+(mmu_slb_size*i);#endif
@@ -251,8 +251,9 @@ static void allocate_dart(void)*16MB(1<<24)alignment.Weallocateafull16Mbchucksincewe*willblowupanentirelargepageanywayinthekernelmapping.*/-dart_tablebase=__va(memblock_alloc_base(1UL<<24,-1UL<<24,0x80000000L));+dart_tablebase=memblock_alloc_try_nid_raw(1UL<<24,1UL<<24,+MEMBLOCK_LOW_LIMIT,0x80000000L,+NUMA_NO_NODE);/* There is no point scanning the DART space for leaks*/kmemleak_no_scan((void*)dart_tablebase);
From: Mike Rapoport <hidden> Date: 2018-12-03 15:50:15
The pte_alloc_one_kernel() function allocates a page using
__get_free_page(GFP_KERNEL) when mm initialization is complete and
memblock_phys_alloc() on the earlier stages. The physical address of the
page allocated with memblock_phys_alloc() is converted to the virtual
address and in the both cases the allocated page is cleared using
clear_page().
The code is simplified by replacing __get_free_page() with
get_zeroed_page() and by replacing memblock_phys_alloc() with
memblock_alloc().
Signed-off-by: Mike Rapoport <redacted>
Acked-by: Stafford Horne <shorne@gmail.com>
---
arch/openrisc/mm/ioremap.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
From: Mike Rapoport <hidden> Date: 2018-12-03 15:58:04
There are several early memory allocations in arch/ code that use
memblock_phys_alloc() to allocate memory, convert the returned physical
address to the virtual address and then set the allocated memory to zero.
Exactly the same behaviour can be achieved simply by calling
memblock_alloc(): it allocates the memory in the same way as
memblock_phys_alloc(), then it performs the phys_to_virt() conversion and
clears the allocated memory.
Replace the longer sequence with a simpler call to memblock_alloc().
Signed-off-by: Mike Rapoport <redacted>
---
arch/arm/mm/mmu.c | 4 +---
arch/c6x/mm/dma-coherent.c | 9 ++-------
arch/nds32/mm/init.c | 12 ++++--------
arch/powerpc/kernel/setup-common.c | 4 ++--
arch/powerpc/mm/pgtable_32.c | 4 +---
arch/powerpc/mm/ppc_mmu_32.c | 3 +--
arch/powerpc/platforms/powernv/opal.c | 3 +--
arch/sparc/kernel/prom_64.c | 7 ++-----
arch/sparc/mm/init_64.c | 9 +++------
arch/unicore32/mm/mmu.c | 4 +---
10 files changed, 18 insertions(+), 41 deletions(-)
@@ -80,8 +80,7 @@ static void __init map_ram(void)}/* Alloc one page for holding PTE's... */-pte=(pte_t*)__va(memblock_phys_alloc(PAGE_SIZE,PAGE_SIZE));-memset(pte,0,PAGE_SIZE);+pte=memblock_alloc(PAGE_SIZE,PAGE_SIZE);set_pmd(pme,__pmd(__pa(pte)+_PAGE_KERNEL_TABLE));/* Fill the newly allocated page with PTE'S */
@@ -171,8 +171,7 @@ int __init early_init_dt_scan_recoverable_ranges(unsigned long node,/**AllocateabuffertoholdtheMCrecoverableranges.*/-mc_recoverable_range=__va(memblock_phys_alloc(size,__alignof__(u64)));-memset(mc_recoverable_range,0,size);+mc_recoverable_range=memblock_alloc(size,__alignof__(u64));for(i=0;i<mc_recoverable_range_len;i++){mc_recoverable_range[i].start_addr=
From: Sam Ravnborg <hidden> Date: 2018-12-03 16:11:12
Hi Mike.
On Mon, Dec 03, 2018 at 05:47:12PM +0200, Mike Rapoport wrote:
quoted hunk
Rather than use the memblock_alloc_base that returns a physical address and
then convert this address to the virtual one, use appropriate memblock
function that returns a virtual address.
There is a small functional change in the allocation of then NODE_DATA().
Instead of panicing if the local allocation failed, the non-local
allocation attempt will be made.
Signed-off-by: Mike Rapoport <redacted>
---
arch/sh/mm/init.c | 18 +++++-------------
arch/sh/mm/numa.c | 5 ++---
2 files changed, 7 insertions(+), 16 deletions(-)
@@ -192,24 +192,16 @@ void __init page_table_range_init(unsigned long start, unsigned long end,void__initallocate_pgdat(unsignedintnid){unsignedlongstart_pfn,end_pfn;-#ifdef CONFIG_NEED_MULTIPLE_NODES-unsignedlongphys;-#endifget_pfn_range_for_nid(nid,&start_pfn,&end_pfn);#ifdef CONFIG_NEED_MULTIPLE_NODES-phys=__memblock_alloc_base(sizeof(structpglist_data),-SMP_CACHE_BYTES,end_pfn<<PAGE_SHIFT);-/* Retry with all of system memory */-if(!phys)-phys=__memblock_alloc_base(sizeof(structpglist_data),-SMP_CACHE_BYTES,memblock_end_of_DRAM());-if(!phys)+NODE_DATA(nid)=memblock_alloc_try_nid_nopanic(+sizeof(structpglist_data),+SMP_CACHE_BYTES,MEMBLOCK_LOW_LIMIT,+MEMBLOCK_ALLOC_ACCESSIBLE,nid);+if(!NODE_DATA(nid))panic("Can't allocate pgdat for node %d\n",nid);--NODE_DATA(nid)=__va(phys);-memset(NODE_DATA(nid),0,sizeof(structpglist_data));
The new code will always assign NODE_DATA(nid), where the old
code only assigned NODE_DATA(nid) in the good case.
I dunno if this is an issue, just noticed the difference and
wanted to point it out.
Sam
From: Rob Herring <robh@kernel.org> Date: 2018-12-03 16:27:20
On Mon, Dec 3, 2018 at 9:48 AM Mike Rapoport [off-list ref] wrote:
quoted hunk
On arm and unicore32i the early_alloc_aligned() and and early_alloc() are
oneliner wrappers for memblock_alloc.
Replace their usage with direct call to memblock_alloc.
Suggested-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Mike Rapoport <redacted>
---
arch/arm/mm/mmu.c | 11 +++--------
arch/unicore32/mm/mmu.c | 12 ++++--------
2 files changed, 7 insertions(+), 16 deletions(-)
From: Mike Rapoport <hidden> Date: 2018-12-03 16:28:36
On Mon, Dec 03, 2018 at 05:10:52PM +0100, Sam Ravnborg wrote:
Hi Mike.
On Mon, Dec 03, 2018 at 05:47:12PM +0200, Mike Rapoport wrote:
quoted
Rather than use the memblock_alloc_base that returns a physical address and
then convert this address to the virtual one, use appropriate memblock
function that returns a virtual address.
There is a small functional change in the allocation of then NODE_DATA().
Instead of panicing if the local allocation failed, the non-local
allocation attempt will be made.
Signed-off-by: Mike Rapoport <redacted>
---
arch/sh/mm/init.c | 18 +++++-------------
arch/sh/mm/numa.c | 5 ++---
2 files changed, 7 insertions(+), 16 deletions(-)
@@ -192,24 +192,16 @@ void __init page_table_range_init(unsigned long start, unsigned long end,void__initallocate_pgdat(unsignedintnid){unsignedlongstart_pfn,end_pfn;-#ifdef CONFIG_NEED_MULTIPLE_NODES-unsignedlongphys;-#endifget_pfn_range_for_nid(nid,&start_pfn,&end_pfn);#ifdef CONFIG_NEED_MULTIPLE_NODES-phys=__memblock_alloc_base(sizeof(structpglist_data),-SMP_CACHE_BYTES,end_pfn<<PAGE_SHIFT);-/* Retry with all of system memory */-if(!phys)-phys=__memblock_alloc_base(sizeof(structpglist_data),-SMP_CACHE_BYTES,memblock_end_of_DRAM());-if(!phys)+NODE_DATA(nid)=memblock_alloc_try_nid_nopanic(+sizeof(structpglist_data),+SMP_CACHE_BYTES,MEMBLOCK_LOW_LIMIT,+MEMBLOCK_ALLOC_ACCESSIBLE,nid);+if(!NODE_DATA(nid))panic("Can't allocate pgdat for node %d\n",nid);--NODE_DATA(nid)=__va(phys);-memset(NODE_DATA(nid),0,sizeof(structpglist_data));
The new code will always assign NODE_DATA(nid), where the old
code only assigned NODE_DATA(nid) in the good case.
I dunno if this is an issue, just noticed the difference and
wanted to point it out.
If the allocation fails the NODE_DATA(nid) remains zero anyway and there is
a panic() call. So I think there is no actual functional change here.
memblock_alloc() calls memblock_alloc_try_nid().
And if allocation fails then memblock_alloc_try_nid() calls panic().
So will we ever hit the prom_halt() code?
Do we have a panic() implementation that actually returns?
memblock_alloc() calls memblock_alloc_try_nid().
And if allocation fails then memblock_alloc_try_nid() calls panic().
So will we ever hit the prom_halt() code?
memblock_phys_alloc_try_nid() also calls panic if an allocation fails. So
in either case we never reach prom_halt() code.
Actually, sparc is rather an exception from the general practice to rely on
panic() inside the early allocator rather than to check the return value.
Do we have a panic() implementation that actually returns?
From: Mike Rapoport <hidden> Date: 2018-12-03 16:55:24
On Mon, Dec 03, 2018 at 10:27:02AM -0600, Rob Herring wrote:
On Mon, Dec 3, 2018 at 9:48 AM Mike Rapoport [off-list ref] wrote:
quoted
On arm and unicore32i the early_alloc_aligned() and and early_alloc() are
oneliner wrappers for memblock_alloc.
Replace their usage with direct call to memblock_alloc.
Suggested-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Mike Rapoport <redacted>
---
arch/arm/mm/mmu.c | 11 +++--------
arch/unicore32/mm/mmu.c | 12 ++++--------
2 files changed, 7 insertions(+), 16 deletions(-)
Why not get rid of this wrapper like you do on unicore?
ARM has early_alloc() and late_alloc() callbacks which in the end are
passed as a parameter to alloc_init_pXd() functions.
Removing early_alloc() would require refactoring all the page table
allocation code.
@@ -42,17 +42,15 @@ static void *__init alloc_paca_data(unsigned long size, unsigned long align,nid=early_cpu_to_node(cpu);}-pa=memblock_alloc_base_nid(size,align,limit,nid,MEMBLOCK_NONE);-if(!pa){-pa=memblock_alloc_base(size,align,limit);-if(!pa)-panic("cannot allocate paca data");-}+ptr=memblock_alloc_try_nid_raw(size,align,MEMBLOCK_LOW_LIMIT,+limit,nid);+if(!ptr)+panic("cannot allocate paca data");
The old code doesn't zero, but two of the three callers of
alloc_paca_data() *do* zero the whole allocation, so I'd be happy if we
did it in here instead.
That would mean we could use memblock_alloc_try_nid() avoiding the need
to panic() manually.
Similarly here, several of the callers zero the stack, and I'd rather
all of them did.
So again we could use memblock_alloc_try_nid() here and remove the
memset()s from emergency_stack_init().
@@ -51,24 +51,18 @@ static int native_register_process_table(unsigned long base, unsigned long pg_szstatic__refvoid*early_alloc_pgtable(unsignedlongsize,intnid,unsignedlongregion_start,unsignedlongregion_end){-unsignedlongpa=0;+phys_addr_tmin_addr=MEMBLOCK_LOW_LIMIT;+phys_addr_tmax_addr=MEMBLOCK_ALLOC_ANYWHERE;void*pt;-if(region_start||region_end)/* has region hint */-pa=memblock_alloc_range(size,size,region_start,region_end,-MEMBLOCK_NONE);-elseif(nid!=-1)/* has node hint */-pa=memblock_alloc_base_nid(size,size,-MEMBLOCK_ALLOC_ANYWHERE,-nid,MEMBLOCK_NONE);+if(region_start)+min_addr=region_start;+if(region_end)+max_addr=region_end;-if(!pa)-pa=memblock_alloc_base(size,size,MEMBLOCK_ALLOC_ANYWHERE);--BUG_ON(!pa);--pt=__va(pa);-memset(pt,0,size);+pt=memblock_alloc_try_nid_nopanic(size,size,min_addr,max_addr,+nid);+BUG_ON(!pt);
I don't think there's any reason to BUG_ON() here rather than letting
memblock() call panic() for us. So this could also be memblock_alloc_try_nid().
@@ -208,7 +208,9 @@ static int __init iob_init(struct device_node *dn)pr_debug(" -> %s\n",__func__);/* For 2G space, 8x64 pages (2^21 bytes) is max total l2 size */-iob_l2_base=(u32*)__va(memblock_alloc_base(1UL<<21,1UL<<21,0x80000000));+iob_l2_base=memblock_alloc_try_nid_raw(1UL<<21,1UL<<21,+MEMBLOCK_LOW_LIMIT,0x80000000,+NUMA_NO_NODE);
This isn't equivalent is it?
memblock_alloc_base() panics on failure but memblock_alloc_try_nid_raw()
doesn't?
Same comment for the other locations that do that conversion.
cheers
@@ -42,17 +42,15 @@ static void *__init alloc_paca_data(unsigned long size, unsigned long align,nid=early_cpu_to_node(cpu);}-pa=memblock_alloc_base_nid(size,align,limit,nid,MEMBLOCK_NONE);-if(!pa){-pa=memblock_alloc_base(size,align,limit);-if(!pa)-panic("cannot allocate paca data");-}+ptr=memblock_alloc_try_nid_raw(size,align,MEMBLOCK_LOW_LIMIT,+limit,nid);+if(!ptr)+panic("cannot allocate paca data");
The old code doesn't zero, but two of the three callers of
alloc_paca_data() *do* zero the whole allocation, so I'd be happy if we
did it in here instead.
I looked at the callers and couldn't tell if zeroing memory in
init_lppaca() would be ok.
I'll remove the _raw here.
That would mean we could use memblock_alloc_try_nid() avoiding the need
to panic() manually.
Actual, my plan was to remove panic() from all memblock_alloc* and make all
callers to check the returned value.
I believe it's cleaner and also allows more meaningful panic messages. Not
mentioning the reduction of memblock code.
Similarly here, several of the callers zero the stack, and I'd rather
all of them did.
So again we could use memblock_alloc_try_nid() here and remove the
memset()s from emergency_stack_init().
@@ -51,24 +51,18 @@ static int native_register_process_table(unsigned long base, unsigned long pg_szstatic__refvoid*early_alloc_pgtable(unsignedlongsize,intnid,unsignedlongregion_start,unsignedlongregion_end){-unsignedlongpa=0;+phys_addr_tmin_addr=MEMBLOCK_LOW_LIMIT;+phys_addr_tmax_addr=MEMBLOCK_ALLOC_ANYWHERE;void*pt;-if(region_start||region_end)/* has region hint */-pa=memblock_alloc_range(size,size,region_start,region_end,-MEMBLOCK_NONE);-elseif(nid!=-1)/* has node hint */-pa=memblock_alloc_base_nid(size,size,-MEMBLOCK_ALLOC_ANYWHERE,-nid,MEMBLOCK_NONE);+if(region_start)+min_addr=region_start;+if(region_end)+max_addr=region_end;-if(!pa)-pa=memblock_alloc_base(size,size,MEMBLOCK_ALLOC_ANYWHERE);--BUG_ON(!pa);--pt=__va(pa);-memset(pt,0,size);+pt=memblock_alloc_try_nid_nopanic(size,size,min_addr,max_addr,+nid);+BUG_ON(!pt);
I don't think there's any reason to BUG_ON() here rather than letting
memblock() call panic() for us. So this could also be memblock_alloc_try_nid().
@@ -208,7 +208,9 @@ static int __init iob_init(struct device_node *dn)pr_debug(" -> %s\n",__func__);/* For 2G space, 8x64 pages (2^21 bytes) is max total l2 size */-iob_l2_base=(u32*)__va(memblock_alloc_base(1UL<<21,1UL<<21,0x80000000));+iob_l2_base=memblock_alloc_try_nid_raw(1UL<<21,1UL<<21,+MEMBLOCK_LOW_LIMIT,0x80000000,+NUMA_NO_NODE);
This isn't equivalent is it?
memblock_alloc_base() panics on failure but memblock_alloc_try_nid_raw()
doesn't?
Right, this should be either a memblock function that panic()'s or a call
to panic() if the returned value is NULL.
My preference is for the second variant :)
Same comment for the other locations that do that conversion.
cheers
@@ -42,17 +42,15 @@ static void *__init alloc_paca_data(unsigned long size, unsigned long align,nid=early_cpu_to_node(cpu);}-pa=memblock_alloc_base_nid(size,align,limit,nid,MEMBLOCK_NONE);-if(!pa){-pa=memblock_alloc_base(size,align,limit);-if(!pa)-panic("cannot allocate paca data");-}+ptr=memblock_alloc_try_nid_raw(size,align,MEMBLOCK_LOW_LIMIT,+limit,nid);+if(!ptr)+panic("cannot allocate paca data");
The old code doesn't zero, but two of the three callers of
alloc_paca_data() *do* zero the whole allocation, so I'd be happy if we
did it in here instead.
I looked at the callers and couldn't tell if zeroing memory in
init_lppaca() would be ok.
I'll remove the _raw here.
Thanks.
quoted
That would mean we could use memblock_alloc_try_nid() avoiding the need
to panic() manually.
Actual, my plan was to remove panic() from all memblock_alloc* and make all
callers to check the returned value.
I believe it's cleaner and also allows more meaningful panic messages. Not
mentioning the reduction of memblock code.
Hmm, not sure.
I see ~200 calls to the panicking functions, that seems like a lot of
work to change all those.
And I think I disagree on the "more meaningful panic message". This is a
perfect example, compare:
panic("cannot allocate paca data");
to:
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);
The former is basically useless, whereas the second might at least give
you a hint as to *why* the allocation failed.
I know it's kind of odd for a function to panic() rather than return an
error, but memblock is kind of special because it's so early in boot.
Most of these allocations have to succeed to get the system up and
running.
cheers
From: Michal Simek <monstr@monstr.eu> Date: 2018-12-05 15:30:02
On 03. 12. 18 16:47, Mike Rapoport wrote:
quoted hunk
Rather than use the memblock_alloc_base that returns a physical address and
then convert this address to the virtual one, use appropriate memblock
function that returns a virtual address.
Signed-off-by: Mike Rapoport <redacted>
---
arch/microblaze/mm/init.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
I can't see any issue with functionality when this patch is applied.
If you want me to take this via my tree please let me know.
Otherwise:
Tested-by: Michal Simek <redacted>
Thanks,
Michal
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs
@@ -42,17 +42,15 @@ static void *__init alloc_paca_data(unsigned long size, unsigned long align,nid=early_cpu_to_node(cpu);}-pa=memblock_alloc_base_nid(size,align,limit,nid,MEMBLOCK_NONE);-if(!pa){-pa=memblock_alloc_base(size,align,limit);-if(!pa)-panic("cannot allocate paca data");-}+ptr=memblock_alloc_try_nid_raw(size,align,MEMBLOCK_LOW_LIMIT,+limit,nid);+if(!ptr)+panic("cannot allocate paca data");
The old code doesn't zero, but two of the three callers of
alloc_paca_data() *do* zero the whole allocation, so I'd be happy if we
did it in here instead.
I looked at the callers and couldn't tell if zeroing memory in
init_lppaca() would be ok.
I'll remove the _raw here.
Thanks.
quoted
quoted
That would mean we could use memblock_alloc_try_nid() avoiding the need
to panic() manually.
Actual, my plan was to remove panic() from all memblock_alloc* and make all
callers to check the returned value.
I believe it's cleaner and also allows more meaningful panic messages. Not
mentioning the reduction of memblock code.
Hmm, not sure.
I see ~200 calls to the panicking functions, that seems like a lot of
work to change all those.
Yeah, I know :)
And I think I disagree on the "more meaningful panic message". This is a
perfect example, compare:
panic("cannot allocate paca data");
to:
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);
The former is basically useless, whereas the second might at least give
you a hint as to *why* the allocation failed.
We can easily keep the memblock message, just make it pr_err instead of
panic.
The message at the call site can show where the problem was without the
need to dive into the stack dump.
I know it's kind of odd for a function to panic() rather than return an
error, but memblock is kind of special because it's so early in boot.
Most of these allocations have to succeed to get the system up and
running.
The downside of having panic() inside some memblock functions is that it
makes the API way too bloated. And, at least currently, it's inconsistent.
For instance memblock_alloc_try_nid_raw() does not panic, but
memblock_alloc_try_nid() does.
When it was about 2 functions and a wrapper, it was perfectly fine, but
since than memblock has three sets of partially overlapping APIs with
endless convenience wrappers.
I believe that patching up ~200 calls is worth the reduction of memblock
API to saner size.
Another thing, the absence of check for return value for memory allocation
is not only odd, but it also makes the code obfuscated.
From: Mike Rapoport <hidden> Date: 2018-12-06 07:31:30
On Wed, Dec 05, 2018 at 04:29:40PM +0100, Michal Simek wrote:
On 03. 12. 18 16:47, Mike Rapoport wrote:
quoted
Rather than use the memblock_alloc_base that returns a physical address and
then convert this address to the virtual one, use appropriate memblock
function that returns a virtual address.
Signed-off-by: Mike Rapoport <redacted>
---
arch/microblaze/mm/init.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
I can't see any issue with functionality when this patch is applied.
If you want me to take this via my tree please let me know.
I thought to route this via mmotm tree.
Otherwise:
Tested-by: Michal Simek <redacted>
Thanks!
Thanks,
Michal
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs
memblock_alloc() calls memblock_alloc_try_nid().
And if allocation fails then memblock_alloc_try_nid() calls panic().
So will we ever hit the prom_halt() code?
memblock_phys_alloc_try_nid() also calls panic if an allocation fails. So
in either case we never reach prom_halt() code.
So we have code here we never reach - not nice.
If the idea is to avoid relying on the panic inside memblock_alloc() then
maybe replace it with a variant that do not call panic?
To make it clear what happens.
Sam
memblock_alloc() calls memblock_alloc_try_nid().
And if allocation fails then memblock_alloc_try_nid() calls panic().
So will we ever hit the prom_halt() code?
memblock_phys_alloc_try_nid() also calls panic if an allocation fails. So
in either case we never reach prom_halt() code.
So we have code here we never reach - not nice.
If the idea is to avoid relying on the panic inside memblock_alloc() then
maybe replace it with a variant that do not call panic?
To make it clear what happens.
My plan is to completely remove memblock variants that call panic() and
make the callers check the return value.
I've started to work on it, but with the holidays it progresses slower than
I'd like to.
Since the code here was unreachable for several year, a few more weeks
won't make real difference so I'd prefer to keep the variant with panic()
for now.