From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793811020; b=uWTStdi4sQEvKYuoG2dL0Wj5uJanYXbmA3dOX/ATUyFpN5LFSnZhylmETyMzwEpfyrFY Y2Xhmi3fhZ+fu5rw3Pj/kMqPJvriALs7MZJplQbznWzreu49CnO4Z0b+6bLFVBcYgApoS 4yCBYvXTvQgH7Pb+AVKXMYhpPaNFjyFOkhJfaUAeCJMTf+8+6D5mcLOgFpPwYrEcCuQZy MMBYbw3gXBKEUbRS7PUOSTpD5uEZb0VZGVTYr1HzHllplL/4fdfOFXJAKqAiAdyLiMxI1 vPgGVSgi5P6tS+972ZmxvW1BpDlDSPn+d45A/hUugqjbqk6t5i6/yd9K+sNVtHXGMVw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793811020; h=Received:DKIM-Signature:From:Date:Subject:MIME-Version:Content-Type: Content-Transfer-Encoding:Message-Id:References:In-Reply-To:To:Cc: X-Mailer; bh=kvZ5XnxdxIW2P/kVJf4H5CXZ0aIg/W594yfUcOxNZPc=; b=H9asCcrPX5cNiFcmirjhPERi6hj74nzsVtbAX7ZAymGIjESaTSMjmDVlIIIO9P5Hv6xg Vgz1hLyFjP++cRl55ldGwgySHawYNFwWDbvrSHyMZN53o/id5+pOjZkNEZfnICUAerPtr 9i6VBZbVIxUCLbc0jhigcsnh3w7/u3w89ghiG6RiZ1e1HJXJdjdGp+tFGFR7+QgnWwipp Fmw+SdERfCavUTols5M4l7FL2/FOz91D4Y6eYMuEx9Gt2iM+8y5cC2GSqU+r+OoabkUR8 IV5YpmBE7WZ5yx2NpI5T8CIiu4fZ6L9foaxvZL2gYaHXU12kLnnEWipKWi8bmNb93hA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=OrV0p0IV; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E20116082BD8 for ; Wed, 4 Nov 2026 16:50:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=OrV0p0IV Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0316E1F00A15; Wed, 4 Nov 2026 16:50:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1793811019; bh=kvZ5XnxdxIW2P/kVJf4H5CXZ0aIg/W594yfUcOxNZPc=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=OrV0p0IVAw9DP4Kokc9d6E9ta+ht4bkjrdGuDvM1eepif0lae0cEYg1sM1ZcXQBcg J9ChDTB9CYfELh/48UhZe7Jxf5NNvFFccS8qFAyyInz3AYU8osJD+wFdgK5mN0JdDy yKhGlLB7zLJvVMXF4Mw1WMkJAjRyLzml5wKH2/jdC5CuGTWAVia+MkEQ1tZwAhSoeQ ooFzd/iHmeaG3rg4YpJcaL22VPZvae4mjVVqx6L6EumhzvpsiMCrbO9OnqD/PtN7LB T+NlyZLKBSFgQdg94qXVHWFVJvR3ThloVy6yYcEftDrEbICo19QP4zcmf672CU9lSu 3Qt6m3gZnsg4A== From: "Mike Rapoport (Microsoft)" Date: Wed, 04 Nov 2026 18:50:09 +0200 Subject: [PATCH v2 1/3] kho: walk bootmem areas in address order X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20261104-kho-bootmem-sizing-v2-1-b0d1a834780f@kernel.org> References: <20261104-kho-bootmem-sizing-v2-0-b0d1a834780f@kernel.org> In-Reply-To: <20261104-kho-bootmem-sizing-v2-0-b0d1a834780f@kernel.org> To: Mike Rapoport , Pasha Tatashin , Pratyush Yadav Cc: Alexander Graf , Andrew Morton , Chen Pei , George Guo , Kexin Liu , Sourabh Jain , kexec@lists.infradead.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org X-Mailer: b4 0.16.1-dev kexec_add_buffer() users may depend on the order in which memory holes are searched. For instance, arm64 places the kernel bottom-up and then requires the DTB to be above the kernel. kho_walk_bootmem() walks the bootmem areas in the order they were reserved, so if the kernel lands in a small area at the top of the memory there is no room left for the DTB and kexec fails. For example, on an arm64 VM with 2G of RAM and kho_bootmem=8M,64M,64M, the lowmem area is reserved first at the top of the memory, the kernel image takes most of it and kexec fails with kexec_file(Image): Could not find any suitable kernel location! Sort the bootmem areas by address and walk them in ascending order, or in descending order for top-down searches, like kexec_walk_resources() does. Fixes: 3bdecc3c93f9 ("kexec: add KHO support to kexec file loads") Signed-off-by: Mike Rapoport (Microsoft) --- kernel/liveupdate/kexec_handover.c | 57 ++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c index 6f1f55fe31819..2ac5d94f33fd4 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -820,6 +821,14 @@ bool kho_bootmem_overlap(phys_addr_t phys, size_t size) return false; } +static int __init kho_bootmem_cmp(const void *_a, const void *_b) +{ + const struct kho_bootmem *a = _a; + const struct kho_bootmem *b = _b; + + return cmp_int(a->addr, b->addr); +} + /** * kho_reserve_bootmem - Reserve a contiguous chunk of memory for kexec * @@ -904,6 +913,9 @@ static void __init kho_reserve_bootmem(void) */ kho_bootmem_cnt = i; + sort(kho_bootmem, kho_bootmem_cnt, sizeof(*kho_bootmem), + kho_bootmem_cmp, NULL); + return; err_free_bootmem_areas: @@ -2081,20 +2093,40 @@ int kho_fill_kimage(struct kimage *image) return 0; } -static int kho_walk_bootmem(struct kexec_buf *kbuf, - int (*func)(struct resource *, void *)) +static int kho_bootmem_walk_one(struct kexec_buf *kbuf, + const struct kho_bootmem *area, + int (*func)(struct resource *, void *)) +{ + struct resource res = { + .start = area->addr, + .end = area->addr + area->size - 1, + }; + + /* Try to fit the kbuf into our KHO bootmem region */ + return func(&res, kbuf); +} + +static int kho_bootmem_walk_top_down(struct kexec_buf *kbuf, + int (*func)(struct resource *, void *)) { int ret = 0; - int i; - for (i = 0; i < kho_bootmem_cnt; i++) { - struct resource res = { - .start = kho_bootmem[i].addr, - .end = kho_bootmem[i].addr + kho_bootmem[i].size - 1, - }; + for (int i = kho_bootmem_cnt - 1; i >= 0; i--) { + ret = kho_bootmem_walk_one(kbuf, &kho_bootmem[i], func); + if (ret) + break; + } + + return ret; +} - /* Try to fit the kimage into our KHO bootmem region */ - ret = func(&res, kbuf); +static int kho_bootmem_walk_bottom_up(struct kexec_buf *kbuf, + int (*func)(struct resource *, void *)) +{ + int ret = 0; + + for (int i = 0; i < kho_bootmem_cnt; i++) { + ret = kho_bootmem_walk_one(kbuf, &kho_bootmem[i], func); if (ret) break; } @@ -2110,7 +2142,10 @@ int kho_locate_mem_hole(struct kexec_buf *kbuf, if (!kho_enable || kbuf->image->type == KEXEC_TYPE_CRASH) return 1; - ret = kho_walk_bootmem(kbuf, func); + if (kbuf->top_down) + ret = kho_bootmem_walk_top_down(kbuf, func); + else + ret = kho_bootmem_walk_bottom_up(kbuf, func); return ret == 1 ? 0 : -EADDRNOTAVAIL; } -- 2.53.0