kho: add support for preserving vmalloc allocations
Subsystems (5)
Mike Rapoport
maintainerv2 cover kho: add support for preserving vmalloc allocations
From: "Mike Rapoport (Microsoft)" <[email protected]>
Hi,
Following the discussion about preservation of memfd with LUO [1] these patches add support for preserving vmalloc allocations.
Any KHO uses case presumes that there's a data structure that lists physical addresses of preserved folios (and potentially some additional metadata). Allowing vmalloc preservations with KHO allows scalable preservation of such data structures.
For instance, instead of allocating array describing preserved folios in the fdt, memfd preservation can use vmalloc:
preserved_folios = vmalloc_array(nr_folios, sizeof(*preserved_folios));
memfd_luo_preserve_folios(preserved_folios, folios, nr_folios);
kho_preserve_vmalloc(preserved_folios, &folios_info);[1] https://lore.kernel.org/all/[email protected]
v2 changes:
* support preservation of vmalloc backed by large pages
* add check for supported vmalloc flags and preserve the flags to be able to identify incompatible preservations
* don't use kho_preserve_phys()
* add kernel-doc
v1: https://lore.kernel.org/all/[email protected]
Mike Rapoport (Microsoft) (2):
kho: add support for preserving vmalloc allocations lib/test_kho: use kho_preserve_vmalloc instead of storing addresses in fdt
include/linux/kexec_handover.h | 12 ++ kernel/kexec_handover.c | 200 +++++++++++++++++++++++++++++++++ lib/test_kho.c | 30 +++-- 3 files changed, 235 insertions(+), 7 deletions(-)
base-commit: b320789d6883cc00ac78ce83bccbfe7ed58afcf0
Signature · 1 line
2.50.1
Mike Rapoport
maintainerPATCH v2 1/2 kho: add support for preserving vmalloc allocations
From: "Mike Rapoport (Microsoft)" <[email protected]>
A vmalloc allocation is preserved using binary structure similar to global KHO memory tracker. It's a linked list of pages where each page is an array of physical address of pages in vmalloc area.
kho_preserve_vmalloc() hands out the physical address of the head page to the caller. This address is used as the argument to kho_vmalloc_restore() to restore the mapping in the vmalloc address space and populate it with the preserved pages.
--- include/linux/kexec_handover.h | 12 ++ kernel/kexec_handover.c | 200 +++++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+)
include/linux/kexec_handover.h +12 -0
@@ -42,8 +42,10 @@ struct kho_serialization;bool kho_is_enabled (void );int kho_preserve_folio (struct folio *folio); +int kho_preserve_vmalloc (void *ptr,phys_addr_t *preservation);int kho_preserve_phys (phys_addr_t phys,size_t size);struct folio *kho_restore_folio (phys_addr_t phys); +void *kho_restore_vmalloc (phys_addr_t preservation);int kho_add_subtree (struct kho_serialization *ser,const char *name,void *fdt);int kho_retrieve_subtree (const char *name,phys_addr_t *phys);
@@ -70,11 +72,21 @@ static inline int kho_preserve_phys(phys_addr_t phys, size_t size)return -EOPNOTSUPP ; } +static inline int kho_preserve_vmalloc (void *ptr,phys_addr_t *preservation) +{ +return -EOPNOTSUPP ; +} +static inline struct folio *kho_restore_folio (phys_addr_t phys) {return NULL ; } +static inline void *kho_restore_vmalloc (phys_addr_t preservation) +{ +return NULL ; +} +static inline int kho_add_subtree (struct kho_serialization *ser,const char *name,void *fdt) {
kernel/kexec_handover.c +200 -0
212 lines not on this page · raw message
Signature · 1 line
2.50.1
Mike Rapoport
maintainerPATCH v2 2/2 lib/test_kho: use kho_preserve_vmalloc instead of storing addresses in fdt
In reply to Mike RapoportFrom: "Mike Rapoport (Microsoft)" <[email protected]>
KHO test stores physical addresses of the preserved folios directly in fdt.
Use kho_preserve_vmalloc() instead of it and kho_restore_vmalloc() to retrieve the addresses after kexec.
This makes the test more scalable from one side and adds tests coverage for kho_preserve_vmalloc() from the other.
--- lib/test_kho.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-)
lib/test_kho.c +23 -7
@@ -32,6 +32,7 @@ module_param(max_mem, long, 0644);struct kho_test_state {unsigned int nr_folios;struct folio **folios; +phys_addr_t *folios_info;struct folio *fdt;__wsum csum; };
@@ -68,13 +69,17 @@ static struct notifier_block kho_test_nb = {static int kho_test_save_data (struct kho_test_state *state,void *fdt) { phys_addr_t *folios_info __free(kvfree) = NULL; +phys_addr_t folios_info_phys;int err =0 ; - folios_info =kvmalloc_array (state->nr_folios,sizeof (*folios_info), -GFP_KERNEL ); + folios_info =vmalloc_array (state->nr_folios,sizeof (*folios_info));if (!folios_info)return -ENOMEM ; + err =kho_preserve_vmalloc (folios_info, &folios_info_phys); +if (err) +return err; +for (int i =0 ; i < state->nr_folios; i++) {struct folio *folio = state->folios[i];unsigned int order =folio_order (folio);
@@ -89,11 +94,14 @@ static int kho_test_save_data(struct kho_test_state *state, void *fdt) err |=fdt_begin_node (fdt,"data" ); err |=fdt_property (fdt,"nr_folios" , &state->nr_folios,sizeof (state->nr_folios)); - err |=fdt_property (fdt,"folios_info" , folios_info, - state->nr_folios *sizeof (*folios_info)); + err |=fdt_property (fdt,"folios_info" , &folios_info_phys, +sizeof (folios_info_phys)); err |=fdt_property (fdt,"csum" , &state->csum,sizeof (state->csum)); err |=fdt_end_node (fdt); +if (!err) + state->folios_info =no_free_ptr (folios_info); +return err; }
@@ -197,7 +205,8 @@ static int kho_test_save(void)static int kho_test_restore_data (const void *fdt,int node) {const unsigned int *nr_folios; -const phys_addr_t *folios_info; +const phys_addr_t *folios_info_phys; +phys_addr_t *folios_info;const __wsum *old_csum;__wsum csum =0 ;int len;
@@ -212,8 +221,12 @@ static int kho_test_restore_data(const void *fdt, int node)if (!old_csum || len !=sizeof (*old_csum))return -EINVAL ; - folios_info =fdt_getprop (fdt, node,"folios_info" , &len); -if (!folios_info || len !=sizeof (*folios_info) * *nr_folios) + folios_info_phys =fdt_getprop (fdt, node,"folios_info" , &len); +if (!folios_info_phys || len !=sizeof (*folios_info_phys)) +return -EINVAL ; + + folios_info =kho_restore_vmalloc (*folios_info_phys); +if (!folios_info)return -EINVAL ;for (int i =0 ; i < *nr_folios; i++) {
@@ -233,6 +246,8 @@ static int kho_test_restore_data(const void *fdt, int node)folio_put (folio); } +vfree (folios_info); +if (csum != *old_csum)return -EINVAL ;
@@ -291,6 +306,7 @@ static void kho_test_cleanup(void)folio_put (kho_test_state.folios[i]);kvfree (kho_test_state.folios); +vfree (kho_test_state.folios_info); } static void __exit kho_test_exit(void)
Signature · 1 line
2.50.1