* Re: [PATCH v1 1/2] kho: check scratch vs CMA alignment at runtime
2026-09-28 8:32 ` [PATCH v1 1/2] kho: check scratch vs CMA alignment at runtime Sourabh Jain
@ 2026-09-28 8:41 ` sashiko-bot
2026-10-01 3:30 ` Sourabh Jain
2026-10-03 7:59 ` Mike Rapoport
2026-10-12 14:30 ` Pratyush Yadav
2 siblings, 1 reply; 11+ messages in thread
From: sashiko-bot @ 2026-09-28 8:41 UTC (permalink / raw)
To: Sourabh Jain
Cc: Aditya Gupta, Baoquan He, Madhavan Srinivasan, Pratyush Yadav,
kexec, Christophe Leroy (CS GROUP),
Mahesh Salgaonkar, Michael Ellerman, Hari Bathini, Mike Rapoport,
linux-kernel, Pasha Tatashin, linuxppc-dev, Andrew Morton,
Alexander Graf, Shrikanth Hegde, Shivang Upadhyay,
Nicholas Piggin, Ritesh Harjani (IBM)
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] kho: bypassed scratch alignment check during resume causes memory corruption
--
commit cbd7cb7f008e704b389d8dfe3306e1e83e49e8a8
Author: Sourabh Jain <sourabhjain@linux.ibm.com>
kho: check scratch vs CMA alignment at runtime
KHO requires the scratch alignment to be at least CMA_MIN_ALIGNMENT_BYTES,
which was previously enforced with a static_assert(). This commit replaces
the static_assert() with a runtime check in kho_reserve_scratch() to allow
KHO on configurations where the minimum alignment is not a constant.
> diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
> index 7c4d86daf86d5..dc76dd6b74da7 100644
> --- a/kernel/liveupdate/kexec_handover.c
> +++ b/kernel/liveupdate/kexec_handover.c
[ ... ]
> @@ -836,6 +828,21 @@ static void __init kho_reserve_scratch(void)
> if (!kho_enable)
> return;
>
> + /*
> + * This is the minimal alignment required by deferred struct page init.
> + * deferred_init_memmap_chunk frees memory to the buddy allocator, which looks
> + * at the neighboring pages (up to MAX_PAGE_ORDER) to merge them.
> + * If KHO scratch is not aligned to that value, buddy can access uninitialized
> + * struct pages, which can cause a crash.
> + */
> + if (WARN_ON_ONCE(SCRATCH_ALIGNMENT_BYTES < CMA_MIN_ALIGNMENT_BYTES)) {
> + pr_err("scratch alignment %lu < CMA minimum %lu, disabling\n",
> + (unsigned long)SCRATCH_ALIGNMENT_BYTES,
> + (unsigned long)CMA_MIN_ALIGNMENT_BYTES);
> + kho_enable = false;
> + return;
> + }
> +
[Severity: High]
Does this new runtime check get bypassed during a KHO resume?
During a KHO resume, kho_memory_init() skips kho_reserve_scratch():
kernel/liveupdate/kexec_handover.c:kho_memory_init() {
if (kho_in.scratch_phys)
kho_mem_retrieve();
else
kho_reserve_scratch();
}
If a predecessor kernel passes a scratch region with a smaller alignment,
and the successor kernel has a larger pageblock_order, bypassing this check
means kho_init() will iterate over the provided scratch memory using the
successor kernel's larger pageblock_nr_pages:
kernel/liveupdate/kexec_handover.c:kho_init() {
for (pfn = base_pfn; pfn < base_pfn + count;
pfn += pageblock_nr_pages)
init_cma_reserved_pageblock(pfn_to_page(pfn));
}
Can this lead to init_cma_reserved_pageblock() overwriting state for pages
outside the actual scratch region bounds, or cause a crash in the buddy
allocator if __free_pages() is called on an unaligned PFN?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260928083226.107807-1-sourabhjain@linux.ibm.com?part=1
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH v1 1/2] kho: check scratch vs CMA alignment at runtime
2026-09-28 8:41 ` sashiko-bot
@ 2026-10-01 3:30 ` Sourabh Jain
2026-10-12 14:29 ` Pratyush Yadav
0 siblings, 1 reply; 11+ messages in thread
From: Sourabh Jain @ 2026-10-01 3:30 UTC (permalink / raw)
To: sashiko-reviews
Cc: Aditya Gupta, Baoquan He, Madhavan Srinivasan, Pratyush Yadav,
kexec, Christophe Leroy (CS GROUP),
Mahesh Salgaonkar, Michael Ellerman, Hari Bathini, Mike Rapoport,
linux-kernel, Pasha Tatashin, linuxppc-dev, Andrew Morton,
Alexander Graf, Shrikanth Hegde, Shivang Upadhyay,
Nicholas Piggin, Ritesh Harjani (IBM)
On 28/09/26 14:11, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] kho: bypassed scratch alignment check during resume causes memory corruption
> --
>
> commit cbd7cb7f008e704b389d8dfe3306e1e83e49e8a8
> Author: Sourabh Jain <sourabhjain@linux.ibm.com>
>
> kho: check scratch vs CMA alignment at runtime
>
> KHO requires the scratch alignment to be at least CMA_MIN_ALIGNMENT_BYTES,
> which was previously enforced with a static_assert(). This commit replaces
> the static_assert() with a runtime check in kho_reserve_scratch() to allow
> KHO on configurations where the minimum alignment is not a constant.
>
>> diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
>> index 7c4d86daf86d5..dc76dd6b74da7 100644
>> --- a/kernel/liveupdate/kexec_handover.c
>> +++ b/kernel/liveupdate/kexec_handover.c
> [ ... ]
>
>> @@ -836,6 +828,21 @@ static void __init kho_reserve_scratch(void)
>> if (!kho_enable)
>> return;
>>
>> + /*
>> + * This is the minimal alignment required by deferred struct page init.
>> + * deferred_init_memmap_chunk frees memory to the buddy allocator, which looks
>> + * at the neighboring pages (up to MAX_PAGE_ORDER) to merge them.
>> + * If KHO scratch is not aligned to that value, buddy can access uninitialized
>> + * struct pages, which can cause a crash.
>> + */
>> + if (WARN_ON_ONCE(SCRATCH_ALIGNMENT_BYTES < CMA_MIN_ALIGNMENT_BYTES)) {
>> + pr_err("scratch alignment %lu < CMA minimum %lu, disabling\n",
>> + (unsigned long)SCRATCH_ALIGNMENT_BYTES,
>> + (unsigned long)CMA_MIN_ALIGNMENT_BYTES);
>> + kho_enable = false;
>> + return;
>> + }
>> +
> [Severity: High]
> Does this new runtime check get bypassed during a KHO resume?
>
> During a KHO resume, kho_memory_init() skips kho_reserve_scratch():
>
> kernel/liveupdate/kexec_handover.c:kho_memory_init() {
> if (kho_in.scratch_phys)
> kho_mem_retrieve();
> else
> kho_reserve_scratch();
> }
>
> If a predecessor kernel passes a scratch region with a smaller alignment,
> and the successor kernel has a larger pageblock_order, bypassing this check
> means kho_init() will iterate over the provided scratch memory using the
> successor kernel's larger pageblock_nr_pages:
>
> kernel/liveupdate/kexec_handover.c:kho_init() {
> for (pfn = base_pfn; pfn < base_pfn + count;
> pfn += pageblock_nr_pages)
> init_cma_reserved_pageblock(pfn_to_page(pfn));
> }
> Can this lead to init_cma_reserved_pageblock() overwriting state for pages
> outside the actual scratch region bounds, or cause a crash in the buddy
> allocator if __free_pages() is called on an unaligned PFN?
Yes, if the kexeced kernel has a higher pageblock_order than the
kernel that initiated the kexec with KHO, this can cause problems when
the code above hands scratch-memory pages back to the buddy allocator
in the kexeced kernel.
Would it make sense to handle this by keeping only the unaligned pages
reserved and handing the remaining pages back to the buddy?
Something like this:
diff --git a/kernel/liveupdate/kexec_handover.c
b/kernel/liveupdate/kexec_handover.c
index 2e3a36054851..dea6e7790972 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -1928,7 +1928,8 @@ static __init int kho_init(void)
for (int i = 0; i < kho_scratch_cnt; i++) {
unsigned long base_pfn = PHYS_PFN(kho_scratch[i].addr);
- unsigned long count = kho_scratch[i].size >> PAGE_SHIFT;
+ unsigned long count = ALIGN_DOWN(kho_scratch[i].size >>
PAGE_SHIFT,
+ pageblock_nr_pages);
unsigned long pfn;
Thanks,
Sourabh Jain
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH v1 1/2] kho: check scratch vs CMA alignment at runtime
2026-10-01 3:30 ` Sourabh Jain
@ 2026-10-12 14:29 ` Pratyush Yadav
0 siblings, 0 replies; 11+ messages in thread
From: Pratyush Yadav @ 2026-10-12 14:29 UTC (permalink / raw)
To: Sourabh Jain
Cc: sashiko-reviews, Aditya Gupta, Baoquan He, Madhavan Srinivasan,
Pratyush Yadav, kexec, Christophe Leroy (CS GROUP),
Mahesh Salgaonkar, Michael Ellerman, Hari Bathini, Mike Rapoport,
linux-kernel, Pasha Tatashin, linuxppc-dev, Andrew Morton,
Alexander Graf, Shrikanth Hegde, Shivang Upadhyay,
Nicholas Piggin, Ritesh Harjani (IBM)
On Thu, Oct 01 2026, Sourabh Jain wrote:
> On 28/09/26 14:11, sashiko-bot@kernel.org wrote:
>> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>> - [High] kho: bypassed scratch alignment check during resume causes memory corruption
>> --
>>
>> commit cbd7cb7f008e704b389d8dfe3306e1e83e49e8a8
>> Author: Sourabh Jain <sourabhjain@linux.ibm.com>
>>
>> kho: check scratch vs CMA alignment at runtime
>>
>> KHO requires the scratch alignment to be at least CMA_MIN_ALIGNMENT_BYTES,
>> which was previously enforced with a static_assert(). This commit replaces
>> the static_assert() with a runtime check in kho_reserve_scratch() to allow
>> KHO on configurations where the minimum alignment is not a constant.
>>
>>> diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
>>> index 7c4d86daf86d5..dc76dd6b74da7 100644
>>> --- a/kernel/liveupdate/kexec_handover.c
>>> +++ b/kernel/liveupdate/kexec_handover.c
>> [ ... ]
>>
>>> @@ -836,6 +828,21 @@ static void __init kho_reserve_scratch(void)
>>> if (!kho_enable)
>>> return;
>>> + /*
>>> + * This is the minimal alignment required by deferred struct page init.
>>> + * deferred_init_memmap_chunk frees memory to the buddy allocator, which looks
>>> + * at the neighboring pages (up to MAX_PAGE_ORDER) to merge them.
>>> + * If KHO scratch is not aligned to that value, buddy can access uninitialized
>>> + * struct pages, which can cause a crash.
>>> + */
>>> + if (WARN_ON_ONCE(SCRATCH_ALIGNMENT_BYTES < CMA_MIN_ALIGNMENT_BYTES)) {
>>> + pr_err("scratch alignment %lu < CMA minimum %lu, disabling\n",
>>> + (unsigned long)SCRATCH_ALIGNMENT_BYTES,
>>> + (unsigned long)CMA_MIN_ALIGNMENT_BYTES);
>>> + kho_enable = false;
>>> + return;
>>> + }
>>> +
>> [Severity: High]
>> Does this new runtime check get bypassed during a KHO resume?
>>
>> During a KHO resume, kho_memory_init() skips kho_reserve_scratch():
>>
>> kernel/liveupdate/kexec_handover.c:kho_memory_init() {
>> if (kho_in.scratch_phys)
>> kho_mem_retrieve();
>> else
>> kho_reserve_scratch();
>> }
>>
>> If a predecessor kernel passes a scratch region with a smaller alignment,
>> and the successor kernel has a larger pageblock_order, bypassing this check
>> means kho_init() will iterate over the provided scratch memory using the
>> successor kernel's larger pageblock_nr_pages:
>>
>> kernel/liveupdate/kexec_handover.c:kho_init() {
>> for (pfn = base_pfn; pfn < base_pfn + count;
>> pfn += pageblock_nr_pages)
>> init_cma_reserved_pageblock(pfn_to_page(pfn));
>> }
>> Can this lead to init_cma_reserved_pageblock() overwriting state for pages
>> outside the actual scratch region bounds, or cause a crash in the buddy
>> allocator if __free_pages() is called on an unaligned PFN?
>
> Yes, if the kexeced kernel has a higher pageblock_order than the
> kernel that initiated the kexec with KHO, this can cause problems when
> the code above hands scratch-memory pages back to the buddy allocator
> in the kexeced kernel.
>
> Would it make sense to handle this by keeping only the unaligned pages
> reserved and handing the remaining pages back to the buddy?
>
> Something like this:
>
> diff --git a/kernel/liveupdate/kexec_handover.c
> b/kernel/liveupdate/kexec_handover.c
> index 2e3a36054851..dea6e7790972 100644
> --- a/kernel/liveupdate/kexec_handover.c
> +++ b/kernel/liveupdate/kexec_handover.c
> @@ -1928,7 +1928,8 @@ static __init int kho_init(void)
>
> for (int i = 0; i < kho_scratch_cnt; i++) {
> unsigned long base_pfn = PHYS_PFN(kho_scratch[i].addr);
> - unsigned long count = kho_scratch[i].size >> PAGE_SHIFT;
> + unsigned long count = ALIGN_DOWN(kho_scratch[i].size >>
> PAGE_SHIFT,
> + pageblock_nr_pages);
> unsigned long pfn;
This code only runs on cold boot. So it will never run for kexec-ed
kernel. See the if (fdt) check above. It is very subtle and easy to
miss.
For kexeced kernels, the migrate type is set via
kho_scratch_migratetype() (see its callers). The logic it uses is that
if any page in the whole page block overlaps with scratch, mark it as
MIGRATE_CMA. So I think it already works with variable pageblock sizes.
>
Also, off-topic nit: your email client seems to like sending
"non-breaking space" (0xC2 0xA0 in UTF-8). For example, for indentation
in the diff above, it uses non-breaking space, and makes the diff hard
to apply. Perhaps tinker with the settings and see if you can avoid it?
--
Regards,
Pratyush Yadav
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 1/2] kho: check scratch vs CMA alignment at runtime
2026-09-28 8:32 ` [PATCH v1 1/2] kho: check scratch vs CMA alignment at runtime Sourabh Jain
2026-09-28 8:41 ` sashiko-bot
@ 2026-10-03 7:59 ` Mike Rapoport
2026-10-05 9:12 ` Sourabh Jain
2026-10-12 14:30 ` Pratyush Yadav
2 siblings, 1 reply; 11+ messages in thread
From: Mike Rapoport @ 2026-10-03 7:59 UTC (permalink / raw)
To: Sourabh Jain
Cc: kexec, Aditya Gupta, Alexander Graf, Andrew Morton, Baoquan He,
Christophe Leroy (CS GROUP),
Hari Bathini, Madhavan Srinivasan, Mahesh Salgaonkar,
Michael Ellerman, Nicholas Piggin, Pasha Tatashin,
Pratyush Yadav, Ritesh Harjani (IBM),
Shivang Upadhyay, Shrikanth Hegde, linux-kernel, linuxppc-dev
Hi,
On Mon, Sep 28, 2026 at 02:02:25PM +0530, Sourabh Jain wrote:
> KHO requires the scratch alignment to be at least CMA_MIN_ALIGNMENT_BYTES,
> and this is currently enforced with a static_assert().
>
> That assertion breaks the build on powerpc once CONFIG_KEXEC_HANDOVER is
> enabled together with CONFIG_TRANSPARENT_HUGEPAGE or CONFIG_HUGETLB_PAGE:
>
> kernel/liveupdate/kexec_handover.c:49:39: error: expression in static assertion is not constant
> 49 | static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES);
> ./include/linux/build_bug.h:80:56: note: in definition of macro '__static_assert'
> 80 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
> | ^~~~
> kernel/liveupdate/kexec_handover.c:49:1: note: in expansion of macro 'static_assert'
> 49 | static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES);
>
> CMA_MIN_ALIGNMENT_BYTES depends on pageblock_order, which is not a
> compile-time constant with certain configs, such as
> CONFIG_HUGETLB_PAGE_SIZE_VARIABLE on powerpc. The next patch in this
> series enables KHO on powerpc, so the alignment must be checked at
> runtime instead.
>
> Replace the static_assert() with a runtime check at the start of
> kho_reserve_scratch(), before any scratch memory is reserved. If the
> scratch alignment is smaller than the CMA minimum alignment, warn once
> and disable KHO rather than continue with a misaligned reservation.
Can we keep static_assert() for everything !powerpc please?
Like something along these lines:
#ifndef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
#define check_scratch_alignment static_assert(...)
#else
static inline bool check_scratch_alignment()
{
...
}
#endif
> Cc: Aditya Gupta <adityag@linux.ibm.com>
> Cc: Alexander Graf <graf@amazon.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Baoquan He <baoquan.he@linux.dev>
> Cc: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
> Cc: Hari Bathini <hbathini@linux.ibm.com>
> Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Mike Rapoport <rppt@kernel.org>
> Cc: Nicholas Piggin <npiggin@gmail.com>
> Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
> Cc: Pratyush Yadav <pratyush@kernel.org>
> Cc: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
> Cc: Shivang Upadhyay <shivangu@linux.ibm.com>
> Cc: Shrikanth Hegde <sshegde@linux.ibm.com>
> Cc: linux-kernel@vger.kernel.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> ---
> kernel/liveupdate/kexec_handover.c | 23 +++++++++++++++--------
> 1 file changed, 15 insertions(+), 8 deletions(-)
>
> diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
> index 7c4d86daf86d..dc76dd6b74da 100644
> --- a/kernel/liveupdate/kexec_handover.c
> +++ b/kernel/liveupdate/kexec_handover.c
> @@ -39,15 +39,7 @@
> #include "../kexec_internal.h"
> #include "kexec_handover_internal.h"
>
> -/*
> - * This is the minimal alignment required by deferred struct page init.
> - * deferred_init_memmap_chunk frees memory to the buddy allocator, which looks
> - * at the neighboring pages (up to MAX_PAGE_ORDER) to merge them.
> - * If KHO scratch is not aligned to that value, buddy can access uninitialized
> - * struct pages, which can cause a crash.
> - */
> #define SCRATCH_ALIGNMENT_BYTES (PAGE_SIZE * MAX_ORDER_NR_PAGES)
> -static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES);
>
> /* The magic token for preserved pages */
> #define KHO_PAGE_MAGIC 0x4b484f50U /* ASCII for 'KHOP' */
> @@ -836,6 +828,21 @@ static void __init kho_reserve_scratch(void)
> if (!kho_enable)
> return;
>
> + /*
> + * This is the minimal alignment required by deferred struct page init.
> + * deferred_init_memmap_chunk frees memory to the buddy allocator, which looks
> + * at the neighboring pages (up to MAX_PAGE_ORDER) to merge them.
> + * If KHO scratch is not aligned to that value, buddy can access uninitialized
> + * struct pages, which can cause a crash.
> + */
> + if (WARN_ON_ONCE(SCRATCH_ALIGNMENT_BYTES < CMA_MIN_ALIGNMENT_BYTES)) {
> + pr_err("scratch alignment %lu < CMA minimum %lu, disabling\n",
> + (unsigned long)SCRATCH_ALIGNMENT_BYTES,
> + (unsigned long)CMA_MIN_ALIGNMENT_BYTES);
> + kho_enable = false;
> + return;
> + }
> +
> scratch_size_update();
>
> /* FIXME: deal with node hot-plug/remove */
> --
> 2.55.0
>
--
Sincerely yours,
Mike.
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH v1 1/2] kho: check scratch vs CMA alignment at runtime
2026-10-03 7:59 ` Mike Rapoport
@ 2026-10-05 9:12 ` Sourabh Jain
0 siblings, 0 replies; 11+ messages in thread
From: Sourabh Jain @ 2026-10-05 9:12 UTC (permalink / raw)
To: Mike Rapoport
Cc: kexec, Aditya Gupta, Alexander Graf, Andrew Morton, Baoquan He,
Christophe Leroy (CS GROUP),
Hari Bathini, Madhavan Srinivasan, Mahesh Salgaonkar,
Michael Ellerman, Nicholas Piggin, Pasha Tatashin,
Pratyush Yadav, Ritesh Harjani (IBM),
Shivang Upadhyay, Shrikanth Hegde, linux-kernel, linuxppc-dev
On 03/10/26 13:29, Mike Rapoport wrote:
> Hi,
>
> On Mon, Sep 28, 2026 at 02:02:25PM +0530, Sourabh Jain wrote:
>> KHO requires the scratch alignment to be at least CMA_MIN_ALIGNMENT_BYTES,
>> and this is currently enforced with a static_assert().
>>
>> That assertion breaks the build on powerpc once CONFIG_KEXEC_HANDOVER is
>> enabled together with CONFIG_TRANSPARENT_HUGEPAGE or CONFIG_HUGETLB_PAGE:
>>
>> kernel/liveupdate/kexec_handover.c:49:39: error: expression in static assertion is not constant
>> 49 | static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES);
>> ./include/linux/build_bug.h:80:56: note: in definition of macro '__static_assert'
>> 80 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
>> | ^~~~
>> kernel/liveupdate/kexec_handover.c:49:1: note: in expansion of macro 'static_assert'
>> 49 | static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES);
>>
>> CMA_MIN_ALIGNMENT_BYTES depends on pageblock_order, which is not a
>> compile-time constant with certain configs, such as
>> CONFIG_HUGETLB_PAGE_SIZE_VARIABLE on powerpc. The next patch in this
>> series enables KHO on powerpc, so the alignment must be checked at
>> runtime instead.
>>
>> Replace the static_assert() with a runtime check at the start of
>> kho_reserve_scratch(), before any scratch memory is reserved. If the
>> scratch alignment is smaller than the CMA minimum alignment, warn once
>> and disable KHO rather than continue with a misaligned reservation.
> Can we keep static_assert() for everything !powerpc please?
Yeah, that's a good idea. We can have a dynamic check for cases
where a static check is not possible.
Thanks for the suggestion.
- Sourabh Jain
> Like something along these lines:
>
> #ifndef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
> #define check_scratch_alignment static_assert(...)
> #else
> static inline bool check_scratch_alignment()
> {
> ...
> }
> #endif
>
>
>> Cc: Aditya Gupta <adityag@linux.ibm.com>
>> Cc: Alexander Graf <graf@amazon.com>
>> Cc: Andrew Morton <akpm@linux-foundation.org>
>> Cc: Baoquan He <baoquan.he@linux.dev>
>> Cc: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
>> Cc: Hari Bathini <hbathini@linux.ibm.com>
>> Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
>> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>> Cc: Mike Rapoport <rppt@kernel.org>
>> Cc: Nicholas Piggin <npiggin@gmail.com>
>> Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
>> Cc: Pratyush Yadav <pratyush@kernel.org>
>> Cc: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
>> Cc: Shivang Upadhyay <shivangu@linux.ibm.com>
>> Cc: Shrikanth Hegde <sshegde@linux.ibm.com>
>> Cc: linux-kernel@vger.kernel.org
>> Cc: linuxppc-dev@lists.ozlabs.org
>> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
>> ---
>> kernel/liveupdate/kexec_handover.c | 23 +++++++++++++++--------
>> 1 file changed, 15 insertions(+), 8 deletions(-)
>>
>> diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
>> index 7c4d86daf86d..dc76dd6b74da 100644
>> --- a/kernel/liveupdate/kexec_handover.c
>> +++ b/kernel/liveupdate/kexec_handover.c
>> @@ -39,15 +39,7 @@
>> #include "../kexec_internal.h"
>> #include "kexec_handover_internal.h"
>>
>> -/*
>> - * This is the minimal alignment required by deferred struct page init.
>> - * deferred_init_memmap_chunk frees memory to the buddy allocator, which looks
>> - * at the neighboring pages (up to MAX_PAGE_ORDER) to merge them.
>> - * If KHO scratch is not aligned to that value, buddy can access uninitialized
>> - * struct pages, which can cause a crash.
>> - */
>> #define SCRATCH_ALIGNMENT_BYTES (PAGE_SIZE * MAX_ORDER_NR_PAGES)
>> -static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES);
>>
>> /* The magic token for preserved pages */
>> #define KHO_PAGE_MAGIC 0x4b484f50U /* ASCII for 'KHOP' */
>> @@ -836,6 +828,21 @@ static void __init kho_reserve_scratch(void)
>> if (!kho_enable)
>> return;
>>
>> + /*
>> + * This is the minimal alignment required by deferred struct page init.
>> + * deferred_init_memmap_chunk frees memory to the buddy allocator, which looks
>> + * at the neighboring pages (up to MAX_PAGE_ORDER) to merge them.
>> + * If KHO scratch is not aligned to that value, buddy can access uninitialized
>> + * struct pages, which can cause a crash.
>> + */
>> + if (WARN_ON_ONCE(SCRATCH_ALIGNMENT_BYTES < CMA_MIN_ALIGNMENT_BYTES)) {
>> + pr_err("scratch alignment %lu < CMA minimum %lu, disabling\n",
>> + (unsigned long)SCRATCH_ALIGNMENT_BYTES,
>> + (unsigned long)CMA_MIN_ALIGNMENT_BYTES);
>> + kho_enable = false;
>> + return;
>> + }
>> +
>> scratch_size_update();
>>
>> /* FIXME: deal with node hot-plug/remove */
>> --
>> 2.55.0
>>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 1/2] kho: check scratch vs CMA alignment at runtime
2026-09-28 8:32 ` [PATCH v1 1/2] kho: check scratch vs CMA alignment at runtime Sourabh Jain
2026-09-28 8:41 ` sashiko-bot
2026-10-03 7:59 ` Mike Rapoport
@ 2026-10-12 14:30 ` Pratyush Yadav
2 siblings, 0 replies; 11+ messages in thread
From: Pratyush Yadav @ 2026-10-12 14:30 UTC (permalink / raw)
To: Sourabh Jain
Cc: kexec, Aditya Gupta, Alexander Graf, Andrew Morton, Baoquan He,
Christophe Leroy (CS GROUP),
Hari Bathini, Madhavan Srinivasan, Mahesh Salgaonkar,
Michael Ellerman, Mike Rapoport, Nicholas Piggin, Pasha Tatashin,
Pratyush Yadav, Ritesh Harjani (IBM),
Shivang Upadhyay, Shrikanth Hegde, linux-kernel, linuxppc-dev
On Mon, Sep 28 2026, Sourabh Jain wrote:
> KHO requires the scratch alignment to be at least CMA_MIN_ALIGNMENT_BYTES,
> and this is currently enforced with a static_assert().
>
> That assertion breaks the build on powerpc once CONFIG_KEXEC_HANDOVER is
> enabled together with CONFIG_TRANSPARENT_HUGEPAGE or CONFIG_HUGETLB_PAGE:
>
> kernel/liveupdate/kexec_handover.c:49:39: error: expression in static assertion is not constant
> 49 | static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES);
> ./include/linux/build_bug.h:80:56: note: in definition of macro '__static_assert'
> 80 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
> | ^~~~
> kernel/liveupdate/kexec_handover.c:49:1: note: in expansion of macro 'static_assert'
> 49 | static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES);
>
> CMA_MIN_ALIGNMENT_BYTES depends on pageblock_order, which is not a
> compile-time constant with certain configs, such as
> CONFIG_HUGETLB_PAGE_SIZE_VARIABLE on powerpc. The next patch in this
> series enables KHO on powerpc, so the alignment must be checked at
> runtime instead.
>
> Replace the static_assert() with a runtime check at the start of
> kho_reserve_scratch(), before any scratch memory is reserved. If the
> scratch alignment is smaller than the CMA minimum alignment, warn once
> and disable KHO rather than continue with a misaligned reservation.
>
> Cc: Aditya Gupta <adityag@linux.ibm.com>
> Cc: Alexander Graf <graf@amazon.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Baoquan He <baoquan.he@linux.dev>
> Cc: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
> Cc: Hari Bathini <hbathini@linux.ibm.com>
> Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Mike Rapoport <rppt@kernel.org>
> Cc: Nicholas Piggin <npiggin@gmail.com>
> Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
> Cc: Pratyush Yadav <pratyush@kernel.org>
> Cc: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
> Cc: Shivang Upadhyay <shivangu@linux.ibm.com>
> Cc: Shrikanth Hegde <sshegde@linux.ibm.com>
> Cc: linux-kernel@vger.kernel.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> ---
> kernel/liveupdate/kexec_handover.c | 23 +++++++++++++++--------
> 1 file changed, 15 insertions(+), 8 deletions(-)
>
> diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
> index 7c4d86daf86d..dc76dd6b74da 100644
> --- a/kernel/liveupdate/kexec_handover.c
> +++ b/kernel/liveupdate/kexec_handover.c
> @@ -39,15 +39,7 @@
> #include "../kexec_internal.h"
> #include "kexec_handover_internal.h"
>
> -/*
> - * This is the minimal alignment required by deferred struct page init.
> - * deferred_init_memmap_chunk frees memory to the buddy allocator, which looks
> - * at the neighboring pages (up to MAX_PAGE_ORDER) to merge them.
> - * If KHO scratch is not aligned to that value, buddy can access uninitialized
> - * struct pages, which can cause a crash.
> - */
> #define SCRATCH_ALIGNMENT_BYTES (PAGE_SIZE * MAX_ORDER_NR_PAGES)
> -static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES);
>
> /* The magic token for preserved pages */
> #define KHO_PAGE_MAGIC 0x4b484f50U /* ASCII for 'KHOP' */
> @@ -836,6 +828,21 @@ static void __init kho_reserve_scratch(void)
> if (!kho_enable)
> return;
>
> + /*
> + * This is the minimal alignment required by deferred struct page init.
> + * deferred_init_memmap_chunk frees memory to the buddy allocator, which looks
> + * at the neighboring pages (up to MAX_PAGE_ORDER) to merge them.
> + * If KHO scratch is not aligned to that value, buddy can access uninitialized
> + * struct pages, which can cause a crash.
> + */
> + if (WARN_ON_ONCE(SCRATCH_ALIGNMENT_BYTES < CMA_MIN_ALIGNMENT_BYTES)) {
Nit: do we need both the WARN_ON_ONCE() and the pr_err()? Can't we drop
the WARN and keep the pr_err only?
LGTM otherwise.
> + pr_err("scratch alignment %lu < CMA minimum %lu, disabling\n",
> + (unsigned long)SCRATCH_ALIGNMENT_BYTES,
> + (unsigned long)CMA_MIN_ALIGNMENT_BYTES);
> + kho_enable = false;
> + return;
> + }
> +
> scratch_size_update();
>
> /* FIXME: deal with node hot-plug/remove */
--
Regards,
Pratyush Yadav
^ permalink raw reply [flat|nested] 11+ messages in thread