From nobody Thu Apr 9 18:39:41 2026 Received: from stravinsky.debian.org (stravinsky.debian.org [82.195.75.108]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4AE3321D3F3 for ; Fri, 6 Mar 2026 12:39:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=82.195.75.108 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800787; cv=none; b=Nzjx3A6lmp9Xc+4/4OAzVrdIRyLEjjenXAytg1nyraaUgOo3XpAVLZM4nNOLCKpRwLdYy+3eaUX9XkqgQZHhhW9l2y2EMfJbxqZRKAydFuqHuD7d5LdMFdScso+RH/ui9rPU27w2wa58ftw7AMhDH6/b2mpDA/VWsTA5VBSEa90= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800787; c=relaxed/simple; bh=aU0aIKTD5Anicm9v3gMTJTcMaA4+bBorKPfkcBjPpeQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qNKtlWJ4zK/W135viYRBbk/Vq1LRzJ+w4xcY7D0eJDrkdA7AotfxbVn8ompY4hqJ69ztfdOh3lombeAJUM63hb2CjlVjcmDde5LhI7w1YqKaxgKJzTumf6OzDaQOdp3STna21iVXAjrqIMzQTHDcFK0QlC+KYzdFMkEz7PaHn40= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org; spf=none smtp.mailfrom=debian.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b=hB9MGqs4; arc=none smtp.client-ip=82.195.75.108 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=debian.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b="hB9MGqs4" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debian.org; s=smtpauto.stravinsky; h=X-Debian-User:Cc:To:In-Reply-To:References: Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description; bh=/9ZZhOrRGryuFNle00hDqS1xUJYiiR7dmjtWIiWkagc=; b=hB9MGqs4culLZLiYWcWP3nDmG6 8dL3LATUrnFdhwEr3deIpYBrFS4ATW2ogSywz3ypFEFuqAVd63tunxm1cK8WjSWYjNSidP+ySbpeK 1A54Mgp/TxEPAS1S7gT0R3GFlfIeyRP7HAzNokpV+KSG2yF4nUWXMSRp3kaYpar6F/r52+UZONjzF //mHO5C64a/pxDXXzsb1RYyv7196ZPAiEL3fJL8W1C5oaw07bQcYYrElU+qA2PnTxkOwBhSdCKLne lLOtzEEYiwGqEUZi86quSUTpKD+Zd+vdSkFosHTEGsaF1TPOyVWT+d3oU8pnplQamIscWxQZ+IqLY P6chfsyQ==; Received: from authenticated user by stravinsky.debian.org with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94.2) (envelope-from ) id 1vyUT1-00HVQp-Id; Fri, 06 Mar 2026 12:39:43 +0000 From: Breno Leitao Date: Fri, 06 Mar 2026 04:39:20 -0800 Subject: [PATCH v7 1/6] kho: add size parameter to kho_add_subtree() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260306-kho-v7-1-404d14c188bb@debian.org> References: <20260306-kho-v7-0-404d14c188bb@debian.org> In-Reply-To: <20260306-kho-v7-0-404d14c188bb@debian.org> To: Alexander Graf , Mike Rapoport , Pasha Tatashin , Pratyush Yadav Cc: linux-kernel@vger.kernel.org, kexec@lists.infradead.org, linux-mm@kvack.org, usamaarif642@gmail.com, Breno Leitao , SeongJae Park , kernel-team@meta.com X-Mailer: b4 0.15-dev-363b9 X-Developer-Signature: v=1; a=openpgp-sha256; l=9284; i=leitao@debian.org; h=from:subject:message-id; bh=aU0aIKTD5Anicm9v3gMTJTcMaA4+bBorKPfkcBjPpeQ=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBpqssG94pdUHt2hmIjeeygau4tEj4H7e4RiVM+0 3hciBh7d6mJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCaarLBgAKCRA1o5Of/Hh3 bV1FD/9q+a1pubFJwKs2Fvw8WVcCZJoO1Xh09djVVEtaRVNIMy3iRNq+Fy7fdj34BmZP58w5TUE NTNmmyrLr/1Jol6JJnNl4UGjO0SrEvq2e/i/ypRC7Rdb//UhIQDodVq5NTPkJdOcJzAKnv96iTf gyNpB4Y+P2YAceP2EsEtYNudAzVvlfQP/ORXVniZqRX0fTcztGpjk4p6of9TrnG81g51X0uLtIr yU6VJB2XeF0OqGBm4ZlyHw9NnILYBPTUd2b6d97jjzzITajP+GlVdBNfwpnZAxI7mJOLuWFkbj9 xsaLzX5E+QFy6RONDOkExKdyN0zjdpbCPqkzZOcBkEmgesh67NiS5k45CA9BDedXKvmu1/POWSl 8S0BpxPL6j9hjhcU24WzS+QbkPvv+vcdmFCFUt825p0D7iKy11P0LdMdjV3j6Fx4kny9kmXwwJ9 ZwNCkJGfs8A/KgpRzj/8bBuY/0GDibSHsw27Jgqkz77WPXNNrPbHyP/b60FODl26RskKjhXuSLa CJOxiay+R8+KW7mzHKCJC6wGeUph1YeqnLrBdD7SFWPEIxoYF9PIQSE7Mv19IYIw9aT0ayKgFiU /fEi0QRw7CItLpPj4Ht/FkF+IwSxNT4FoGUYkaVhLbZpkPnulNonuZgy8FIx0QhOQ7Ha+tOycC7 OV19Rd7ZECwmmfQ== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D X-Debian-User: leitao kho_add_subtree() assumes the fdt argument is always an FDT and calls fdt_totalsize() on it in the debugfs code path. This assumption will break if a caller passes arbitrary data instead of an FDT. When CONFIG_KEXEC_HANDOVER_DEBUGFS is enabled, kho_debugfs_fdt_add() calls __kho_debugfs_fdt_add(), which executes: f->wrapper.size =3D fdt_totalsize(fdt); Fix this by adding an explicit size parameter to kho_add_subtree() so callers specify the blob size. This allows subtrees to contain arbitrary data formats, not just FDTs. Update all callers: - memblock.c: use fdt_totalsize(fdt) - luo_core.c: use fdt_totalsize(fdt_out) - test_kho.c: use fdt_totalsize() - kexec_handover.c (root fdt): use fdt_totalsize(kho_out.fdt) Also update __kho_debugfs_fdt_add() to receive the size explicitly instead of computing it internally via fdt_totalsize(). In kho_in_debugfs_init(), pass fdt_totalsize() for the root FDT and sub-blobs since all current users are FDTs. A subsequent patch will persist the size in the KHO FDT so the incoming side can handle non-FDT blobs correctly. Suggested-by: Pratyush Yadav Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: Breno Leitao Acked-by: SeongJae Park --- include/linux/kexec_handover.h | 4 ++-- kernel/liveupdate/kexec_handover.c | 8 +++++--- kernel/liveupdate/kexec_handover_debugfs.c | 15 +++++++++------ kernel/liveupdate/kexec_handover_internal.h | 5 +++-- kernel/liveupdate/luo_core.c | 3 ++- lib/test_kho.c | 3 ++- mm/memblock.c | 2 +- 7 files changed, 24 insertions(+), 16 deletions(-) diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h index ac4129d1d7416..abb1d324f42d0 100644 --- a/include/linux/kexec_handover.h +++ b/include/linux/kexec_handover.h @@ -32,7 +32,7 @@ void kho_restore_free(void *mem); struct folio *kho_restore_folio(phys_addr_t phys); struct page *kho_restore_pages(phys_addr_t phys, unsigned long nr_pages); void *kho_restore_vmalloc(const struct kho_vmalloc *preservation); -int kho_add_subtree(const char *name, void *fdt); +int kho_add_subtree(const char *name, void *fdt, size_t size); void kho_remove_subtree(void *fdt); int kho_retrieve_subtree(const char *name, phys_addr_t *phys); =20 @@ -97,7 +97,7 @@ static inline void *kho_restore_vmalloc(const struct kho_= vmalloc *preservation) return NULL; } =20 -static inline int kho_add_subtree(const char *name, void *fdt) +static inline int kho_add_subtree(const char *name, void *fdt, size_t size) { return -EOPNOTSUPP; } diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_h= andover.c index b64f36a452965..55bdc5d2d1929 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -752,6 +752,7 @@ static void __init kho_reserve_scratch(void) * kho_add_subtree - record the physical address of a sub FDT in KHO root = tree. * @name: name of the sub tree. * @fdt: the sub tree blob. + * @size: size of the blob in bytes. * * Creates a new child node named @name in KHO root FDT and records * the physical address of @fdt. The pages of @fdt must also be preserved @@ -763,7 +764,7 @@ static void __init kho_reserve_scratch(void) * * Return: 0 on success, error code on failure */ -int kho_add_subtree(const char *name, void *fdt) +int kho_add_subtree(const char *name, void *fdt, size_t size) { phys_addr_t phys =3D virt_to_phys(fdt); void *root_fdt =3D kho_out.fdt; @@ -788,7 +789,7 @@ int kho_add_subtree(const char *name, void *fdt) if (err < 0) goto out_pack; =20 - WARN_ON_ONCE(kho_debugfs_fdt_add(&kho_out.dbg, name, fdt, false)); + WARN_ON_ONCE(kho_debugfs_fdt_add(&kho_out.dbg, name, fdt, size, false)); =20 out_pack: fdt_pack(root_fdt); @@ -1452,7 +1453,8 @@ static __init int kho_init(void) } =20 WARN_ON_ONCE(kho_debugfs_fdt_add(&kho_out.dbg, "fdt", - kho_out.fdt, true)); + kho_out.fdt, + fdt_totalsize(kho_out.fdt), true)); =20 return 0; =20 diff --git a/kernel/liveupdate/kexec_handover_debugfs.c b/kernel/liveupdate= /kexec_handover_debugfs.c index 3f395fbd978f4..b5a1e09ca8f14 100644 --- a/kernel/liveupdate/kexec_handover_debugfs.c +++ b/kernel/liveupdate/kexec_handover_debugfs.c @@ -24,7 +24,7 @@ struct fdt_debugfs { }; =20 static int __kho_debugfs_fdt_add(struct list_head *list, struct dentry *di= r, - const char *name, const void *fdt) + const char *name, const void *fdt, size_t size) { struct fdt_debugfs *f; struct dentry *file; @@ -34,7 +34,7 @@ static int __kho_debugfs_fdt_add(struct list_head *list, = struct dentry *dir, return -ENOMEM; =20 f->wrapper.data =3D (void *)fdt; - f->wrapper.size =3D fdt_totalsize(fdt); + f->wrapper.size =3D size; =20 file =3D debugfs_create_blob(name, 0400, dir, &f->wrapper); if (IS_ERR(file)) { @@ -49,7 +49,7 @@ static int __kho_debugfs_fdt_add(struct list_head *list, = struct dentry *dir, } =20 int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name, - const void *fdt, bool root) + const void *fdt, size_t size, bool root) { struct dentry *dir; =20 @@ -58,7 +58,7 @@ int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const ch= ar *name, else dir =3D dbg->sub_fdt_dir; =20 - return __kho_debugfs_fdt_add(&dbg->fdt_list, dir, name, fdt); + return __kho_debugfs_fdt_add(&dbg->fdt_list, dir, name, fdt, size); } =20 void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, void *fdt) @@ -112,7 +112,8 @@ __init void kho_in_debugfs_init(struct kho_debugfs *dbg= , const void *fdt) goto err_rmdir; } =20 - err =3D __kho_debugfs_fdt_add(&dbg->fdt_list, dir, "fdt", fdt); + err =3D __kho_debugfs_fdt_add(&dbg->fdt_list, dir, "fdt", fdt, + fdt_totalsize(fdt)); if (err) goto err_rmdir; =20 @@ -120,6 +121,7 @@ __init void kho_in_debugfs_init(struct kho_debugfs *dbg= , const void *fdt) int len =3D 0; const char *name =3D fdt_get_name(fdt, child, NULL); const u64 *fdt_phys; + void *sub_fdt; =20 fdt_phys =3D fdt_getprop(fdt, child, "fdt", &len); if (!fdt_phys) @@ -129,8 +131,9 @@ __init void kho_in_debugfs_init(struct kho_debugfs *dbg= , const void *fdt) name, len); continue; } + sub_fdt =3D phys_to_virt(*fdt_phys); err =3D __kho_debugfs_fdt_add(&dbg->fdt_list, sub_fdt_dir, name, - phys_to_virt(*fdt_phys)); + sub_fdt, fdt_totalsize(sub_fdt)); if (err) { pr_warn("failed to add fdt %s to debugfs: %pe\n", name, ERR_PTR(err)); diff --git a/kernel/liveupdate/kexec_handover_internal.h b/kernel/liveupdat= e/kexec_handover_internal.h index 9a832a35254cf..2a28cb8db9b0a 100644 --- a/kernel/liveupdate/kexec_handover_internal.h +++ b/kernel/liveupdate/kexec_handover_internal.h @@ -27,7 +27,7 @@ int kho_debugfs_init(void); void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt); int kho_out_debugfs_init(struct kho_debugfs *dbg); int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name, - const void *fdt, bool root); + const void *fdt, size_t size, bool root); void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, void *fdt); #else static inline int kho_debugfs_init(void) { return 0; } @@ -35,7 +35,8 @@ static inline void kho_in_debugfs_init(struct kho_debugfs= *dbg, const void *fdt) { } static inline int kho_out_debugfs_init(struct kho_debugfs *dbg) { return 0= ; } static inline int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char = *name, - const void *fdt, bool root) { return 0; } + const void *fdt, size_t size, + bool root) { return 0; } static inline void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, void *fdt) { } #endif /* CONFIG_KEXEC_HANDOVER_DEBUGFS */ diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c index 84ac728d63baa..04d06a0906c0e 100644 --- a/kernel/liveupdate/luo_core.c +++ b/kernel/liveupdate/luo_core.c @@ -172,7 +172,8 @@ static int __init luo_fdt_setup(void) if (err) goto exit_free; =20 - err =3D kho_add_subtree(LUO_FDT_KHO_ENTRY_NAME, fdt_out); + err =3D kho_add_subtree(LUO_FDT_KHO_ENTRY_NAME, fdt_out, + fdt_totalsize(fdt_out)); if (err) goto exit_free; luo_global.fdt_out =3D fdt_out; diff --git a/lib/test_kho.c b/lib/test_kho.c index 7ef9e40618696..2631824373152 100644 --- a/lib/test_kho.c +++ b/lib/test_kho.c @@ -143,7 +143,8 @@ static int kho_test_preserve(struct kho_test_state *sta= te) if (err) goto err_unpreserve_data; =20 - err =3D kho_add_subtree(KHO_TEST_FDT, folio_address(state->fdt)); + err =3D kho_add_subtree(KHO_TEST_FDT, folio_address(state->fdt), + fdt_totalsize(folio_address(state->fdt))); if (err) goto err_unpreserve_data; =20 diff --git a/mm/memblock.c b/mm/memblock.c index ae6a5af46bd78..29e12ea2a854c 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -2488,7 +2488,7 @@ static int __init prepare_kho_fdt(void) if (err) goto err_unpreserve_fdt; =20 - err =3D kho_add_subtree(MEMBLOCK_KHO_FDT, fdt); + err =3D kho_add_subtree(MEMBLOCK_KHO_FDT, fdt, fdt_totalsize(fdt)); if (err) goto err_unpreserve_fdt; =20 --=20 2.47.3 From nobody Thu Apr 9 18:39:41 2026 Received: from stravinsky.debian.org (stravinsky.debian.org [82.195.75.108]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2CBDD245019 for ; Fri, 6 Mar 2026 12:39:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=82.195.75.108 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800791; cv=none; b=mqn/jJh5wgT3Lag9iYUWg+w/8LhwNY4VyYO4fY6oz6ymmXLpvU1dJdF9f0RIjwgIIr+O2yZjRLbyY+7vuBqz+GJ5kbv6SiYu77AgcXult7QqyPnvYeowIONMyc0v+iK1ctn/ajb8q87FOICXjnRsTufIRJYx3F+1AwGJiGb9CcI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800791; c=relaxed/simple; bh=7TBdPTTYw0zoMn471vRtwsNMfp1d8kR2nSnZkv9zjn8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=azw1eQ6HP+TFW7jURn7W4bg6Gkz+WYwdD8o4IYMkRnYdAvQDccdPgdjFBfDX5eDxGKQpJdHvijfe2Ay7/DN/bcT5BCuvVVe6F2vBEqCmSrummerXpZGPYThOo10WqESJtgORObIvhZ766srZGKLLP1g+NAVh4LfJ9f53Z1yUX+g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org; spf=none smtp.mailfrom=debian.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b=MTAQI/o5; arc=none smtp.client-ip=82.195.75.108 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=debian.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b="MTAQI/o5" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debian.org; s=smtpauto.stravinsky; h=X-Debian-User:Cc:To:In-Reply-To:References: Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description; bh=7jPQeI5iP3IUgbGEOnO1hH1SOYsnp9o5xyKhbpyewiY=; b=MTAQI/o5Y/id2t27NCQhGVgayc 3aPClizN8r9PBlf3ZltBKLzXx4p5twH5vFtYD44R1k+G6JGRbuDK7or6f8MdbUHC4IU/08V3RcFWa VF6vnZSf1EErtObcG8DwG1L2x65j7gCOLdtLLr00TPVZthoF/3EfSlAFvYoMIBABMz2Rn/kl74WyU Bb94Sv6OBK5hLcfmOHGteH5AHQswa16ur1Ro7XwvSSmTu6UZgJzsEaMc0hTXsBv+sQMBa/3JsvShD WVslXBUtYz2TB5NDWPP8nShDN40HZzyvHdzJoJwFU0HtAGVhKkNGpPy2VpzT0eBzi+be3Yrq9dj6V NnGe4i3g==; Received: from authenticated user by stravinsky.debian.org with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94.2) (envelope-from ) id 1vyUT5-00HVQx-IB; Fri, 06 Mar 2026 12:39:47 +0000 From: Breno Leitao Date: Fri, 06 Mar 2026 04:39:21 -0800 Subject: [PATCH v7 2/6] kho: rename fdt parameter to blob in kho_add/remove_subtree() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260306-kho-v7-2-404d14c188bb@debian.org> References: <20260306-kho-v7-0-404d14c188bb@debian.org> In-Reply-To: <20260306-kho-v7-0-404d14c188bb@debian.org> To: Alexander Graf , Mike Rapoport , Pasha Tatashin , Pratyush Yadav Cc: linux-kernel@vger.kernel.org, kexec@lists.infradead.org, linux-mm@kvack.org, usamaarif642@gmail.com, Breno Leitao , SeongJae Park , kernel-team@meta.com X-Mailer: b4 0.15-dev-363b9 X-Developer-Signature: v=1; a=openpgp-sha256; l=9178; i=leitao@debian.org; h=from:subject:message-id; bh=7TBdPTTYw0zoMn471vRtwsNMfp1d8kR2nSnZkv9zjn8=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBpqssGIKZGmNU3hCa8g+ly8QAVPqzEA2R1Rg2uN KR/bNTpMK+JAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCaarLBgAKCRA1o5Of/Hh3 bUByD/wOMNonG5IbxBIjvypv0cfOhp/C09PFjscftPB7DDHHdzuVeGg022d8R2Ir2LZxv+H/2CU Xxvu6aZ5/EBb5LZjFs9ZNAkwpajLgU+2NNpBlEXsRDvdq1HMICdgzGgonajCLlykT4QBXFZb4Kk gY5issaX5MSr3s27QJN6U0cPH/UFfA392XzCtMbXTftbB+zOyMVY0RJnTyD+0JzGZqQmNhzRtBQ uT7AHGkmeXhwZ+TqeQoTerxq0JAJw8ocqHejB1fTJGmJGA2OdAjTpbRSmWRTStJn/HF/aHuZAhN oNSU3Cajhy1PigzDUyrjc5sX0CGjIJFTofyXYveETtl/tRBOH+3WeyckmRXjBpsbCbB0Np5LTLH oJQ18OWWOgKx9UOiUs8qdTT2ntoyX75kboQJysmAXfvp/5Bx0yAds5UFJcXtt55g9vf1k2qfV3G yC2BPIujO/Ep7qZPv3AMb89rN83jUxjgz+zYrTH2BjB8xb0cWh3CwvVBQ3jKZF9tYxDCXcalhvn cY8yxgRuliGPFh7gYNma+UNr0knvfBRuQ/p1hiH8RSCy+hTFGfGjkKMYri17mVdEg6mmB6lyJEG Xw3hTuyVoKQSvnVbZt2sXdCLeRyqzsGlO+ZIVLHv7GMVlLhuRqtJq5GbwWz1u4OoDcw5jX5kkca 3Oo28hnVjvR8lFQ== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D X-Debian-User: leitao Since kho_add_subtree() now accepts arbitrary data blobs (not just FDTs), rename the parameter from 'fdt' to 'blob' to better reflect its purpose. Apply the same rename to kho_remove_subtree() for consistency. Also rename kho_debugfs_fdt_add() and kho_debugfs_fdt_remove() to kho_debugfs_blob_add() and kho_debugfs_blob_remove() respectively, with the same parameter rename from 'fdt' to 'blob'. Signed-off-by: Breno Leitao Acked-by: SeongJae Park Reviewed-by: Mike Rapoport (Microsoft) --- include/linux/kexec_handover.h | 8 ++++---- kernel/liveupdate/kexec_handover.c | 25 +++++++++++++------------ kernel/liveupdate/kexec_handover_debugfs.c | 25 +++++++++++++------------ kernel/liveupdate/kexec_handover_internal.h | 16 ++++++++-------- 4 files changed, 38 insertions(+), 36 deletions(-) diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h index abb1d324f42d0..0666cf298c7f4 100644 --- a/include/linux/kexec_handover.h +++ b/include/linux/kexec_handover.h @@ -32,8 +32,8 @@ void kho_restore_free(void *mem); struct folio *kho_restore_folio(phys_addr_t phys); struct page *kho_restore_pages(phys_addr_t phys, unsigned long nr_pages); void *kho_restore_vmalloc(const struct kho_vmalloc *preservation); -int kho_add_subtree(const char *name, void *fdt, size_t size); -void kho_remove_subtree(void *fdt); +int kho_add_subtree(const char *name, void *blob, size_t size); +void kho_remove_subtree(void *blob); int kho_retrieve_subtree(const char *name, phys_addr_t *phys); =20 void kho_memory_init(void); @@ -97,12 +97,12 @@ static inline void *kho_restore_vmalloc(const struct kh= o_vmalloc *preservation) return NULL; } =20 -static inline int kho_add_subtree(const char *name, void *fdt, size_t size) +static inline int kho_add_subtree(const char *name, void *blob, size_t siz= e) { return -EOPNOTSUPP; } =20 -static inline void kho_remove_subtree(void *fdt) { } +static inline void kho_remove_subtree(void *blob) { } =20 static inline int kho_retrieve_subtree(const char *name, phys_addr_t *phys) { diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_h= andover.c index 55bdc5d2d1929..ebaf3104c36ab 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -749,13 +749,13 @@ static void __init kho_reserve_scratch(void) } =20 /** - * kho_add_subtree - record the physical address of a sub FDT in KHO root = tree. + * kho_add_subtree - record the physical address of a sub blob in KHO root= tree. * @name: name of the sub tree. - * @fdt: the sub tree blob. + * @blob: the sub tree blob. * @size: size of the blob in bytes. * * Creates a new child node named @name in KHO root FDT and records - * the physical address of @fdt. The pages of @fdt must also be preserved + * the physical address of @blob. The pages of @blob must also be preserved * by KHO for the new kernel to retrieve it after kexec. * * A debugfs blob entry is also created at @@ -764,9 +764,9 @@ static void __init kho_reserve_scratch(void) * * Return: 0 on success, error code on failure */ -int kho_add_subtree(const char *name, void *fdt, size_t size) +int kho_add_subtree(const char *name, void *blob, size_t size) { - phys_addr_t phys =3D virt_to_phys(fdt); + phys_addr_t phys =3D virt_to_phys(blob); void *root_fdt =3D kho_out.fdt; int err =3D -ENOMEM; int off, fdt_err; @@ -789,7 +789,8 @@ int kho_add_subtree(const char *name, void *fdt, size_t= size) if (err < 0) goto out_pack; =20 - WARN_ON_ONCE(kho_debugfs_fdt_add(&kho_out.dbg, name, fdt, size, false)); + WARN_ON_ONCE(kho_debugfs_blob_add(&kho_out.dbg, name, blob, + size, false)); =20 out_pack: fdt_pack(root_fdt); @@ -798,9 +799,9 @@ int kho_add_subtree(const char *name, void *fdt, size_t= size) } EXPORT_SYMBOL_GPL(kho_add_subtree); =20 -void kho_remove_subtree(void *fdt) +void kho_remove_subtree(void *blob) { - phys_addr_t target_phys =3D virt_to_phys(fdt); + phys_addr_t target_phys =3D virt_to_phys(blob); void *root_fdt =3D kho_out.fdt; int off; int err; @@ -822,7 +823,7 @@ void kho_remove_subtree(void *fdt) =20 if ((phys_addr_t)*val =3D=3D target_phys) { fdt_del_node(root_fdt, off); - kho_debugfs_fdt_remove(&kho_out.dbg, fdt); + kho_debugfs_blob_remove(&kho_out.dbg, blob); break; } } @@ -1452,9 +1453,9 @@ static __init int kho_init(void) return 0; } =20 - WARN_ON_ONCE(kho_debugfs_fdt_add(&kho_out.dbg, "fdt", - kho_out.fdt, - fdt_totalsize(kho_out.fdt), true)); + WARN_ON_ONCE(kho_debugfs_blob_add(&kho_out.dbg, "fdt", + kho_out.fdt, + fdt_totalsize(kho_out.fdt), true)); =20 return 0; =20 diff --git a/kernel/liveupdate/kexec_handover_debugfs.c b/kernel/liveupdate= /kexec_handover_debugfs.c index b5a1e09ca8f14..7a100f2bf3947 100644 --- a/kernel/liveupdate/kexec_handover_debugfs.c +++ b/kernel/liveupdate/kexec_handover_debugfs.c @@ -23,8 +23,9 @@ struct fdt_debugfs { struct dentry *file; }; =20 -static int __kho_debugfs_fdt_add(struct list_head *list, struct dentry *di= r, - const char *name, const void *fdt, size_t size) +static int __kho_debugfs_blob_add(struct list_head *list, struct dentry *d= ir, + const char *name, const void *blob, + size_t size) { struct fdt_debugfs *f; struct dentry *file; @@ -33,7 +34,7 @@ static int __kho_debugfs_fdt_add(struct list_head *list, = struct dentry *dir, if (!f) return -ENOMEM; =20 - f->wrapper.data =3D (void *)fdt; + f->wrapper.data =3D (void *)blob; f->wrapper.size =3D size; =20 file =3D debugfs_create_blob(name, 0400, dir, &f->wrapper); @@ -48,8 +49,8 @@ static int __kho_debugfs_fdt_add(struct list_head *list, = struct dentry *dir, return 0; } =20 -int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name, - const void *fdt, size_t size, bool root) +int kho_debugfs_blob_add(struct kho_debugfs *dbg, const char *name, + const void *blob, size_t size, bool root) { struct dentry *dir; =20 @@ -58,15 +59,15 @@ int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const = char *name, else dir =3D dbg->sub_fdt_dir; =20 - return __kho_debugfs_fdt_add(&dbg->fdt_list, dir, name, fdt, size); + return __kho_debugfs_blob_add(&dbg->fdt_list, dir, name, blob, size); } =20 -void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, void *fdt) +void kho_debugfs_blob_remove(struct kho_debugfs *dbg, void *blob) { struct fdt_debugfs *ff; =20 list_for_each_entry(ff, &dbg->fdt_list, list) { - if (ff->wrapper.data =3D=3D fdt) { + if (ff->wrapper.data =3D=3D blob) { debugfs_remove(ff->file); list_del(&ff->list); kfree(ff); @@ -112,8 +113,8 @@ __init void kho_in_debugfs_init(struct kho_debugfs *dbg= , const void *fdt) goto err_rmdir; } =20 - err =3D __kho_debugfs_fdt_add(&dbg->fdt_list, dir, "fdt", fdt, - fdt_totalsize(fdt)); + err =3D __kho_debugfs_blob_add(&dbg->fdt_list, dir, "fdt", fdt, + fdt_totalsize(fdt)); if (err) goto err_rmdir; =20 @@ -132,8 +133,8 @@ __init void kho_in_debugfs_init(struct kho_debugfs *dbg= , const void *fdt) continue; } sub_fdt =3D phys_to_virt(*fdt_phys); - err =3D __kho_debugfs_fdt_add(&dbg->fdt_list, sub_fdt_dir, name, - sub_fdt, fdt_totalsize(sub_fdt)); + err =3D __kho_debugfs_blob_add(&dbg->fdt_list, sub_fdt_dir, name, + sub_fdt, fdt_totalsize(sub_fdt)); if (err) { pr_warn("failed to add fdt %s to debugfs: %pe\n", name, ERR_PTR(err)); diff --git a/kernel/liveupdate/kexec_handover_internal.h b/kernel/liveupdat= e/kexec_handover_internal.h index 2a28cb8db9b0a..0399ff1077750 100644 --- a/kernel/liveupdate/kexec_handover_internal.h +++ b/kernel/liveupdate/kexec_handover_internal.h @@ -26,19 +26,19 @@ extern unsigned int kho_scratch_cnt; int kho_debugfs_init(void); void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt); int kho_out_debugfs_init(struct kho_debugfs *dbg); -int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name, - const void *fdt, size_t size, bool root); -void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, void *fdt); +int kho_debugfs_blob_add(struct kho_debugfs *dbg, const char *name, + const void *blob, size_t size, bool root); +void kho_debugfs_blob_remove(struct kho_debugfs *dbg, void *blob); #else static inline int kho_debugfs_init(void) { return 0; } static inline void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt) { } static inline int kho_out_debugfs_init(struct kho_debugfs *dbg) { return 0= ; } -static inline int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char = *name, - const void *fdt, size_t size, - bool root) { return 0; } -static inline void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, - void *fdt) { } +static inline int kho_debugfs_blob_add(struct kho_debugfs *dbg, + const char *name, const void *blob, + size_t size, bool root) { return 0; } +static inline void kho_debugfs_blob_remove(struct kho_debugfs *dbg, + void *blob) { } #endif /* CONFIG_KEXEC_HANDOVER_DEBUGFS */ =20 #ifdef CONFIG_KEXEC_HANDOVER_DEBUG --=20 2.47.3 From nobody Thu Apr 9 18:39:41 2026 Received: from stravinsky.debian.org (stravinsky.debian.org [82.195.75.108]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C221D2609C5 for ; Fri, 6 Mar 2026 12:39:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=82.195.75.108 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800796; cv=none; b=XmzBsMshYBu8ePWyKTtLukXrUqlP5Hpq8gsswvPYUvjnYlttbupGvuLidE4cBNICU+DP9AZZbGDeAyTlJdaB0Ghb7KBvJUGoqhQVSTwcZlEMwmK2PAK9i1ufum0/965CHlKRnprM4CARoOSUFflo5J0SvN+zG0Fz+yBTDCQJdhU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800796; c=relaxed/simple; bh=SCRWzBzn9iJWzcyHMXkCR/smhQiBHZEHRDsJ6N05VTs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tZOJBT9JOsK0kj47TrfNYOqm5DS2kJpDtD/jrbh51v4Si0GW7mPOm8ZFkvKV5khLqc3KlQerQ58PIuX5oIZn6j2DBt6qHL/xkPqTsug+akfHSZDZ9n2eaQnu9euR0BERHEL42LlDSmN/UAruNAcch4IG8SJaxh64X5r9khUA7ZQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org; spf=none smtp.mailfrom=debian.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b=otTFmNzP; arc=none smtp.client-ip=82.195.75.108 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=debian.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b="otTFmNzP" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debian.org; s=smtpauto.stravinsky; h=X-Debian-User:Cc:To:In-Reply-To:References: Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description; bh=BhE/kAyP2PMNYjVkf7VWvL5e+VPagJ0YxqGnWHCRq+U=; b=otTFmNzPd7YM26o9dFWndy2jPm syzmZNvKrdueC/JBHgsO2f3v9JoR8xugHxv5fEx3H8BAs/CU53elqAj9DQ5QAmjct+F8jOvh+MqdC rHZrMxpF2Q8tPyABTCTv/CukKCTnaRsKsMFsZXKgwbYtaNvmLMyUaUeIhr5Bulg7NkXqZTvFx7Aih QAFmWemNks0GmVla99JsL7VtKNlV0rW3rOTN0ZwgRIRzIFZqTpydnNF39B/aJNsezRwUxKapu+Iz1 36PibsBkOI/MBnu35jNALK4kKE6UsDxvCoROvPP0plrVykCpvZp8htU0OCY5na58XLNF2Z+dNpim9 wNsmNQ2w==; Received: from authenticated user by stravinsky.debian.org with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94.2) (envelope-from ) id 1vyUTA-00HVR9-1n; Fri, 06 Mar 2026 12:39:52 +0000 From: Breno Leitao Date: Fri, 06 Mar 2026 04:39:22 -0800 Subject: [PATCH v7 3/6] kho: persist blob size in KHO FDT Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260306-kho-v7-3-404d14c188bb@debian.org> References: <20260306-kho-v7-0-404d14c188bb@debian.org> In-Reply-To: <20260306-kho-v7-0-404d14c188bb@debian.org> To: Alexander Graf , Mike Rapoport , Pasha Tatashin , Pratyush Yadav Cc: linux-kernel@vger.kernel.org, kexec@lists.infradead.org, linux-mm@kvack.org, usamaarif642@gmail.com, Breno Leitao , SeongJae Park , kernel-team@meta.com X-Mailer: b4 0.15-dev-363b9 X-Developer-Signature: v=1; a=openpgp-sha256; l=7293; i=leitao@debian.org; h=from:subject:message-id; bh=SCRWzBzn9iJWzcyHMXkCR/smhQiBHZEHRDsJ6N05VTs=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBpqssGJ2ZzRQn7CHLdGRWOkEqcEMCc2WgNTIUfO rcE++1Jb5eJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCaarLBgAKCRA1o5Of/Hh3 beRdD/4ndO7EJhwQP5T/1HuZorU8UvNdcgrME6SbRYx078Rnqo/eaP/0Q4iaB4VXYAVfzdgXTFk vrOIwL7SsuYiIEfhiIlbIbH7pZ9Wl9WW7n9f+cptxzHEsJlIazkpDo/NdM0XddA7s75ftK4bVoF yNTStYv99M2Ozt3ZDKJW4m5yLYSh6GNBEolTu9AaECy8Gwl6uE7NBtPRra2AAdZD60/rcRxfQRT Tz5uj7D5wXYKYxSAN3iREssM+claNxo+RoAGMNwHDZ25tCDNmp2EvyMnsP/PzxRVjn4a8Ufxcc1 T8zTh6xWZkYJgln/twWzdzWWv5KOTk2cyj1ygeLjGJxO7abylNz8Wba9RSfgqRG912/Wh4ABfUp iIBZ3p8IRgj7Kpx5TcWCkHr6NuparF+KMRrZfo9w3TW6G6dTJrIeVbVMSYU1WeWlrczPdfkCDer VUzwZK4ijCoNumo6ubxZI+gEvA9yeMyrhRaNqebY7JlrgaWp9HgSoBXHB3ejmyP9qBN812Ufdyl iABe2Ew0vMudWk52iYlQymdFtxaeJkS3rG443NJXoAvOrYo06pNK72RRLMI6vvxEt4guIzPePIl Q4sO2SbPobAUC44aEmOYZ3tI+DzvjgIaSoMP6EkyO7JOhgoaSWPcrkoo2NTV4DbLObZoIbXl7qJ +BT22k9C4zgnpiw== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D X-Debian-User: leitao kho_add_subtree() accepts a size parameter but only forwards it to debugfs. The size is not persisted in the KHO FDT, so it is lost across kexec. This makes it impossible for the incoming kernel to determine the blob size without understanding the blob format. Store the blob size as a "blob-size" property in the KHO FDT alongside the "preserved-data" physical address. This allows the receiving kernel to recover the size for any blob regardless of format. Also extend kho_retrieve_subtree() with an optional size output parameter so callers can learn the blob size without needing to understand the blob format. Update all callers to pass NULL for the new parameter. Signed-off-by: Breno Leitao Acked-by: SeongJae Park --- include/linux/kexec_handover.h | 5 +++-- include/linux/kho/abi/kexec_handover.h | 12 ++++++++++++ kernel/liveupdate/kexec_handover.c | 28 ++++++++++++++++++++++------ kernel/liveupdate/luo_core.c | 2 +- lib/test_kho.c | 2 +- mm/memblock.c | 2 +- 6 files changed, 40 insertions(+), 11 deletions(-) diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h index 0666cf298c7f4..8968c56d2d73e 100644 --- a/include/linux/kexec_handover.h +++ b/include/linux/kexec_handover.h @@ -34,7 +34,7 @@ struct page *kho_restore_pages(phys_addr_t phys, unsigned= long nr_pages); void *kho_restore_vmalloc(const struct kho_vmalloc *preservation); int kho_add_subtree(const char *name, void *blob, size_t size); void kho_remove_subtree(void *blob); -int kho_retrieve_subtree(const char *name, phys_addr_t *phys); +int kho_retrieve_subtree(const char *name, phys_addr_t *phys, size_t *size= ); =20 void kho_memory_init(void); =20 @@ -104,7 +104,8 @@ static inline int kho_add_subtree(const char *name, voi= d *blob, size_t size) =20 static inline void kho_remove_subtree(void *blob) { } =20 -static inline int kho_retrieve_subtree(const char *name, phys_addr_t *phys) +static inline int kho_retrieve_subtree(const char *name, phys_addr_t *phys, + size_t *size) { return -EOPNOTSUPP; } diff --git a/include/linux/kho/abi/kexec_handover.h b/include/linux/kho/abi= /kexec_handover.h index 6b7d8ef550f98..15bf7a5be8cf1 100644 --- a/include/linux/kho/abi/kexec_handover.h +++ b/include/linux/kho/abi/kexec_handover.h @@ -47,14 +47,17 @@ * * { * preserved-data =3D <0x...>; + * blob-size =3D <0x...>; * }; * * { * preserved-data =3D <0x...>; + * blob-size =3D <0x...>; * }; * ... ... * { * preserved-data =3D <0x...>; + * blob-size =3D <0x...>; * }; * }; * @@ -78,6 +81,12 @@ * * Physical address pointing to a subnode data blob that is also * being preserved. + * + * - blob-size: u64 + * + * Size in bytes of the preserved data blob. This is needed because + * blobs may use arbitrary formats (not just FDT), so the size + * cannot be determined from the blob content alone. */ =20 /* The compatible string for the KHO FDT root node. */ @@ -89,6 +98,9 @@ /* The FDT property for preserved data blobs. */ #define KHO_FDT_SUB_TREE_PROP_NAME "preserved-data" =20 +/* The FDT property for the size of preserved data blobs. */ +#define KHO_FDT_SUB_TREE_SIZE_PROP_NAME "blob-size" + /** * DOC: Kexec Handover ABI for vmalloc Preservation * diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_h= andover.c index ebaf3104c36ab..e52615fdd5e4b 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -768,6 +768,7 @@ int kho_add_subtree(const char *name, void *blob, size_= t size) { phys_addr_t phys =3D virt_to_phys(blob); void *root_fdt =3D kho_out.fdt; + u64 size_u64 =3D size; int err =3D -ENOMEM; int off, fdt_err; =20 @@ -789,6 +790,11 @@ int kho_add_subtree(const char *name, void *blob, size= _t size) if (err < 0) goto out_pack; =20 + err =3D fdt_setprop(root_fdt, off, KHO_FDT_SUB_TREE_SIZE_PROP_NAME, + &size_u64, sizeof(size_u64)); + if (err < 0) + goto out_pack; + WARN_ON_ONCE(kho_debugfs_blob_add(&kho_out.dbg, name, blob, size, false)); =20 @@ -1311,16 +1317,17 @@ bool is_kho_boot(void) EXPORT_SYMBOL_GPL(is_kho_boot); =20 /** - * kho_retrieve_subtree - retrieve a preserved sub FDT by its name. - * @name: the name of the sub FDT passed to kho_add_subtree(). - * @phys: if found, the physical address of the sub FDT is stored in @phys. + * kho_retrieve_subtree - retrieve a preserved sub blob by its name. + * @name: the name of the sub blob passed to kho_add_subtree(). + * @phys: if found, the physical address of the sub blob is stored in @phy= s. + * @size: if not NULL and found, the size of the sub blob is stored in @si= ze. * - * Retrieve a preserved sub FDT named @name and store its physical - * address in @phys. + * Retrieve a preserved sub blob named @name and store its physical + * address in @phys and optionally its size in @size. * * Return: 0 on success, error code on failure */ -int kho_retrieve_subtree(const char *name, phys_addr_t *phys) +int kho_retrieve_subtree(const char *name, phys_addr_t *phys, size_t *size) { const void *fdt =3D kho_get_fdt(); const u64 *val; @@ -1342,6 +1349,15 @@ int kho_retrieve_subtree(const char *name, phys_addr= _t *phys) =20 *phys =3D (phys_addr_t)*val; =20 + if (size) { + val =3D fdt_getprop(fdt, offset, KHO_FDT_SUB_TREE_SIZE_PROP_NAME, + &len); + if (val && len =3D=3D sizeof(*val)) + *size =3D (size_t)*val; + else + *size =3D 0; + } + return 0; } EXPORT_SYMBOL_GPL(kho_retrieve_subtree); diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c index 04d06a0906c0e..48b25c9abeda3 100644 --- a/kernel/liveupdate/luo_core.c +++ b/kernel/liveupdate/luo_core.c @@ -88,7 +88,7 @@ static int __init luo_early_startup(void) } =20 /* Retrieve LUO subtree, and verify its format. */ - err =3D kho_retrieve_subtree(LUO_FDT_KHO_ENTRY_NAME, &fdt_phys); + err =3D kho_retrieve_subtree(LUO_FDT_KHO_ENTRY_NAME, &fdt_phys, NULL); if (err) { if (err !=3D -ENOENT) { pr_err("failed to retrieve FDT '%s' from KHO: %pe\n", diff --git a/lib/test_kho.c b/lib/test_kho.c index 2631824373152..aa6a0956bb8b7 100644 --- a/lib/test_kho.c +++ b/lib/test_kho.c @@ -319,7 +319,7 @@ static int __init kho_test_init(void) if (!kho_is_enabled()) return 0; =20 - err =3D kho_retrieve_subtree(KHO_TEST_FDT, &fdt_phys); + err =3D kho_retrieve_subtree(KHO_TEST_FDT, &fdt_phys, NULL); if (!err) { err =3D kho_test_restore(fdt_phys); if (err) diff --git a/mm/memblock.c b/mm/memblock.c index 29e12ea2a854c..4f4bf1a9d7900 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -2533,7 +2533,7 @@ static void *__init reserve_mem_kho_retrieve_fdt(void) if (fdt) return fdt; =20 - err =3D kho_retrieve_subtree(MEMBLOCK_KHO_FDT, &fdt_phys); + err =3D kho_retrieve_subtree(MEMBLOCK_KHO_FDT, &fdt_phys, NULL); if (err) { if (err !=3D -ENOENT) pr_warn("failed to retrieve FDT '%s' from KHO: %d\n", --=20 2.47.3 From nobody Thu Apr 9 18:39:41 2026 Received: from stravinsky.debian.org (stravinsky.debian.org [82.195.75.108]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1A49B281369 for ; Fri, 6 Mar 2026 12:39:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=82.195.75.108 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800800; cv=none; b=eMHMI/IKxAup+rfDZIwjaIe6J98ecLVz0DjEhqahp7yhw7cAAXQnnp0JhKBNu02VxDItcfPR4ZboPdf6DnycPeGVQsunvcL11mWwLb/JoQHEVG25LO2tTG7Og1KE7/gyWv9R5wg23JAyo6NGnTXYoFTBNiMXCF0xU1dvu201P20= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800800; c=relaxed/simple; bh=4JJwA4BhcQH0vypVqf0AFPnXED7DjJgKgSgxLA0Nv5k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=onTVER/ohBwjskGXDtcfxM8dSJCMmGm6oQqfIizT7+FLDITOYkWk+fKGShfhk0eI10ruGPAHhUTC74frI++RMeGyTZon9gIEDh0hnPKUOGA1EzILPT0MRLN1fl9/OWkHksvWRgEDCNpOEiPYwGWVUhv4o7Qu/FrVZY37+BTCgb8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org; spf=none smtp.mailfrom=debian.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b=UXPEiSm3; arc=none smtp.client-ip=82.195.75.108 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=debian.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b="UXPEiSm3" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debian.org; s=smtpauto.stravinsky; h=X-Debian-User:Cc:To:In-Reply-To:References: Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description; bh=r3UzGEG+EMO5hQVHIScmxOOOv+tHtfPy3q+mI1q7KDo=; b=UXPEiSm3MiUPouY7UBy0zb/KBs GMdw4BdFGlt2480xHC/IIKzr+vh1Ae4UZPWWQJXZb0h0KlJEsxl3U+9Ud5p3olZKrJZU/w7cm1qDJ g52RpheYz9KCzPP4JIkmhIOcyuBrgKl0HHQD04+OOQImCk8mh5rGpO4uUvfvnWSj0mIyK66UjxTjG bcFMBzDBMWkRLmLRlLQvPOz2mC2u9ZPQQ4ajYGe51Q+PHFwU2bTPnSXzU3z3L5KaFYGBy+AfccoJr WjW7OgUatQCJBnAiipLjrDYgB1KkIy8Bs7nvTs9EYpem76YFB5ji5lgaw1JAHtAzGMxt5/b5Rjiu8 xIuf8xxQ==; Received: from authenticated user by stravinsky.debian.org with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94.2) (envelope-from ) id 1vyUTE-00HVRP-35; Fri, 06 Mar 2026 12:39:56 +0000 From: Breno Leitao Date: Fri, 06 Mar 2026 04:39:23 -0800 Subject: [PATCH v7 4/6] kho: fix kho_in_debugfs_init() to handle non-FDT blobs Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260306-kho-v7-4-404d14c188bb@debian.org> References: <20260306-kho-v7-0-404d14c188bb@debian.org> In-Reply-To: <20260306-kho-v7-0-404d14c188bb@debian.org> To: Alexander Graf , Mike Rapoport , Pasha Tatashin , Pratyush Yadav Cc: linux-kernel@vger.kernel.org, kexec@lists.infradead.org, linux-mm@kvack.org, usamaarif642@gmail.com, Breno Leitao , SeongJae Park , kernel-team@meta.com X-Mailer: b4 0.15-dev-363b9 X-Developer-Signature: v=1; a=openpgp-sha256; l=2820; i=leitao@debian.org; h=from:subject:message-id; bh=4JJwA4BhcQH0vypVqf0AFPnXED7DjJgKgSgxLA0Nv5k=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBpqssGmTaJ8Ll+XqkUU13uPDLWy3W9GTdb/bEvL kPgndgfIICJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCaarLBgAKCRA1o5Of/Hh3 bbqFD/4rbEXrPDtNBWZD7+8GEQ5PvrWyCEoLl4we3SLx+m0aZfb7JTLB1XE7e9YH4zNT0Kfi7MB 6gm3bkNjfQ0v5moSTjVXPdOh6A2SOi2HN8Hs4tRXI1UUL90QSbANNQ2v3R/ZgMi94mGToy6bA2M 4jmFTiUwv/pxTYNL4x8BTNB8CI1UOF1qVIO6iQ86ngXmu4pOMunCf5q9yv5KO/a8m6N509BNtbn SdbzysegryN2W+0ztpNIx80v7PGY2xNUKZ0HHjWrfvZd8RbBBa/cYu/WOHtl3jKCCoJzRq4HV4E v3OOcafotjyxzzK91DNwzKZTLZbPg4dmLIGgws5Yp/0hkMBFT1cLoNJyn/a915HyMBWDVaC67TT Za7G1HQNfIjYvWy2CYky9ylPrGNtrtpELbtzuyOFIDJ6skUV/CybdZpHOHu3xPGFrrCmpdxQ0C7 z3P1+pKYNsuite31v3E9H3IcN0gwG+XWeq5Xe+PofXTVJRei5dGkgnXhoNcQk6BOd87RPW78KCG FAB0uY0Ev7+G5dvcIeS/OESx5xfs0Yy4d5EFTAjJTtkGMVZSfkn9OcGd3y+YeSV7JV2g7E/5ZHE fBkUcLL7fN5hUNg7cMVY2hsOhKSfq4M+vnPe62VdYNXuhlrNFb9Yd2qJwnTPY/PiUykBuEBYaRT 6HMrPdq0cPVRvow== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D X-Debian-User: leitao kho_in_debugfs_init() has two problems when displaying incoming sub-blobs in debugfs: 1. It uses the hardcoded property name "fdt" instead of KHO_FDT_SUB_TREE_PROP_NAME ("preserved-data"), so it never finds subtrees stored by the current kho_add_subtree(). 2. It calls fdt_totalsize() to determine blob sizes, which assumes all blobs are FDTs. This breaks for non-FDT blobs like struct kho_kexec_metadata. Fix both issues by using KHO_FDT_SUB_TREE_PROP_NAME to find subtrees and reading the "blob-size" property from the FDT (persisted by kho_add_subtree()) instead of calling fdt_totalsize(). Signed-off-by: Breno Leitao Acked-by: SeongJae Park --- kernel/liveupdate/kexec_handover_debugfs.c | 38 ++++++++++++++++++++------= ---- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/kernel/liveupdate/kexec_handover_debugfs.c b/kernel/liveupdate= /kexec_handover_debugfs.c index 7a100f2bf3947..fc2baa8b104fd 100644 --- a/kernel/liveupdate/kexec_handover_debugfs.c +++ b/kernel/liveupdate/kexec_handover_debugfs.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "kexec_handover_internal.h" =20 static struct dentry *debugfs_root; @@ -121,23 +122,36 @@ __init void kho_in_debugfs_init(struct kho_debugfs *d= bg, const void *fdt) fdt_for_each_subnode(child, fdt, 0) { int len =3D 0; const char *name =3D fdt_get_name(fdt, child, NULL); - const u64 *fdt_phys; - void *sub_fdt; - - fdt_phys =3D fdt_getprop(fdt, child, "fdt", &len); - if (!fdt_phys) + const u64 *blob_phys; + const u64 *blob_size; + void *blob; + size_t size; + + blob_phys =3D fdt_getprop(fdt, child, + KHO_FDT_SUB_TREE_PROP_NAME, &len); + if (!blob_phys) continue; - if (len !=3D sizeof(*fdt_phys)) { - pr_warn("node %s prop fdt has invalid length: %d\n", - name, len); + if (len !=3D sizeof(*blob_phys)) { + pr_warn("node %s prop %s has invalid length: %d\n", + name, KHO_FDT_SUB_TREE_PROP_NAME, len); continue; } - sub_fdt =3D phys_to_virt(*fdt_phys); + + blob_size =3D fdt_getprop(fdt, child, + KHO_FDT_SUB_TREE_SIZE_PROP_NAME, &len); + if (!blob_size || len !=3D sizeof(*blob_size)) { + pr_warn("node %s missing or invalid %s property\n", + name, KHO_FDT_SUB_TREE_SIZE_PROP_NAME); + continue; + } + size =3D (size_t)*blob_size; + + blob =3D phys_to_virt(*blob_phys); err =3D __kho_debugfs_blob_add(&dbg->fdt_list, sub_fdt_dir, name, - sub_fdt, fdt_totalsize(sub_fdt)); + blob, size); if (err) { - pr_warn("failed to add fdt %s to debugfs: %pe\n", name, - ERR_PTR(err)); + pr_warn("failed to add blob %s to debugfs: %pe\n", + name, ERR_PTR(err)); continue; } } --=20 2.47.3 From nobody Thu Apr 9 18:39:41 2026 Received: from stravinsky.debian.org (stravinsky.debian.org [82.195.75.108]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E2195284B2F for ; Fri, 6 Mar 2026 12:40:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=82.195.75.108 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800804; cv=none; b=gen4Daa0DhHG2KOn9G1ns0GSt60SrZBEEJEq+9Cz07TvkDkKo9rfAf2SIj51o6yeuo8m04gtg+A5NpM69Gr0LnbCgymad1J30JnoxdoFk/Lx0umL9tz5tSITC4t7tiMiIFd8Hd6pzeGikzUmOZLsCvCSEJLeWGHeQgUfJDshSbo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800804; c=relaxed/simple; bh=K3p6Gosnlu/2JipzJi3Hi1uRbDEte28JJd8WF+OBUak=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HJ+AKUO7//394R7d2YspQVqdlhGKfwXptokkunWs1saqMhwhsPXA9qsBQGxDJksd44kwWGMA5Q/N5E6W33SQqB/EDWdjk0gUZd5UdhJ1g5CDsmYg56eF2cBxfQIIwJdAmRPX7V3UuneejUplLsjjLxG5XuxhRZq6kTx7aQWZsj0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org; spf=none smtp.mailfrom=debian.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b=pie+yQXJ; arc=none smtp.client-ip=82.195.75.108 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=debian.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b="pie+yQXJ" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debian.org; s=smtpauto.stravinsky; h=X-Debian-User:Cc:To:In-Reply-To:References: Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description; bh=GwwNaqrGZTaZUSJESBV+OjOZVYMTyVZCT2p3mgx1kQ4=; b=pie+yQXJ4i7JiF+mtw4xNTlwLv tPfZLfMy1F2bjIlAbovXJawutSkZ5394R6mY4shJ5GIVMSdDGsirIVxQyqIvRD8kSGOq3THEsa0TN eud8Dk2TU2nxjLZEE593SNgP+PcwVjXteepLF3RKMdwJryb66EBb3qZXt0FDGTdCauIpMECeRbGZ9 7mcJq4G37cG5/aZZWX065RAlxzcgQ6CMjESHhQs3d8xa+tYjpdEuc2Dx1sC/gXZvoKbs9kKt5n1WQ tyZtaoX6kYZBEjy4pwAcLDWwXYsYaV7xqcE3wFOHLxOq3BYiF7r6X5sAZalR2qC4dX+jn4oQtrrWc 2xBC30MA==; Received: from authenticated user by stravinsky.debian.org with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94.2) (envelope-from ) id 1vyUTI-00HVRa-5v; Fri, 06 Mar 2026 12:40:00 +0000 From: Breno Leitao Date: Fri, 06 Mar 2026 04:39:24 -0800 Subject: [PATCH v7 5/6] kho: kexec-metadata: track previous kernel chain Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260306-kho-v7-5-404d14c188bb@debian.org> References: <20260306-kho-v7-0-404d14c188bb@debian.org> In-Reply-To: <20260306-kho-v7-0-404d14c188bb@debian.org> To: Alexander Graf , Mike Rapoport , Pasha Tatashin , Pratyush Yadav Cc: linux-kernel@vger.kernel.org, kexec@lists.infradead.org, linux-mm@kvack.org, usamaarif642@gmail.com, Breno Leitao , SeongJae Park , kernel-team@meta.com X-Mailer: b4 0.15-dev-363b9 X-Developer-Signature: v=1; a=openpgp-sha256; l=6982; i=leitao@debian.org; h=from:subject:message-id; bh=K3p6Gosnlu/2JipzJi3Hi1uRbDEte28JJd8WF+OBUak=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBpqssG1ehn7jF8aO5NgvyxPuT/6Fd8GCYAWYTvy LxwPvxp40yJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCaarLBgAKCRA1o5Of/Hh3 bdfXD/0cTpXmbLuBH+gMxCkZYZ5dTEZaefYgCFtsxgb3WxPQ3D4bKkMBGcwGIzk+fR0M22BKEx5 B5DK8nZvTY3igR4Op657Mzpk8IOnYGYrHKQ8EtYCrF24nCqZUQ4IHSyrKvtb1Q28vHb6HRAU+S3 IVFSicl0eeUUIE4oOP1nKH8Nf4ui7lbAdCbyhv+xf6I2z3PxNUKI2h9ZF1HwjgzbdkBZd5m3Hqv tq8ZHwyaFxf3zS5jx2qpqyZNBegriBgrbRUrHpMph71Cit4XkYLuVJVyMuABNj/m70IOudl4uSG InoJB1+uRlS7XzQB80q57OiGLhBnSe89C6bcVRoT5legkE0ZMGXC2kb9Qkf7tWNjcZa9aQ5Y3F3 OrvRZHt5ZmiCe+1bH2Gxqo8IkXLrh7hq7IQvHSHYINEg8KMu+WU/iMHluPPaksrGmcyCZ30AzvS BmIh080u6zizno8UWRWTWsegRM93513l1zeN86GoVJkDa+tod6Y/HnjdiMPdbwH/gfNUBN96DmK Jri3l27lN7fooiKLQPehU2/f4LoGfXSC7eT+ENDhzR33nRLCzLEd5aKZ9p5gF8IKjEXyyrdBNba LOfksk6LtTab+X3FhH5E5P+NQzn4lS8uU+wSJHgfvKE9xPmCIMCjulpiKzPCbpgR2tjMZ3Wz/PJ INJx4Kli1bx1+LQ== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D X-Debian-User: leitao Use Kexec Handover (KHO) to pass the previous kernel's version string and the number of kexec reboots since the last cold boot to the next kernel, and print it at boot time. Example output: [ 0.000000] KHO: exec from: 6.19.0-rc4-next-20260107 (count 1) Motivation =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Bugs that only reproduce when kexecing from specific kernel versions are difficult to diagnose. These issues occur when a buggy kernel kexecs into a new kernel, with the bug manifesting only in the second kernel. Recent examples include the following commits: * eb2266312507 ("x86/boot: Fix page table access in 5-level to 4-level pag= ing transition") * 77d48d39e991 ("efistub/tpm: Use ACPI reclaim memory for event log to avo= id corruption") * 64b45dd46e15 ("x86/efi: skip memattr table on kexec boot") As kexec-based reboots become more common, these version-dependent bugs are appearing more frequently. At scale, correlating crashes to the previous kernel version is challenging, especially when issues only occur in specific transition scenarios. Implementation =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D The kexec metadata is stored as a plain C struct (struct kho_kexec_metadata) rather than FDT format, for simplicity and direct field access. It is registered via kho_add_subtree() as a separate subtree, keeping it independent from the core KHO ABI. This design choice: - Keeps the core KHO ABI minimal and stable - Allows the metadata format to evolve independently - Avoids requiring version bumps for all KHO consumers (LUO, etc.) when the metadata format changes The struct kho_metadata contains two fields: - previous_release: The kernel version that initiated the kexec - kexec_count: Number of kexec boots since last cold boot On cold boot, kexec_count starts at 0 and increments with each kexec. The count helps identify issues that only manifest after multiple consecutive kexec reboots. Acked-by: SeongJae Park Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: Breno Leitao --- include/linux/kho/abi/kexec_handover.h | 31 ++++++++++++++ kernel/liveupdate/kexec_handover.c | 75 ++++++++++++++++++++++++++++++= ++++ 2 files changed, 106 insertions(+) diff --git a/include/linux/kho/abi/kexec_handover.h b/include/linux/kho/abi= /kexec_handover.h index 15bf7a5be8cf1..16212f3659198 100644 --- a/include/linux/kho/abi/kexec_handover.h +++ b/include/linux/kho/abi/kexec_handover.h @@ -14,6 +14,7 @@ #include #include #include +#include =20 #include =20 @@ -101,6 +102,36 @@ /* The FDT property for the size of preserved data blobs. */ #define KHO_FDT_SUB_TREE_SIZE_PROP_NAME "blob-size" =20 +/** + * DOC: Kexec Metadata ABI + * + * The "kexec-metadata" subtree stores optional metadata about the kexec c= hain. + * It is registered via kho_add_subtree(), keeping it independent from the= core + * KHO ABI. This allows the metadata format to evolve without affecting ot= her + * KHO consumers. + * + * The metadata is stored as a plain C struct rather than FDT format for + * simplicity and direct field access. + */ + +/** + * struct kho_kexec_metadata - Kexec metadata passed between kernels + * @previous_release: Kernel version string that initiated the kexec + * @kexec_count: Number of kexec boots since last cold boot + * + * This structure is preserved across kexec and allows the new kernel to + * identify which kernel it was booted from and how many kexec reboots + * have occurred. + * + * __NEW_UTS_LEN is part of uABI, so it safe to use it in here. + */ +struct kho_kexec_metadata { + char previous_release[__NEW_UTS_LEN + 1]; + u32 kexec_count; +} __packed; + +#define KHO_METADATA_NODE_NAME "kexec-metadata" + /** * DOC: Kexec Handover ABI for vmalloc Preservation * diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_h= andover.c index e52615fdd5e4b..912199df3675f 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -1285,6 +1286,8 @@ EXPORT_SYMBOL_GPL(kho_restore_free); struct kho_in { phys_addr_t fdt_phys; phys_addr_t scratch_phys; + char previous_release[__NEW_UTS_LEN + 1]; + u32 kexec_count; struct kho_debugfs dbg; }; =20 @@ -1408,6 +1411,74 @@ static __init int kho_out_fdt_setup(void) return err; } =20 +static void __init kho_in_kexec_metadata(void) +{ + struct kho_kexec_metadata *metadata; + phys_addr_t metadata_phys; + int err; + + err =3D kho_retrieve_subtree(KHO_METADATA_NODE_NAME, &metadata_phys, + NULL); + if (err) + /* This is fine, previous kernel didn't export metadata */ + return; + metadata =3D phys_to_virt(metadata_phys); + + /* + * Copy data to the kernel structure that will persist during + * kernel lifetime. + */ + kho_in.kexec_count =3D metadata->kexec_count; + strscpy(kho_in.previous_release, metadata->previous_release, + sizeof(kho_in.previous_release)); + + pr_info("exec from: %s (count %u)\n", kho_in.previous_release, + kho_in.kexec_count); +} + +/* + * Create kexec metadata to pass kernel version and boot count to the + * next kernel. This keeps the core KHO ABI minimal and allows the + * metadata format to evolve independently. + */ +static __init int kho_out_kexec_metadata(void) +{ + struct kho_kexec_metadata *metadata; + int err; + + metadata =3D kho_alloc_preserve(sizeof(*metadata)); + if (IS_ERR(metadata)) + return PTR_ERR(metadata); + + strscpy(metadata->previous_release, init_uts_ns.name.release, + sizeof(metadata->previous_release)); + /* kho_in.kexec_count is set to 0 on cold boot */ + metadata->kexec_count =3D kho_in.kexec_count + 1; + + err =3D kho_add_subtree(KHO_METADATA_NODE_NAME, metadata, + sizeof(*metadata)); + if (err) + kho_unpreserve_free(metadata); + + return err; +} + +static int __init kho_kexec_metadata_init(const void *fdt) +{ + int err; + + if (fdt) + kho_in_kexec_metadata(); + + /* Populate kexec metadata for the possible next kexec */ + err =3D kho_out_kexec_metadata(); + if (err) + pr_warn("failed to initialize kexec-metadata subtree: %d\n", + err); + + return err; +} + static __init int kho_init(void) { struct kho_radix_tree *tree =3D &kho_out.radix_tree; @@ -1441,6 +1512,10 @@ static __init int kho_init(void) if (err) goto err_free_fdt; =20 + err =3D kho_kexec_metadata_init(fdt); + if (err) + goto err_free_fdt; + for (int i =3D 0; i < kho_scratch_cnt; i++) { unsigned long base_pfn =3D PHYS_PFN(kho_scratch[i].addr); unsigned long count =3D kho_scratch[i].size >> PAGE_SHIFT; --=20 2.47.3 From nobody Thu Apr 9 18:39:41 2026 Received: from stravinsky.debian.org (stravinsky.debian.org [82.195.75.108]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A06412765D7 for ; Fri, 6 Mar 2026 12:40:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=82.195.75.108 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800808; cv=none; b=prevKvaDAJPx6GHzz/X5ILHe0XrNy+7STT+PjH0K/QrYhOTvlZZt1fcTFFDhf0I+eFx94IHeux+/Y2MjM6HNr4KNSkyo9QmvHPKXTLmed+UugcWqH7u12uyIRdU2Dkt3B++0wIF0p1zZ9caSmldPQCqav0VVLPatXuV8oXoIPrI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772800808; c=relaxed/simple; bh=QTYE0HCCPpFCLiFL5V/nZqYT03OWnMpDhIbyr7syUIs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=m/nX3ZN4e/zDWe2Slj/b73DqxcS2N4JxFUtRyemzdD3JtoYAyoL7EBffXscQHfADkZNS4kCu/WtMV4hKn+7FMHDwmZ//rHwI7qa/Qs9bIPavujZSdhO8EI1DM0BGGU4nEY5pJpCKXryNIYI0Yr2c/MyOFiWx1WrS/3+HCT+3XB4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org; spf=none smtp.mailfrom=debian.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b=n3mdsYCp; arc=none smtp.client-ip=82.195.75.108 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=debian.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b="n3mdsYCp" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debian.org; s=smtpauto.stravinsky; h=X-Debian-User:Cc:To:In-Reply-To:References: Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description; bh=ov55JeCCcCTI9x6RF1+xOgMdlYSvCZuzinIPQ6ZR/W8=; b=n3mdsYCpgoWo4ZadI4IRQMe2s3 2igiPsHr8bu/s0uHunrTT4u0v2shTOqTNeX7FmzAUeEviKXBwzaRRXkBjScjnFw/gQd93Xm5J1ybI d5Q81YdkfiqgYdWDqW2dK+xwddNzEkoFxwlwgVbxZeYUsgZPJPdXwkS612XbG75kUC0WGGIlLwE+D A/pmENobybKc/tO68hBIjUuOlHPlgsSqbxdepPtw7f6JT8mqYKKfmPrRYlWuysrogb7DV6jdAJQEZ wHPrIZLLLqXYqZDxmzEzqll/Mj86ukQvvk7FtJ3rgNN0Ou3XqnRI64bpXTtnvm3d8VYXu7Akr8OCB 9p9ylgQw==; Received: from authenticated user by stravinsky.debian.org with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94.2) (envelope-from ) id 1vyUTM-00HVRn-C6; Fri, 06 Mar 2026 12:40:04 +0000 From: Breno Leitao Date: Fri, 06 Mar 2026 04:39:25 -0800 Subject: [PATCH v7 6/6] kho: document kexec-metadata tracking feature Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260306-kho-v7-6-404d14c188bb@debian.org> References: <20260306-kho-v7-0-404d14c188bb@debian.org> In-Reply-To: <20260306-kho-v7-0-404d14c188bb@debian.org> To: Alexander Graf , Mike Rapoport , Pasha Tatashin , Pratyush Yadav Cc: linux-kernel@vger.kernel.org, kexec@lists.infradead.org, linux-mm@kvack.org, usamaarif642@gmail.com, Breno Leitao , SeongJae Park , kernel-team@meta.com X-Mailer: b4 0.15-dev-363b9 X-Developer-Signature: v=1; a=openpgp-sha256; l=2486; i=leitao@debian.org; h=from:subject:message-id; bh=QTYE0HCCPpFCLiFL5V/nZqYT03OWnMpDhIbyr7syUIs=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBpqssGqwKfHdo2QxZJ6I25DRn3JnCg9iml8RDR5 KBHqXz3mHiJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCaarLBgAKCRA1o5Of/Hh3 bWTgD/4jWQiT2UnkeKb9NEgYI+ILjpkrxclkPGXdbg4z8XrpmcS7fzoREezM0yFZd9evwYRH+7T kbtvWRxfUeDI4XmFGQ2Ovrai/v50qE5nEHl7L/mfolZM1J+kktRv/zpGBICBb4lcJOYRtdKZhMi RDC30ctSlkl3OJLuIbhbNl3MxywiWvMHBXWPX4SAxKSIxkTQCZCOzITHKJltf9jZYZ++2X4+hDO x6NYMp0nswM4Oij3+hMgVjvVQ0nygvIPrl1j66yGA47gKa7kOhPigXcScQiEBwv5Y5kNCLztk+v Ex3OJd8XGNoFsqDvIKSIWNc2ssVgx/3wwRzLNuFYExoG+8//L9FmhaZJhxE0GOkh1ZvTsBnXpnQ 44IZ+nnukzcjF4qfZ/LL8aXmGVsj2eYrHLGP6STMYu7yFlU6Nnh5R7d/8yFzqv8fMAaW7Z1fGgv xLcqCQNcOeL7YbxGf0g/sxdWGWJzmeP+RaQR1bNmuNFuzeqYqEc/2+J8Hp9doEP0HqY8wddKpkF uoiwhKDNMyb8tVIIu7q9LXULlz5kiqGvnokn+XBwEad9oeEVabEL9wiLz5do1tyOiQUzFYslwnf CyU7UUMJDyC63h0gbp4sPRARzaQlJMWiBfY1rJyoDPYKI9co06Bk7X2/h0G8o2ArlY6zwbuFt+x X+VwYWAubtbstLA== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D X-Debian-User: leitao Add documentation for the kexec-metadata feature that tracks the previous kernel version and kexec boot count across kexec reboots. This helps diagnose bugs that only reproduce when kexecing from specific kernel versions. Suggested-by: Mike Rapoport Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: Breno Leitao Acked-by: SeongJae Park --- Documentation/admin-guide/mm/kho.rst | 39 ++++++++++++++++++++++++++++++++= ++++ 1 file changed, 39 insertions(+) diff --git a/Documentation/admin-guide/mm/kho.rst b/Documentation/admin-gui= de/mm/kho.rst index cb9a20f649206..b439e4db152a4 100644 --- a/Documentation/admin-guide/mm/kho.rst +++ b/Documentation/admin-guide/mm/kho.rst @@ -42,6 +42,45 @@ For example, if you used ``reserve_mem`` command line pa= rameter to create an early memory reservation, the new kernel will have that memory at the same physical address as the old kernel. =20 +Kexec Metadata +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +KHO automatically tracks metadata about the kexec chain, passing informati= on +about the previous kernel to the next kernel. This feature helps diagnose +bugs that only reproduce when kexecing from specific kernel versions. + +On each KHO kexec, the kernel logs the previous kernel's version and the +number of kexec reboots since the last cold boot:: + + [ 0.000000] KHO: exec from: 6.19.0-rc4-next-20260107 (count 1) + +The metadata includes: + +``previous_release`` + The kernel version string (from ``uname -r``) of the kernel that + initiated the kexec. + +``kexec_count`` + The number of kexec boots since the last cold boot. On cold boot, + this counter starts at 0 and increments with each kexec. This helps + identify issues that only manifest after multiple consecutive kexec + reboots. + +Use Cases +--------- + +This metadata is particularly useful for debugging kexec transition bugs, +where a buggy kernel kexecs into a new kernel and the bug manifests only +in the second kernel. Examples of such bugs include: + +- Memory corruption from the previous kernel affecting the new kernel +- Incorrect hardware state left by the previous kernel +- Firmware/ACPI state issues that only appear in kexec scenarios + +At scale, correlating crashes to the previous kernel version enables +faster root cause analysis when issues only occur in specific kernel +transition scenarios. + debugfs Interfaces =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 --=20 2.47.3