cma: powerpc fadump fixes
Subsystems (3)
Ritesh Harjani (IBM)
reviewerv2 cover cma: powerpc fadump fixes
Please find the v2 of cma related powerpc fadump fixes.
Patch-1 is a change in mm/cma.c to make sure we return an error if someone uses cma_init_reserved_mem() before the pageblock_order is initalized.
I guess, it's best if Patch-1 goes via mm tree and since rest of the changes are powerpc fadump fixes hence those should go via powerpc tree. Right?
v1 -> v2:
=========
1. Review comments from David to call fadump_cma_init() after the pageblock_order is initialized. Also to catch usages if someone tries to call cma_init_reserved_mem() before pageblock_order is initialized.
Ritesh Harjani (IBM) (4):
cma: Enforce non-zero pageblock_order during cma_init_reserved_mem()
fadump: Refactor and prepare fadump_cma_init for late init
fadump: Reserve page-aligned boot_memory_size during fadump_reserve_mem
fadump: Move fadump_cma_init to setup_arch() after initmem_init()
arch/powerpc/include/asm/fadump.h | 7 ++++ arch/powerpc/kernel/fadump.c | 55 +++++++++++++++--------------- arch/powerpc/kernel/setup-common.c | 6 ++-- mm/cma.c | 9 +++++ 4 files changed, 48 insertions(+), 29 deletions(-)
--
2.46.0
Ritesh Harjani (IBM)
reviewerRFC v2 1/4 cma: Enforce non-zero pageblock_order during cma_init_reserved_mem()
cma_init_reserved_mem() checks base and size alignment with CMA_MIN_ALIGNMENT_BYTES. However, some users might call this during early boot when pageblock_order is 0. That means if base and size does not have pageblock_order alignment, it can cause functional failures during cma activate area.
So let's enforce pageblock_order to be non-zero during cma_init_reserved_mem().
--- mm/cma.c | 9 +++++++++ 1 file changed, 9 insertions(+)
mm/cma.c +9 -0
@@ -182,6 +182,15 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,if (!size || !memblock_is_region_reserved (base, size))return -EINVAL ; +/* +* CMA uses CMA_MIN_ALIGNMENT_BYTES as alignment requirement which +* needs pageblock_order to be initialized. Let's enforce it. +*/ +if (!pageblock_order) { +pr_err ("pageblock_order not yet initialized. Called during early boot?\n" ); +return -EINVAL ; + } +/* ensure minimal alignment required by mm core */ if (!IS_ALIGNED (base | size,CMA_MIN_ALIGNMENT_BYTES ))return -EINVAL ;
Signature · 1 line
2.46.0
Re: [RFC v2 1/4] cma: Enforce non-zero pageblock_order during cma_init_reserved_mem()
Quoted 24 lines · Ritesh Harjani (IBM)
cma_init_reserved_mem()checks base and size alignment withCMA_MIN_ALIGNMENT_BYTES. However, some users might call this during early boot whenpageblock_orderis 0. That means if base and size does not havepageblock_orderalignment, it can cause functional failures during cma activate area.So let's enforce
pageblock_orderto be non-zero duringcma_init_reserved_mem().Signed-off-by Ritesh Harjani (IBM) <[email protected]>--- mm/cma.c | 9 +++++++++ 1 file changed, 9 insertions(+)mm/cma.c +2
-0@@ -182,6 +182,15 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,if (!size || !memblock_is_region_reserved (base, size))return -EINVAL ; +/* +* CMA uses CMA_MIN_ALIGNMENT_BYTES as alignment requirement which
mm/cma.c int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size, · line 196
Quoted 10 lines
mm/cma.c +7
-0+* needs pageblock_order to be initialized. Let's enforce it. +*/ +if (!pageblock_order) { +pr_err ("pageblock_order not yet initialized. Called during early boot?\n" ); +return -EINVAL ; + } +/* ensure minimal alignment required by mm core */ if (!IS_ALIGNED (base | size,CMA_MIN_ALIGNMENT_BYTES ))return -EINVAL ;
Signature · 3 lines
Cheers, David / dhildenb
Ritesh Harjani (IBM)
reviewerRFC v2 2/4 fadump: Refactor and prepare fadump_cma_init for late init
In reply to Ritesh Harjani (IBM)We anyway don't use any return values from fadump_cma_init(). Since fadump_reserve_mem() from where fadump_cma_init() gets called today, already has the required checks.
This patch makes this function return type as void. Let's also handle extra cases like return if fadump_supported is false or dump_active, so that in later patches we can call fadump_cma_init() separately from setup_arch().
--- arch/powerpc/kernel/fadump.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-)
arch/powerpc/kernel/fadump.c +9 -14
@@ -78,27 +78,23 @@ static struct cma *fadump_cma;* But for some reason even if it fails we still have the memory reservation * with us and we can still continue doing fadump. */ -static int __init fadump_cma_init (void ) +static void __init fadump_cma_init (void ) {unsigned long long base, size;int rc; -if (!fw_dump.fadump_enabled) -return 0 ; - +if (!fw_dump.fadump_supported || !fw_dump.fadump_enabled || + fw_dump.dump_active) +return ;/* * Do not use CMA if user has provided fadump=nocma kernel parameter. -* Return 1 to continue with fadump old behaviour. */ -if (fw_dump.nocma) -return 1 ; +if (fw_dump.nocma || !fw_dump.boot_memory_size) +return ; base = fw_dump.reserve_dump_area_start; size = fw_dump.boot_memory_size; -if (!size) -return 0 ; - rc =cma_init_reserved_mem (base, size,0 ,"fadump_cma" , &fadump_cma);if (rc) {pr_err ("Failed to init cma area for firmware-assisted dump,%d\n" , rc);
@@ -108,7 +104,7 @@ static int __init fadump_cma_init(void)* blocked from production system usage. Hence return 1, * so that we can continue with fadump. */ -return 1 ; +return ; }/*
@@ -125,10 +121,9 @@ static int __init fadump_cma_init(void)cma_get_size (fadump_cma), (unsigned long )cma_get_base (fadump_cma) >>20 , fw_dump.reserve_dump_area_size); - return 1; }#else -static int __init fadump_cma_init (void ) {return 1 ; } +static void __init fadump_cma_init (void ) { }#endif /* CONFIG_CMA */ /*
@@ -638,7 +633,7 @@ int __init fadump_reserve_mem(void)pr_info ("Reserved %lldMB of memory at %#016llx (System RAM: %lldMB)\n" , (size >>20 ), base, (memblock_phys_mem_size () >>20 )); - ret =fadump_cma_init (); +fadump_cma_init (); }return ret;
Signature · 1 line
2.46.0
Ritesh Harjani (IBM)
reviewerRFC v2 3/4 fadump: Reserve page-aligned boot_memory_size during fadump_reserve_mem
In reply to Ritesh Harjani (IBM)This patch refactors all CMA related initialization and alignment code to within fadump_cma_init() which gets called in the end. This also means that we keep [reserve_dump_area_start, boot_memory_size] page aligned during fadump_reserve_mem(). Then later in fadump_cma_init() we extract the aligned chunk and provide it to CMA. This inherently also fixes an issue in the current code where the reserve_dump_area_start is not aligned when the physical memory can have holes and the suitable chunk starts at an unaligned boundary.
After this we should be able to call fadump_cma_init() independently later in setup_arch() where pageblock_order is non-zero.
--- arch/powerpc/kernel/fadump.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-)
arch/powerpc/kernel/fadump.c +22 -12
@@ -80,7 +80,7 @@ static struct cma *fadump_cma;*/ static void __init fadump_cma_init (void ) { -unsigned long long base, size; +unsigned long long base, size, end;int rc; if (!fw_dump.fadump_supported || !fw_dump.fadump_enabled ||
@@ -92,8 +92,24 @@ static void __init fadump_cma_init(void)if (fw_dump.nocma || !fw_dump.boot_memory_size)return ; +/* +* [base, end) should be reserved during early init in +* fadump_reserve_mem(). No need to check this here as +* cma_init_reserved_mem() already checks for overlap. +* Here we give the aligned chunk of this reserved memory to CMA. +*/ base = fw_dump.reserve_dump_area_start; size = fw_dump.boot_memory_size; + end = base + size; + + base =ALIGN (base,CMA_MIN_ALIGNMENT_BYTES ); + end =ALIGN_DOWN (end,CMA_MIN_ALIGNMENT_BYTES ); + size = end - base; + +if (end <= base) { +pr_warn ("%s: Too less memory to give to CMA\n" , __func__); +return ; + } rc =cma_init_reserved_mem (base, size,0 ,"fadump_cma" , &fadump_cma);if (rc) {
@@ -116,11 +132,12 @@ static void __init fadump_cma_init(void)/* * So we now have successfully initialized cma area for fadump. */ -pr_info ("Initialized 0x%lx bytes cma area at %ldMB from 0x%lx " +pr_info ("Initialized [0x%llx, %luMB] cma area from [0x%lx, %luMB] " "bytes of memory reserved for firmware-assisted dump\n" , -cma_get_size (fadump_cma), - (unsigned long )cma_get_base (fadump_cma) >>20 , - fw_dump.reserve_dump_area_size); +cma_get_base (fadump_cma),cma_get_size (fadump_cma) >>20 , + fw_dump.reserve_dump_area_start, + fw_dump.boot_memory_size >>20 ); + return; }#else static void __init fadump_cma_init (void ) { }
@@ -553,13 +570,6 @@ int __init fadump_reserve_mem(void)if (!fw_dump.dump_active) { fw_dump.boot_memory_size =PAGE_ALIGN (fadump_calculate_reserve_size ()); -#ifdef CONFIG_CMA -if (!fw_dump.nocma) { - fw_dump.boot_memory_size = -ALIGN (fw_dump.boot_memory_size, -CMA_MIN_ALIGNMENT_BYTES ); - } -#endif bootmem_min = fw_dump.ops->fadump_get_bootmem_min ();if (fw_dump.boot_memory_size < bootmem_min) {
Signature · 1 line
2.46.0
Re: [RFC v2 3/4] fadump: Reserve page-aligned boot_memory_size during fadump_reserve_mem
Quoted 60 lines · Ritesh Harjani (IBM)
This patch refactors all CMA related initialization and alignment code to within
fadump_cma_init()which gets called in the end. This also means that we keep [reserve_dump_area_start,boot_memory_size] page aligned duringfadump_reserve_mem(). Then later infadump_cma_init()we extract the aligned chunk and provide it to CMA. This inherently also fixes an issue in the current code where thereserve_dump_area_startis not aligned when the physical memory can have holes and the suitable chunk starts at an unaligned boundary.After this we should be able to call
fadump_cma_init()independently later insetup_arch()wherepageblock_orderis non-zero.Suggested-by Sourabh Jain <[email protected]>Signed-off-by Ritesh Harjani (IBM) <[email protected]>--- arch/powerpc/kernel/fadump.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-)arch/powerpc/kernel/fadump.c +17
-1@@ -80,7 +80,7 @@ static struct cma *fadump_cma;*/ static void __init fadump_cma_init (void ) { -unsigned long long base, size; +unsigned long long base, size, end;int rc; if (!fw_dump.fadump_supported || !fw_dump.fadump_enabled ||@@ -92,8 +92,24 @@ static void __init fadump_cma_init(void)if (fw_dump.nocma || !fw_dump.boot_memory_size)return ; +/* +* [base, end) should be reserved during early init in +* fadump_reserve_mem(). No need to check this here as +* cma_init_reserved_mem() already checks for overlap. +* Here we give the aligned chunk of this reserved memory to CMA. +*/ base = fw_dump.reserve_dump_area_start; size = fw_dump.boot_memory_size; + end = base + size; + + base =ALIGN (base,CMA_MIN_ALIGNMENT_BYTES ); + end =ALIGN_DOWN (end,CMA_MIN_ALIGNMENT_BYTES ); + size = end - base; + +if (end <= base) { +pr_warn ("%s: Too less memory to give to CMA\n" , __func__); +return ; + } rc =cma_init_reserved_mem (base, size,0 ,"fadump_cma" , &fadump_cma);if (rc) {@@ -116,11 +132,12 @@ static void __init fadump_cma_init(void)/* * So we now have successfully initialized cma area for fadump. */
arch/powerpc/kernel/fadump.c static void __init fadump_cma_init(void) · line 140
Quoted 10 lines
arch/powerpc/kernel/fadump.c +4
-4-pr_info ("Initialized 0x%lx bytes cma area at %ldMB from 0x%lx " +pr_info ("Initialized [0x%llx, %luMB] cma area from [0x%lx, %luMB] " "bytes of memory reserved for firmware-assisted dump\n" , -cma_get_size (fadump_cma), - (unsigned long )cma_get_base (fadump_cma) >>20 , - fw_dump.reserve_dump_area_size); +cma_get_base (fadump_cma),cma_get_size (fadump_cma) >>20 , + fw_dump.reserve_dump_area_start, + fw_dump.boot_memory_size >>20 );
The changes look good. Thanks for looking into it.
For patches 2, 3 & 4
Quoted 18 lines
arch/powerpc/kernel/fadump.c +1
-0+ return; }#else static void
__initfadump_cma_init(void){ }arch/powerpc/kernel/fadump.c +0
-7@@ -553,13 +570,6 @@ int __init fadump_reserve_mem(void)if (!fw_dump.dump_active) { fw_dump.boot_memory_size =PAGE_ALIGN (fadump_calculate_reserve_size ()); -#ifdef CONFIG_CMA -if (!fw_dump.nocma) { - fw_dump.boot_memory_size = -ALIGN (fw_dump.boot_memory_size, -CMA_MIN_ALIGNMENT_BYTES ); - } -#endif bootmem_min = fw_dump.ops->fadump_get_bootmem_min ();if (fw_dump.boot_memory_size < bootmem_min) {
Ritesh Harjani (IBM)
reviewerRFC v2 4/4 fadump: Move fadump_cma_init to setup_arch() after initmem_init()
In reply to Ritesh Harjani (IBM)During early init CMA_MIN_ALIGNMENT_BYTES can be PAGE_SIZE, since pageblock_order is still zero and it gets initialized later during initmem_init() e.g.setup_arch() -> initmem_init() -> sparse_init() -> set_pageblock_order()
One such use case where this causes issues is -early_setup() -> early_init_devtree() -> fadump_reserve_mem() -> fadump_cma_init()
This causes CMA memory alignment check to be bypassed in cma_init_reserved_mem(). Then later cma_activate_area() can hit a VM_BUG_ON_PAGE(pfn & ((1 << order) - 1)) if the reserved memory area was not pageblock_order aligned.
Fix it by moving the fadump_cma_init() after initmem_init(), where other such cma reservations also gets called.
<stack trace>
==============
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x10010 flags: 0x13ffff800000000(node=1|zone=0|lastcpupid=0x7ffff) CMA raw: 013ffff800000000 5deadbeef0000100 5deadbeef0000122 0000000000000000 raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 page dumped because: VM_BUG_ON_PAGE(pfn & ((1 << order) - 1)) ------------[ cut here ]------------ kernel BUG at mm/page_alloc.c:778! Call Trace: __free_one_page+0x57c/0x7b0 (unreliable) free_pcppages_bulk+0x1a8/0x2c8 free_unref_page_commit+0x3d4/0x4e4 free_unref_page+0x458/0x6d0 init_cma_reserved_pageblock+0x114/0x198 cma_init_reserved_areas+0x270/0x3e0 do_one_initcall+0x80/0x2f8 kernel_init_freeable+0x33c/0x530 kernel_init+0x34/0x26c ret_from_kernel_user_thread+0x14/0x1c
--- arch/powerpc/include/asm/fadump.h | 7 +++++++ arch/powerpc/kernel/fadump.c | 6 +----- arch/powerpc/kernel/setup-common.c | 6 ++++-- 3 files changed, 12 insertions(+), 7 deletions(-)
arch/powerpc/include/asm/fadump.h +7 -0
@@ -34,4 +34,11 @@ extern int early_init_dt_scan_fw_dump(unsigned long node, const char *uname, int depth, void *data);extern int fadump_reserve_mem (void );#endif + +#if defined(CONFIG_FA_DUMP ) && defined(CONFIG_CMA ) +void fadump_cma_init (void ); +#else +static inline void fadump_cma_init (void ) { } +#endif +#endif /* _ASM_POWERPC_FADUMP_H */
arch/powerpc/kernel/fadump.c +1 -5
@@ -78,7 +78,7 @@ static struct cma *fadump_cma;* But for some reason even if it fails we still have the memory reservation * with us and we can still continue doing fadump. */ -static void __init fadump_cma_init (void ) +void __init fadump_cma_init (void ) {unsigned long long base, size, end;int rc;
@@ -139,8 +139,6 @@ static void __init fadump_cma_init(void) fw_dump.boot_memory_size >> 20); return; } -#else -static void __init fadump_cma_init (void ) { }#endif /* CONFIG_CMA */ /*
@@ -642,8 +640,6 @@ int __init fadump_reserve_mem(void)pr_info ("Reserved %lldMB of memory at %#016llx (System RAM: %lldMB)\n" , (size >>20 ), base, (memblock_phys_mem_size () >>20 )); - -fadump_cma_init (); }return ret;
arch/powerpc/kernel/setup-common.c +4 -2
@@ -997,9 +997,11 @@ void __init setup_arch(char **cmdline_p)initmem_init ();/* -* Reserve large chunks of memory for use by CMA for KVM and hugetlb. These must -* be called after initmem_init(), so that pageblock_order is initialised. +* Reserve large chunks of memory for use by CMA for fadump, KVM and +* hugetlb. These must be called after initmem_init(), so that +* pageblock_order is initialised. */ +fadump_cma_init ();kvm_cma_reserve ();gigantic_hugetlb_cma_reserve ();
--
2.46.0
Michael Ellerman
reviewerQuoted 7 lines · Ritesh Harjani (IBM)
Please find the v2 of cma related powerpc fadump fixes.
Patch-1 is a change in
mm/cma.cto make sure we return an error if someone usescma_init_reserved_mem()before thepageblock_orderis initalized.I guess, it's best if Patch-1 goes via mm tree and since rest of the changes are powerpc fadump fixes hence those should go via powerpc tree. Right?
Yes I think that will work.
Because there's no actual dependency on patch 1, correct?
Let's see if the mm folks are happy with the approach, and if so you should send patch 1 on its own, and patches 2-4 as a separate series.
Then I can take the series (2-4) as fixes, and patch 1 can go via the mm tree (probably in next, not as a fix).
cheers
Quoted 22 lines
v1 -> v2:
=========
1. Review comments from David to callfadump_cma_init()after thepageblock_orderis initialized. Also to catch usages if someone tries to callcma_init_reserved_mem()beforepageblock_orderis initialized.Ritesh Harjani (IBM) (4):
cma: Enforce non-zeropageblock_orderduringcma_init_reserved_mem()
fadump: Refactor and preparefadump_cma_initfor late init
fadump: Reserve page-alignedboot_memory_sizeduringfadump_reserve_mem
fadump: Movefadump_cma_inittosetup_arch()afterinitmem_init()arch/powerpc/include/asm/fadump.h | 7 ++++ arch/powerpc/kernel/fadump.c | 55 +++++++++++++++--------------- arch/powerpc/kernel/setup-common.c | 6 ++-- mm/cma.c | 9 +++++ 4 files changed, 48 insertions(+), 29 deletions(-)--
2.46.0
Quoted 9 lines · Michael Ellerman
Quoted 7 lines · Ritesh Harjani (IBM)
Please find the v2 of cma related powerpc fadump fixes.
Patch-1 is a change in
mm/cma.cto make sure we return an error if someone usescma_init_reserved_mem()before thepageblock_orderis initalized.I guess, it's best if Patch-1 goes via mm tree and since rest of the changes are powerpc fadump fixes hence those should go via powerpc tree. Right?
Quoted 6 lines
Yes I think that will work.
Because there's no actual dependency on patch 1, correct?
Let's see if the mm folks are happy with the approach, and if so you should send patch 1 on its own, and patches 2-4 as a separate series.
Makes sense to me.
Signature · 3 lines
Cheers, David / dhildenb
Ritesh Harjani (IBM)
reviewerQuoted 6 lines · Michael Ellerman
Quoted 5 lines · Ritesh Harjani (IBM)
Please find the v2 of cma related powerpc fadump fixes.
Patch-1 is a change in
mm/cma.cto make sure we return an error if someone usescma_init_reserved_mem()before thepageblock_orderis initalized.
Quoted 6 lines
Quoted 2 lines
I guess, it's best if Patch-1 goes via mm tree and since rest of the changes are powerpc fadump fixes hence those should go via powerpc tree. Right?
Yes I think that will work.
Because there's no actual dependency on patch 1, correct?
There is no dependency, yes.
Quoted 7 lines
Let's see if the mm folks are happy with the approach, and if so you should send patch 1 on its own, and patches 2-4 as a separate series.
Then I can take the series (2-4) as fixes, and patch 1 can go via the mm tree (probably in next, not as a fix).
Sure. Since David has acked patch-1, let me split this into 2 series as you mentioned above and re-send both seperately, so that it can be picked up in their respective trees.
Will just do it in sometime. Thanks!
-ritesh
Quoted 24 lines
cheers
Quoted 22 lines
v1 -> v2:
=========
1. Review comments from David to callfadump_cma_init()after thepageblock_orderis initialized. Also to catch usages if someone tries to callcma_init_reserved_mem()beforepageblock_orderis initialized.Ritesh Harjani (IBM) (4):
cma: Enforce non-zeropageblock_orderduringcma_init_reserved_mem()
fadump: Refactor and preparefadump_cma_initfor late init
fadump: Reserve page-alignedboot_memory_sizeduringfadump_reserve_mem
fadump: Movefadump_cma_inittosetup_arch()afterinitmem_init()arch/powerpc/include/asm/fadump.h | 7 ++++ arch/powerpc/kernel/fadump.c | 55 +++++++++++++++--------------- arch/powerpc/kernel/setup-common.c | 6 ++-- mm/cma.c | 9 +++++ 4 files changed, 48 insertions(+), 29 deletions(-)--
2.46.0