From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5228E42BC28 for ; Tue, 14 Jul 2026 20:51:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784062285; cv=none; b=WR5MRghyZUAEZ6TWz92UnwgH18NaKFDjzam/GF/kzKxSrv5+PZtlHFkcJ0TkPSoQZdHclDeicisLos1iyxUOKDbJW8mPGgKtU1ZIWJBjdv0EgU3MK7KMtRyrx+mWVV3hDm5LOLyMSx1mEaL4RLnjuu8zdXXQfZXWUrna25dhSJQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784062285; c=relaxed/simple; bh=6G/n1Up45Y4QyD1GNiH2ddR2BHzgTKKfxDUN2T9cLT8=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=SmsTtUu6+S2FABma2+MycnePm/o8plBtZdPzbcFZlVWYbm7sDYXR9zeEM7sUcH0HQnPURpcMhqIHnOwAtidLcnjT1HW77TSP1ESmw26lsX21UFFgqZavHat5z7CGTsVhPMGIrD3D11oQVka+JXhf/e0R1/+JNw6J5Gn/T7nb8YU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--mclapinski.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=tCC35IKa; arc=none smtp.client-ip=209.85.128.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--mclapinski.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="tCC35IKa" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-492714d002cso9333105e9.0 for ; Tue, 14 Jul 2026 13:51:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1784062282; x=1784667082; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:mime-version:date:from :to:cc:subject:date:message-id:reply-to:content-type; bh=d9tldHgHpDRf8TAZCwFzg+tWQLwf+4+RS0Dz7CW5np8=; b=tCC35IKaAw7cFFCJzf3nTqEcs7UqpwY9k3L+YP75Qzxss/NWGfKTbzb+uKwhhwg9Eb MqXBFSq7M8PQPVUvh/kiLogq9lRLtwR/4Ix4xHP+Z0mCbLlPrkShvLFIzVaGjWdgTpg0 KqPVKAPtvxlgaickDupHognIwdjCCMIpSTtAO08ywgJtOUuWjYGrzhC3QZjuVN16cn/f mbojXtY6Vl3TfepBNRuEJxM9wKaoeFNIndsHBBdcikoM/RLp8Gc9dLN/iQhp9C1XwccN iXLpSlfkmUqF+N8YMa2zG/kPB0CeS4vjjyCoHSHhSyGYZlILqlpvts6uMr2hutn1qWhJ LICg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784062282; x=1784667082; h=content-type:cc:to:from:subject:message-id:mime-version:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=d9tldHgHpDRf8TAZCwFzg+tWQLwf+4+RS0Dz7CW5np8=; b=oqkjN8kmIhEhMgMelXzKZmUDi82mgVD7ue75922jfbzk+9CZjDXEoRORuViDbm5ypj 0QIUziORC3AFe7Kg8suDb0IoKqSntyXfsGYTwnaBAwW9q/4B7k7Mqaksy7dHX8yD+RLF rRYOGDitobw2oECLIxbiAExVVTu0dKJ7cUAJkg03X+IOP12geeSehlIhLEqZ+QvTaF4x k7J2pcbhbHRK4WTzYzJx8bfWRHhKPhegCzDMDpRLF1qs9oJMSG989ZKp41+rfQjLr2yJ Ae6hq6AnX1L1VNwpG7F7+0C4A1yxbtFnHiiSoN/E/EEkwLPv36+gJgOpacWEs2hoymHK fxYw== X-Forwarded-Encrypted: i=1; AHgh+Rq2SKi9oeB6Yi57MxilUPJt+u1/HERkg4LQ3QKhuk9GEveCaQWvUR7/B/Xr9JzFjr2RkO3CyBhFIGZp+AY=@vger.kernel.org X-Gm-Message-State: AOJu0YyWdw6tFEQ3EOglqR09sxeZiTT7j73cO1Tsbmvr04M1AVpD87+L +TFtBm6bA8stIRo2BSjaTW39LoSjcKZ0DwHD3KFHjcNjhjjNVKKhnVMASM69rW03L/bgrsp1/SU wJrCbVztbaFnKJhZU60Vf6Q== X-Received: from wmkz11.prod.google.com ([2002:a7b:c7cb:0:b0:493:b78f:716b]) (user=mclapinski job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:3f06:b0:493:b9cd:1272 with SMTP id 5b1f17b1804b1-493f881de56mr144831135e9.23.1784062282098; Tue, 14 Jul 2026 13:51:22 -0700 (PDT) Date: Tue, 14 Jul 2026 22:51:11 +0200 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 X-Mailer: git-send-email 2.55.0.141.g00534a21ce-goog Message-ID: <20260714205111.2497151-1-mclapinski@google.com> Subject: [PATCH] kho: align kho_scratch to MAX_ORDER_NR_PAGES pages From: Michal Clapinski To: Mike Rapoport , Pasha Tatashin , Pratyush Yadav , Alexander Graf , Evangelos Petrongonas , kexec@lists.infradead.org Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Michal Clapinski Content-Type: text/plain; charset="UTF-8" I caught this crash: BUG: unable to handle page fault for address: ff19164fffff8328 RIP: 0010:__free_one_page+0x1a1/0x6b0 Call Trace: [] free_one_page+0xaf/0x240 [] deferred_free_pages+0xa8/0xd0 [] deferred_init_memmap_chunk+0x10f/0x1b0 [] padata_mt_helper+0x65/0xa0 [] process_scheduled_works+0x202/0x410 [] worker_thread+0x1f9/0x2d0 [] kthread+0x27d/0x2f0 [] ? __pfx_worker_thread+0x10/0x10 [] ? __pfx_kthread+0x10/0x10 [] ret_from_fork+0x145/0x280 [] ? __pfx_kthread+0x10/0x10 [] ret_from_fork_asm+0x1a/0x30 deferred_init_memmap_chunk() works fine without KHO because free regions will never be neighbors. However, with KHO, free memory will be split into (free && scratch) and (free && !scratch). KHO scratch is aligned to CMA_MIN_ALIGNMENT_BYTES (which on my setup is equal to 1 << 9 pages) but buddy can look at the neighborhood of MAX_ORDER_NR_PAGES pages (which is equal to 1 << 10 pages). This sometimes crashes when one half of the neighborhood is being initialized but the other part is yet to be initialized. To fix this, let's just align KHO scratch to MAX_ORDER_NR_PAGES pages. Fixes: c6073743d0c7 ("kho: make preserved pages compatible with deferred struct page init") Signed-off-by: Michal Clapinski --- Unfortunately, this is very hard to catch, so I don't have a good reproducer. But I run the code with the fix through extensive testing and it seems fine. I think I've never caught it before because enabling HUGETLB is what causes CMA_MIN_ALIGNMENT_PAGES to be 1 << 9, instead of 1 << 10. If this passes review, please cherry-pick it to 7.2 so we don't release a broken kernel. --- kernel/liveupdate/kexec_handover.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c index 4834a809985a..50928aaa3371 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -38,6 +38,16 @@ #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 (1 << (PAGE_SHIFT + MAX_PAGE_ORDER)) +static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES); + /* The magic token for preserved pages */ #define KHO_PAGE_MAGIC 0x4b484f50U /* ASCII for 'KHOP' */ @@ -640,8 +650,8 @@ static void __init scratch_size_update(void) * Scratch areas are released as MIGRATE_CMA. Round them up to the right * size. */ - scratch_size_lowmem = round_up(scratch_size_lowmem, CMA_MIN_ALIGNMENT_BYTES); - scratch_size_global = round_up(scratch_size_global, CMA_MIN_ALIGNMENT_BYTES); + scratch_size_lowmem = round_up(scratch_size_lowmem, SCRATCH_ALIGNMENT_BYTES); + scratch_size_global = round_up(scratch_size_global, SCRATCH_ALIGNMENT_BYTES); } static phys_addr_t __init scratch_size_node(int nid) @@ -656,7 +666,7 @@ static phys_addr_t __init scratch_size_node(int nid) size = scratch_size_pernode; } - return round_up(size, CMA_MIN_ALIGNMENT_BYTES); + return round_up(size, SCRATCH_ALIGNMENT_BYTES); } /** @@ -692,7 +702,7 @@ static void __init kho_reserve_scratch(void) * next kernel */ size = scratch_size_lowmem; - addr = memblock_phys_alloc_range(size, CMA_MIN_ALIGNMENT_BYTES, 0, + addr = memblock_phys_alloc_range(size, SCRATCH_ALIGNMENT_BYTES, 0, ARCH_LOW_ADDRESS_LIMIT); if (!addr) { pr_err("Failed to reserve lowmem scratch buffer\n"); @@ -705,7 +715,7 @@ static void __init kho_reserve_scratch(void) /* reserve large contiguous area for allocations without nid */ size = scratch_size_global; - addr = memblock_phys_alloc(size, CMA_MIN_ALIGNMENT_BYTES); + addr = memblock_phys_alloc(size, SCRATCH_ALIGNMENT_BYTES); if (!addr) { pr_err("Failed to reserve global scratch buffer\n"); goto err_free_scratch_areas; @@ -721,7 +731,7 @@ static void __init kho_reserve_scratch(void) */ for_each_node_state(nid, N_MEMORY) { size = scratch_size_node(nid); - addr = memblock_alloc_range_nid(size, CMA_MIN_ALIGNMENT_BYTES, + addr = memblock_alloc_range_nid(size, SCRATCH_ALIGNMENT_BYTES, 0, MEMBLOCK_ALLOC_ACCESSIBLE, nid, true); if (!addr) { -- 2.55.0.141.g00534a21ce-goog