Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

kho: persist blob size in KHO FDT

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.

Link: https://lore.kernel.org/20260316-kho-v9-3-ed6dcd951988@debian.org
Signed-off-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
Cc: Alexander Graf <graf@amazon.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: "Liam R. Howlett" <Liam.Howlett@oracle.com>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
Cc: SeongJae Park <sj@kernel.org>
Cc: Shuah Khan <skhan@linuxfoundation.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Breno Leitao and committed by
Andrew Morton
85e41392 4916ae38

+46 -15
+3 -2
include/linux/kexec_handover.h
··· 34 34 void *kho_restore_vmalloc(const struct kho_vmalloc *preservation); 35 35 int kho_add_subtree(const char *name, void *blob, size_t size); 36 36 void kho_remove_subtree(void *blob); 37 - int kho_retrieve_subtree(const char *name, phys_addr_t *phys); 37 + int kho_retrieve_subtree(const char *name, phys_addr_t *phys, size_t *size); 38 38 39 39 void kho_memory_init(void); 40 40 ··· 104 104 105 105 static inline void kho_remove_subtree(void *blob) { } 106 106 107 - static inline int kho_retrieve_subtree(const char *name, phys_addr_t *phys) 107 + static inline int kho_retrieve_subtree(const char *name, phys_addr_t *phys, 108 + size_t *size) 108 109 { 109 110 return -EOPNOTSUPP; 110 111 }
+16 -4
include/linux/kho/abi/kexec_handover.h
··· 41 41 * restore the preserved data.:: 42 42 * 43 43 * / { 44 - * compatible = "kho-v2"; 44 + * compatible = "kho-v3"; 45 45 * 46 46 * preserved-memory-map = <0x...>; 47 47 * 48 48 * <subnode-name-1> { 49 49 * preserved-data = <0x...>; 50 + * blob-size = <0x...>; 50 51 * }; 51 52 * 52 53 * <subnode-name-2> { 53 54 * preserved-data = <0x...>; 55 + * blob-size = <0x...>; 54 56 * }; 55 57 * ... ... 56 58 * <subnode-name-N> { 57 59 * preserved-data = <0x...>; 60 + * blob-size = <0x...>; 58 61 * }; 59 62 * }; 60 63 * 61 64 * Root KHO Node (/): 62 - * - compatible: "kho-v2" 65 + * - compatible: "kho-v3" 63 66 * 64 67 * Indentifies the overall KHO ABI version. 65 68 * ··· 81 78 * 82 79 * Physical address pointing to a subnode data blob that is also 83 80 * being preserved. 81 + * 82 + * - blob-size: u64 83 + * 84 + * Size in bytes of the preserved data blob. This is needed because 85 + * blobs may use arbitrary formats (not just FDT), so the size 86 + * cannot be determined from the blob content alone. 84 87 */ 85 88 86 89 /* The compatible string for the KHO FDT root node. */ 87 - #define KHO_FDT_COMPATIBLE "kho-v2" 90 + #define KHO_FDT_COMPATIBLE "kho-v3" 88 91 89 92 /* The FDT property for the preserved memory map. */ 90 93 #define KHO_FDT_MEMORY_MAP_PROP_NAME "preserved-memory-map" 91 94 92 95 /* The FDT property for preserved data blobs. */ 93 - #define KHO_FDT_SUB_TREE_PROP_NAME "preserved-data" 96 + #define KHO_SUB_TREE_PROP_NAME "preserved-data" 97 + 98 + /* The FDT property for the size of preserved data blobs. */ 99 + #define KHO_SUB_TREE_SIZE_PROP_NAME "blob-size" 94 100 95 101 /** 96 102 * DOC: Kexec Handover ABI for vmalloc Preservation
+22 -5
kernel/liveupdate/kexec_handover.c
··· 743 743 { 744 744 phys_addr_t phys = virt_to_phys(blob); 745 745 void *root_fdt = kho_out.fdt; 746 + u64 size_u64 = size; 746 747 int err = -ENOMEM; 747 748 int off, fdt_err; 748 749 ··· 760 759 goto out_pack; 761 760 } 762 761 763 - err = fdt_setprop(root_fdt, off, KHO_FDT_SUB_TREE_PROP_NAME, 762 + err = fdt_setprop(root_fdt, off, KHO_SUB_TREE_PROP_NAME, 764 763 &phys, sizeof(phys)); 764 + if (err < 0) 765 + goto out_pack; 766 + 767 + err = fdt_setprop(root_fdt, off, KHO_SUB_TREE_SIZE_PROP_NAME, 768 + &size_u64, sizeof(size_u64)); 765 769 if (err < 0) 766 770 goto out_pack; 767 771 ··· 798 792 const u64 *val; 799 793 int len; 800 794 801 - val = fdt_getprop(root_fdt, off, KHO_FDT_SUB_TREE_PROP_NAME, &len); 795 + val = fdt_getprop(root_fdt, off, KHO_SUB_TREE_PROP_NAME, &len); 802 796 if (!val || len != sizeof(phys_addr_t)) 803 797 continue; 804 798 ··· 1303 1297 * kho_retrieve_subtree - retrieve a preserved sub blob by its name. 1304 1298 * @name: the name of the sub blob passed to kho_add_subtree(). 1305 1299 * @phys: if found, the physical address of the sub blob is stored in @phys. 1300 + * @size: if not NULL and found, the size of the sub blob is stored in @size. 1306 1301 * 1307 1302 * Retrieve a preserved sub blob named @name and store its physical 1308 - * address in @phys. 1303 + * address in @phys and optionally its size in @size. 1309 1304 * 1310 1305 * Return: 0 on success, error code on failure 1311 1306 */ 1312 - int kho_retrieve_subtree(const char *name, phys_addr_t *phys) 1307 + int kho_retrieve_subtree(const char *name, phys_addr_t *phys, size_t *size) 1313 1308 { 1314 1309 const void *fdt = kho_get_fdt(); 1315 1310 const u64 *val; ··· 1326 1319 if (offset < 0) 1327 1320 return -ENOENT; 1328 1321 1329 - val = fdt_getprop(fdt, offset, KHO_FDT_SUB_TREE_PROP_NAME, &len); 1322 + val = fdt_getprop(fdt, offset, KHO_SUB_TREE_PROP_NAME, &len); 1330 1323 if (!val || len != sizeof(*val)) 1331 1324 return -EINVAL; 1332 1325 1333 1326 *phys = (phys_addr_t)*val; 1327 + 1328 + val = fdt_getprop(fdt, offset, KHO_SUB_TREE_SIZE_PROP_NAME, &len); 1329 + if (!val || len != sizeof(*val)) { 1330 + pr_warn("broken KHO subnode '%s': missing or invalid blob-size property\n", 1331 + name); 1332 + return -EINVAL; 1333 + } 1334 + 1335 + if (size) 1336 + *size = (size_t)*val; 1334 1337 1335 1338 return 0; 1336 1339 }
+2 -1
kernel/liveupdate/kexec_handover_debugfs.c
··· 125 125 const u64 *fdt_phys; 126 126 void *sub_fdt; 127 127 128 - fdt_phys = fdt_getprop(fdt, child, KHO_FDT_SUB_TREE_PROP_NAME, &len); 128 + fdt_phys = fdt_getprop(fdt, child, 129 + KHO_SUB_TREE_PROP_NAME, &len); 129 130 if (!fdt_phys) 130 131 continue; 131 132 if (len != sizeof(*fdt_phys)) {
+1 -1
kernel/liveupdate/luo_core.c
··· 88 88 } 89 89 90 90 /* Retrieve LUO subtree, and verify its format. */ 91 - err = kho_retrieve_subtree(LUO_FDT_KHO_ENTRY_NAME, &fdt_phys); 91 + err = kho_retrieve_subtree(LUO_FDT_KHO_ENTRY_NAME, &fdt_phys, NULL); 92 92 if (err) { 93 93 if (err != -ENOENT) { 94 94 pr_err("failed to retrieve FDT '%s' from KHO: %pe\n",
+1 -1
lib/test_kho.c
··· 319 319 if (!kho_is_enabled()) 320 320 return 0; 321 321 322 - err = kho_retrieve_subtree(KHO_TEST_FDT, &fdt_phys); 322 + err = kho_retrieve_subtree(KHO_TEST_FDT, &fdt_phys, NULL); 323 323 if (!err) { 324 324 err = kho_test_restore(fdt_phys); 325 325 if (err)
+1 -1
mm/memblock.c
··· 2555 2555 if (fdt) 2556 2556 return fdt; 2557 2557 2558 - err = kho_retrieve_subtree(MEMBLOCK_KHO_FDT, &fdt_phys); 2558 + err = kho_retrieve_subtree(MEMBLOCK_KHO_FDT, &fdt_phys, NULL); 2559 2559 if (err) { 2560 2560 if (err != -ENOENT) 2561 2561 pr_warn("failed to retrieve FDT '%s' from KHO: %d\n",