From: Stanislav Kinsburskii <stanislav.kinsburskii@xxxxxxxxx> Introduce a pmpool kexec fdt notifier that enables pmpool to pass its metadata, including the bitmap address, to the new kernel during kexec. Signed-off-by: Stanislav Kinsburskii <skinsburskii@xxxxxxxxxxxxxxxxxxx> --- mm/Kconfig | 1 + mm/pmpool.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/mm/Kconfig b/mm/Kconfig index e7c10094fb10..1eefdd4c82ba 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -925,6 +925,7 @@ config CMA_AREAS config PMPOOL bool "Persistent memory pool support" select CMA + select LIBFDT help This option adds support for CMA-based persistent memory pool feature, which provides pages allocation and freeing from a set of diff --git a/mm/pmpool.c b/mm/pmpool.c index 12a8cac75558..f2173db782d6 100644 --- a/mm/pmpool.c +++ b/mm/pmpool.c @@ -6,6 +6,7 @@ #include <linux/cma.h> #include <linux/io.h> #include <linux/kexec.h> +#include <linux/libfdt.h> #include <linux/memblock.h> #include <linux/mm.h> #include <linux/pmpool.h> @@ -58,6 +59,59 @@ static int __init default_pmpool_fixup_cma(void) } postcore_initcall(default_pmpool_fixup_cma); +static int pmpool_fdt_update(struct notifier_block *nb, unsigned long val, + void *data) +{ + void *fdt = data; + int node, status; + + if (!fdt) + goto err; + + node = fdt_subnode_offset(fdt, 0, "chosen"); + if (node < 0) { + node = fdt_add_subnode(fdt, 0, "chosen"); + if (node < 0) + goto err; + } + + node = fdt_add_subnode(fdt, node, "default_pmpool"); + if (node == -FDT_ERR_EXISTS) + return 0; + if (node < 0) + goto err; + + status = fdt_setprop(fdt, node, "compatible", + "pmpool", sizeof("pmpool")); + if (status) + goto err; + + status = fdt_setprop_u64(fdt, node, "bitmap", + virt_to_phys(default_pmpool->cma->bitmap)); + if (status) + goto err; + + status = fdt_setprop_u64(fdt, node, "size", + default_pmpool->cma->count << PAGE_SHIFT); + if (status) + goto err; + + status = fdt_setprop_u64(fdt, node, "base", + default_pmpool->cma->base_pfn << PAGE_SHIFT); + if (status) + goto err; + + return NOTIFY_DONE; + +err: + pr_err("failed to update fdt\n"); + return NOTIFY_DONE; +} + +static struct notifier_block pmpool_kexec_fdt_nb = { + .notifier_call = pmpool_fdt_update, +}; + static int __init parse_pmpool_opt(char *str) { static struct pmpool pmpool; @@ -80,10 +134,16 @@ static int __init parse_pmpool_opt(char *str) return 0; } + err = register_kexec_fdt_notifier(&pmpool_kexec_fdt_nb); + if (err) { + pr_err("failed to register kexec fdt notifier: %d\n", err); + goto free_memblock; + } + err = cma_init_reserved_mem(base, size, 0, "pmpool", &pmpool.cma); if (err) { pr_err("failed to initialize CMA: %d\n", err); - goto free_memblock; + goto notifier_unregister; } pr_info("default memory pool is created: %#llx-%#llx\n", @@ -93,6 +153,8 @@ static int __init parse_pmpool_opt(char *str) return 0; +notifier_unregister: + unregister_kexec_fdt_notifier(&pmpool_kexec_fdt_nb); free_memblock: memblock_phys_free(base, size); return 0; _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec