mm/nvidmm: Drop x86 dependency on nvdimm e820 device
Subsystems (3)
RFC PATCH 1/2 mm/nvidmm: Drop x86 dependency on nvdimm e820 device
This patch adds new Kconfig variable PMEM_PLATFORM_DEVICE and use that to select the nvdimm e820 device. The x86 config is now named X86_PMEM_LEGACY_DEVICE.
--- arch/x86/Kconfig | 5 +---- arch/x86/include/asm/e820/types.h | 2 +- arch/x86/include/uapi/asm/e820.h | 2 +- drivers/nvdimm/Kconfig | 5 ++++- drivers/nvdimm/Makefile | 2 +- tools/testing/nvdimm/Kbuild | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-)
arch/x86/Kconfig +1 -4
@@ -1641,13 +1641,10 @@ config ILLEGAL_POINTER_VALUE source "mm/Kconfig" config X86_PMEM_LEGACY_DEVICE - bool - -config X86_PMEM_LEGACY tristate "Support non-standard NVDIMMs and ADR protected memory" depends on PHYS_ADDR_T_64BIT depends on BLK_DEV - select X86_PMEM_LEGACY_DEVICE + select PMEM_PLATFORM_DEVICE select LIBNVDIMM help Treat memory marked using the non-standard e820 type of 12 as used
arch/x86/include/asm/e820/types.h +1 -1
@@ -20,7 +20,7 @@ enum e820_type {* NVDIMM regions that persist over a reboot. * * The kernel will ignore their special capabilities -* unless the CONFIG_X86_PMEM_LEGACY=y option is set. +* unless the CONFIG_X86_PMEM_LEGACY_DEVICE=y option is set. * * ( Note that older platforms also used 6 for the same * type of memory, but newer versions switched to 12 as
arch/x86/include/uapi/asm/e820.h +1 -1
@@ -38,7 +38,7 @@/* * This is a non-standardized way to represent ADR or NVDIMM regions that * persist over a reboot. The kernel will ignore their special capabilities -* unless the CONFIG_X86_PMEM_LEGACY option is set. +* unless the CONFIG_X86_PMEM_LEGACY_DEVICE option is set. * * ( Note that older platforms also used 6 for the same type of memory, * but newer versions switched to 12 as 6 was assigned differently. Some
drivers/nvdimm/Kconfig +4 -1
@@ -27,7 +27,7 @@ config BLK_DEV_PMEM Memory ranges for PMEM are described by either an NFIT (NVDIMM Firmware Interface Table, see CONFIG_NFIT_ACPI), a non-standard OEM-specific E820 memory type (type-12, see - CONFIG_X86_PMEM_LEGACY), or it is manually specified by the + CONFIG_X86_PMEM_LEGACY_DEVICE), or it is manually specified by the 'memmap=nn[KMG]!ss[KMG]' kernel command line (see Documentation/admin-guide/kernel-parameters.rst). This driver converts these persistent memory ranges into block devices that are
@@ -112,4 +112,7 @@ config OF_PMEM Select Y if unsure. +config PMEM_PLATFORM_DEVICE + bool + endif
drivers/nvdimm/Makefile +1 -1
@@ -3,7 +3,7 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o obj-$(CONFIG_ND_BTT) += nd_btt.o obj-$(CONFIG_ND_BLK) += nd_blk.o -obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o +obj-$(CONFIG_PMEM_PLATFORM_DEVICE) += nd_e820.o obj-$(CONFIG_OF_PMEM) += of_pmem.o nd_pmem-y := pmem.o
tools/testing/nvdimm/Kbuild +1 -1
@@ -27,7 +27,7 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o obj-$(CONFIG_ND_BTT) += nd_btt.o obj-$(CONFIG_ND_BLK) += nd_blk.o -obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o +obj-$(CONFIG_PMEM_PLATFORM_DEVICE) += nd_e820.o obj-$(CONFIG_ACPI_NFIT) += nfit.o ifeq ($(CONFIG_DAX),m) obj-$(CONFIG_DAX) += dax.o
Signature · 1 line
2.17.1
RFC PATCH 2/2 mm/pmem: Add memblock based e820 platform driver
This patch steal system RAM and use that to emulate pmem device using the e820 platform driver.
This adds a new kernel command line 'pmemmap' which takes the format <size[KMG]> to allocate memory early in the boot. This memory is later registered as persistent memory range.
Based on original patch from Oliver OHalloran <[email protected]>
--- drivers/nvdimm/Kconfig | 13 ++++ drivers/nvdimm/Makefile | 1 + drivers/nvdimm/memblockpmem.c | 115 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 drivers/nvdimm/memblockpmem.c
drivers/nvdimm/Kconfig +13 -0
@@ -115,4 +115,17 @@ config OF_PMEM config PMEM_PLATFORM_DEVICE bool +config MEMBLOCK_PMEM + bool "pmemmap= parameter support" + default y + depends on HAVE_MEMBLOCK + select PMEM_PLATFORM_DEVICE + help + Add support for the pmemmap= kernel command line parameter. This is similar + to the memmap= parameter available on ACPI platforms, but it uses generic + kernel facilities (the memblock allocator) to reserve memory rather than adding + to the e820 table. + + Select Y if unsure. + endif
drivers/nvdimm/Makefile +1 -0
@@ -5,6 +5,7 @@ obj-$(CONFIG_ND_BTT) += nd_btt.o obj-$(CONFIG_ND_BLK) += nd_blk.o obj-$(CONFIG_PMEM_PLATFORM_DEVICE) += nd_e820.o obj-$(CONFIG_OF_PMEM) += of_pmem.o +obj-$(CONFIG_MEMBLOCK_PMEM) += memblockpmem.o nd_pmem-y := pmem.o
drivers/nvdimm/memblockpmem.c new file +115 -0
115 lines not on this page · raw message
Signature · 1 line
2.17.1
Re: [RFC PATCH 2/2] mm/pmem: Add memblock based e820 platform driver
Quoted 29 lines · Aneesh Kumar K.V
This patch steal system RAM and use that to emulate pmem device using the e820 platform driver.
This adds a new kernel command line 'pmemmap' which takes the format <size[KMG]> to allocate memory early in the boot. This memory is later registered as persistent memory range.
Based on original patch from Oliver OHalloran <[email protected]>
Not-Signed-off-by Aneesh Kumar K.V <[email protected]>--- drivers/nvdimm/Kconfig | 13 ++++ drivers/nvdimm/Makefile | 1 + drivers/nvdimm/memblockpmem.c | 115 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 drivers/nvdimm/memblockpmem.cdrivers/nvdimm/Kconfig +4
-0@@ -115,4 +115,17 @@ config OF_PMEM config PMEM_PLATFORM_DEVICE bool +config MEMBLOCK_PMEM + bool "pmemmap= parameter support" + default y + depends on HAVE_MEMBLOCK
drivers/nvdimm/Kconfig config OF_PMEM · line 131
Quoted 10 lines
drivers/nvdimm/Kconfig +9
-0+ select PMEM_PLATFORM_DEVICE + help + Add support for the pmemmap= kernel command line parameter. This is similar + to the memmap= parameter available on ACPI platforms, but it uses generic + kernel facilities (the memblock allocator) to reserve memory rather than adding + to the e820 table. + + Select Y if unsure. + endif
There's a high barrier for "default y", something like if the platform or device cannot boot without it, it can be "default y". I have doubts that this is OK.
Signature · 1 line
~Randy
Re: [RFC PATCH 2/2] mm/pmem: Add memblock based e820 platform driver
In reply to Aneesh Kumar K.VQuoted 17 lines · Aneesh Kumar K.V
This patch steal system RAM and use that to emulate pmem device using the e820 platform driver.
This adds a new kernel command line 'pmemmap' which takes the format <size[KMG]> to allocate memory early in the boot. This memory is later registered as persistent memory range.
Based on original patch from Oliver OHalloran <[email protected]>
Not-Signed-off-by Aneesh Kumar K.V <[email protected]>--- drivers/nvdimm/Kconfig | 13 ++++ drivers/nvdimm/Makefile | 1 + drivers/nvdimm/memblockpmem.c | 115 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 drivers/nvdimm/memblockpmem.c
[..]
Quoted 6 lines
+/*
+ * pmemmap=ss[KMG]
+ *
+ * This is similar to the memremap=offset[KMG]!size[KMG] paramater
+ * for adding a legacy pmem range to the e820 map on x86, but it's
+ * platform agnostic.
The current memmap=ss!nn option is a non-stop source of bugs and fragility. The fact that this lets the kernel specify the base address helps, but then this is purely just a debug facility because memmap=ss!nn is there to cover platform firmware implementations that fail to mark a given address range as persistent.
If this is just for debug, why not use qemu? If this is not for debug what are these systems that don't have proper firmware support?
Re: [RFC PATCH 2/2] mm/pmem: Add memblock based e820 platform driver
Quoted 27 lines · Dan Williams
Quoted 17 lines · Aneesh Kumar K.V
This patch steal system RAM and use that to emulate pmem device using the e820 platform driver.
This adds a new kernel command line 'pmemmap' which takes the format <size[KMG]> to allocate memory early in the boot. This memory is later registered as persistent memory range.
Based on original patch from Oliver OHalloran <[email protected]>
Not-Signed-off-by Aneesh Kumar K.V <[email protected]>--- drivers/nvdimm/Kconfig | 13 ++++ drivers/nvdimm/Makefile | 1 + drivers/nvdimm/memblockpmem.c | 115 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 drivers/nvdimm/memblockpmem.c[..]
Quoted 6 lines
+/*
+ * pmemmap=ss[KMG]
+ *
+ * This is similar to the memremap=offset[KMG]!size[KMG] paramater
+ * for adding a legacy pmem range to the e820 map on x86, but it's
+ * platform agnostic.
Quoted 7 lines
The current memmap=ss!nn option is a non-stop source of bugs and fragility. The fact that this lets the kernel specify the base address helps, but then this is purely just a debug facility because memmap=ss!nn is there to cover platform firmware implementations that fail to mark a given address range as persistent.
If this is just for debug, why not use qemu?
To make a long story short, we have two virtualisation stacks and only one of them is based on qemu. An unfortunately large chunk of our customers (and our internal test systems) run the other one so we need to accommodate them somehow.
Quoted 2 lines
If this is not for debug what are these systems that don't have proper firmware support?
I wrote the original version (for RHEL 7.something) for a customer who wanted to do some testing which needed to be run on real hardware for some reason. We couldn't install a FW update on their system so this ended up being the least painful way to get them going. That's not a strong argument for merging this, but
the point is that it's sometimes useful to have the capability in the kernel.
Oliver
Re: [RFC PATCH 2/2] mm/pmem: Add memblock based e820 platform driver
Quoted 44 lines · Oliver
Quoted 27 lines · Dan Williams
Quoted 17 lines · Aneesh Kumar K.V
This patch steal system RAM and use that to emulate pmem device using the e820 platform driver.
This adds a new kernel command line 'pmemmap' which takes the format <size[KMG]> to allocate memory early in the boot. This memory is later registered as persistent memory range.
Based on original patch from Oliver OHalloran <[email protected]>
Not-Signed-off-by Aneesh Kumar K.V <[email protected]>--- drivers/nvdimm/Kconfig | 13 ++++ drivers/nvdimm/Makefile | 1 + drivers/nvdimm/memblockpmem.c | 115 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 drivers/nvdimm/memblockpmem.c[..]
Quoted 6 lines
+/*
+ * pmemmap=ss[KMG]
+ *
+ * This is similar to the memremap=offset[KMG]!size[KMG] paramater
+ * for adding a legacy pmem range to the e820 map on x86, but it's
+ * platform agnostic.Quoted 7 lines
The current memmap=ss!nn option is a non-stop source of bugs and fragility. The fact that this lets the kernel specify the base address helps, but then this is purely just a debug facility because memmap=ss!nn is there to cover platform firmware implementations that fail to mark a given address range as persistent.
If this is just for debug, why not use qemu?
To make a long story short, we have two virtualisation stacks and only one of them is based on qemu. An unfortunately large chunk of our customers (and our internal test systems) run the other one so we need to accommodate them somehow.
Quoted 2 lines
If this is not for debug what are these systems that don't have proper firmware support?
Quoted 6 lines
I wrote the original version (for RHEL 7.something) for a customer who wanted to do some testing which needed to be run on real hardware for some reason. We couldn't install a FW update on their system so this ended up being the least painful way to get them going. That's not a strong argument for merging this, but
the point is that it's sometimes useful to have the capability in the kernel.
Ok, correct me if I'm wrong, but it seems to be purely about debug and emulation? If that's the case would it be acceptable to just add more capabilities to tools/testing/nvdimm/ for what you want to do? That has been our primary vehicle for testing libnvdimm.
Re: [RFC PATCH 2/2] mm/pmem: Add memblock based e820 platform driver
Quoted 52 lines · Dan Williams
Quoted 44 lines · Oliver
Quoted 27 lines · Dan Williams
Quoted 17 lines · Aneesh Kumar K.V
This patch steal system RAM and use that to emulate pmem device using the e820 platform driver.
This adds a new kernel command line 'pmemmap' which takes the format <size[KMG]> to allocate memory early in the boot. This memory is later registered as persistent memory range.
Based on original patch from Oliver OHalloran <[email protected]>
Not-Signed-off-by Aneesh Kumar K.V <[email protected]>--- drivers/nvdimm/Kconfig | 13 ++++ drivers/nvdimm/Makefile | 1 + drivers/nvdimm/memblockpmem.c | 115 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+)create mode 100644
drivers/nvdimm/memblockpmem.c[..]
Quoted 6 lines
+/*
+ * pmemmap=ss[KMG]
+ *
+ * This is similar to the memremap=offset[KMG]!size[KMG] paramater
+ * for adding a legacy pmem range to the e820 map on x86, but it's
+ * platform agnostic.Quoted 7 lines
The current memmap=ss!nn option is a non-stop source of bugs and fragility. The fact that this lets the kernel specify the base address helps, but then this is purely just a debug facility because memmap=ss!nn is there to cover platform firmware implementations that fail to mark a given address range as persistent.
If this is just for debug, why not use qemu?
To make a long story short, we have two virtualisation stacks and only one of them is based on qemu. An unfortunately large chunk of our customers (and our internal test systems) run the other one so we need to accommodate them somehow.
Quoted 2 lines
If this is not for debug what are these systems that don't have proper firmware support?
Quoted 6 lines
I wrote the original version (for RHEL 7.something) for a customer who wanted to do some testing which needed to be run on real hardware for some reason. We couldn't install a FW update on their system so this ended up being the least painful way to get them going. That's not a strong argument for merging this, but
the point is that it's sometimes useful to have the capability in the kernel.
Quoted 5 lines
Ok, correct me if I'm wrong, but it seems to be purely about debug and emulation? If that's the case would it be acceptable to just add more capabilities to
tools/testing/nvdimm/for what you want to do? That has been our primary vehicle for testing libnvdimm.
What we need is the ability to run with fsdax on hypervisor other than KVM.
-aneesh
Re: [RFC PATCH 2/2] mm/pmem: Add memblock based e820 platform driver
Quoted 1 line · Aneesh Kumar K.V
On 07/07/2018 11:06 PM, Dan Williams wrote:
[..]
Quoted 1 line
What we need is the ability to run with fsdax on hypervisor other than KVM.
That sounds like a production use case? How can it be actual persistent memory if the kernel is picking the physical address backing the range?
Re: [RFC PATCH 2/2] mm/pmem: Add memblock based e820 platform driver
In reply to Aneesh Kumar K.VQuoted 8 lines · Aneesh Kumar K.V
This patch steal system RAM and use that to emulate pmem device using the e820 platform driver.
This adds a new kernel command line 'pmemmap' which takes the format <size[KMG]> to allocate memory early in the boot. This memory is later registered as persistent memory range.
Based on original patch from Oliver OHalloran <[email protected]>
I use this account rather than my internal address for community facing stuff since
no one deserves to have IBM email inflicted upon them. Also you left out the apostrophe, you monster!
Quoted 35 lines
Not-Signed-off-by Aneesh Kumar K.V <[email protected]>--- drivers/nvdimm/Kconfig | 13 ++++ drivers/nvdimm/Makefile | 1 + drivers/nvdimm/memblockpmem.c | 115 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 drivers/nvdimm/memblockpmem.cdrivers/nvdimm/Kconfig +13
-0@@ -115,4 +115,17 @@ config OF_PMEM config PMEM_PLATFORM_DEVICE bool +config MEMBLOCK_PMEM + bool "pmemmap= parameter support" + default y + depends on HAVE_MEMBLOCK + select PMEM_PLATFORM_DEVICE + help + Add support for the pmemmap= kernel command line parameter. This is similar + to the memmap= parameter available on ACPI platforms, but it uses generic + kernel facilities (the memblock allocator) to reserve memory rather than adding + to the e820 table. + + Select Y if unsure. + endifdrivers/nvdimm/Makefile +0
-0
drivers/nvdimm/Makefile obj-$(CONFIG_ND_BTT) += nd_btt.o · line 8
Quoted 4 lines
drivers/nvdimm/Makefile +1
-0@@ -5,6 +5,7 @@ obj-$(CONFIG_ND_BTT) += nd_btt.o obj-$(CONFIG_ND_BLK) += nd_blk.o obj-$(CONFIG_PMEM_PLATFORM_DEVICE) += nd_e820.o obj-$(CONFIG_OF_PMEM) += of_pmem.o +obj-$(CONFIG_MEMBLOCK_PMEM) += memblockpmem.o
Does this work when libnvdimm is built as a module? I remember doing something like
this and discovering that the early_param() stuff didn't get included in the vmlinux
when libnvdimm was built as a module due to how the makefiles worked. It might have
been a bug in the RHEL7 tree I was using that has since been fixed upstream.
Quoted 25 lines
drivers/nvdimm/Makefile +0
-0nd_pmem-y := pmem.odrivers/nvdimm/memblockpmem.c new file +17
-0@@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* Copyright (c) 2018 IBM Corporation +*/ + +#define pr_fmt (fmt) "memblock pmem: " fmt + +#include <linux/libnvdimm.h> +#include <linux/bootmem.h> +#include <linux/memblock.h> +#include <linux/mmzone.h> +#include <linux/cpu.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/ctype.h> +#include <linux/slab.h>
drivers/nvdimm/memblockpmem.c line 27
Quoted 10 lines
drivers/nvdimm/memblockpmem.c new file +10
-0+ +/* +* Align pmem reservations to the section size so we don't have issues with +* memory hotplug +*/ +#ifdef CONFIG_SPARSEMEM +#define BOOTPMEM_ALIGN (1UL << SECTION_SIZE_BITS) +#else +#define BOOTPMEM_ALIGN PFN_DEFAULT_ALIGNMENT +#endif
Is aligning to the section size sufficient? IIRC I had to align it to the memory block
size on some systems. Of course, that might have been a RHEL bug that has since been fixed upstream.
Quoted 27 lines
drivers/nvdimm/memblockpmem.c new file +27
-0+ +static __initdata u64 pmem_size; +static __initdata phys_addr_t pmem_stolen_memory; + +static void alloc_pmem_from_memblock (void ) +{ + + pmem_stolen_memory =memblock_alloc_base (pmem_size, +BOOTPMEM_ALIGN , +MEMBLOCK_ALLOC_ACCESSIBLE ); +if (!pmem_stolen_memory) { +pr_err ("Failed to allocate memory for PMEM from memblock\n" ); +return ; + } + +/* +* Remove from the memblock reserved range +*/ +memblock_free (pmem_stolen_memory, pmem_size); + +/* +* Remove from the memblock memory range. +*/ +memblock_remove (pmem_stolen_memory, pmem_size); +pr_info ("Allocated %ld memory at 0x%lx\n" , (unsigned long )pmem_size, + (unsigned long )pmem_stolen_memory); +return ;
drivers/nvdimm/memblockpmem.c line 64
Quoted 10 lines
drivers/nvdimm/memblockpmem.c new file +10
-0+} + +/* +* pmemmap=ss[KMG] +* +* This is similar to the memremap=offset[KMG]!size[KMG] paramater +* for adding a legacy pmem range to the e820 map on x86, but it's +* platform agnostic. +* +* e.g. pmemmap=16G allocates 16G pmem region
I'm not really thrilled with this and I'd rather we kept the <size>@<node id> format and the ability to reserve multiple regions that I had in the old version.
I know getting the nid allocations working is a pain in the ass since HAVE_MEMBLOCK_NODE_MAP doesn't specify *when* in the boot process the node map information is actually available, but it's useful functionality and
I think the problems are resolvable.
It's also possible that the whole memblock approach to this is wrong and we should look at doing something similar to how gigantic pages are allocated at runtime.
Quoted 54 lines
drivers/nvdimm/memblockpmem.c new file +51
-1+*/ +static int __init parse_pmemmap (char *p) +{ +char *old_p = p; + +if (!p) +return -EINVAL ; + + pmem_size =memparse (p, &p); +if (p == old_p) +return -EINVAL ; + +alloc_pmem_from_memblock (); +return 0 ; +} +early_param ("pmemmap" , parse_pmemmap); + +static __init int register_e820_pmem (void ) +{ +struct resource *res, *conflict; +struct platform_device *pdev; + +if (!pmem_stolen_memory) +return 0 ; + + res =kzalloc (sizeof (*res),GFP_KERNEL ); +if (!res) +return -1 ; + +memset (res,0 ,sizeof (*res)); + res->start = pmem_stolen_memory; + res->end = pmem_stolen_memory + pmem_size -1 ; + res->name ="Persistent Memory (legacy)" ; + res->desc =IORES_DESC_PERSISTENT_MEMORY_LEGACY ; + res->flags =IORESOURCE_MEM ; + + conflict =insert_resource_conflict (&iomem_resource, res); +if (conflict) { +pr_err ("%pR conflicts, try insert below %pR\n" , res, conflict); +kfree (res); +return -1 ; + } +/* +* See drivers/nvdimm/e820.c for the implementation, this is +* simply here to trigger the module to load on demand. +*/ + pdev =platform_device_alloc ("e820_pmem" ,-1 ); + +return platform_device_add (pdev); +} +device_initcall (register_e820_pmem); --2.17.1
Re: [RFC PATCH 2/2] mm/pmem: Add memblock based e820 platform driver
Quoted 9 lines · Oliver
Quoted 7 lines · Aneesh Kumar K.V
This patch steal system RAM and use that to emulate pmem device using the e820 platform driver.
This adds a new kernel command line 'pmemmap' which takes the format <size[KMG]> to allocate memory early in the boot. This memory is later registered as persistent memory range.
Quoted 6 lines
Quoted 1 line
Based on original patch from Oliver OHalloran <[email protected]>
I use this account rather than my internal address for community facing stuff since
no one deserves to have IBM email inflicted upon them. Also you left out the apostrophe, you monster!
:) Will switch to gmail.com address?
Quoted 41 lines
Quoted 36 lines
Not-Signed-off-by Aneesh Kumar K.V <[email protected]>--- drivers/nvdimm/Kconfig | 13 ++++ drivers/nvdimm/Makefile | 1 + drivers/nvdimm/memblockpmem.c | 115 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+)create mode 100644
drivers/nvdimm/memblockpmem.cdrivers/nvdimm/Kconfig +13
-0@@ -115,4 +115,17 @@ config OF_PMEM config PMEM_PLATFORM_DEVICE bool +config MEMBLOCK_PMEM + bool "pmemmap= parameter support" + default y + depends on HAVE_MEMBLOCK + select PMEM_PLATFORM_DEVICE + help + Add support for the pmemmap= kernel command line parameter. This is similar + to the memmap= parameter available on ACPI platforms, but it uses generic + kernel facilities (the memblock allocator) to reserve memory rather than adding + to the e820 table. + + Select Y if unsure. + endifdrivers/nvdimm/Makefile +0
-0drivers/nvdimm/Makefile obj-$(CONFIG_ND_BTT) += nd_btt.o · line 8
Quoted 4 lines
drivers/nvdimm/Makefile +1
-0@@ -5,6 +5,7 @@ obj-$(CONFIG_ND_BTT) += nd_btt.o obj-$(CONFIG_ND_BLK) += nd_blk.o obj-$(CONFIG_PMEM_PLATFORM_DEVICE) += nd_e820.o obj-$(CONFIG_OF_PMEM) += of_pmem.o +obj-$(CONFIG_MEMBLOCK_PMEM) += memblockpmem.o
Quoted 8 lines
Does this work when libnvdimm is built as a module? I remember doing something like
this and discovering that theearly_param()stuff didn't get included in the vmlinux
when libnvdimm was built as a module due to how the makefiles worked. It might have
been a bug in the RHEL7 tree I was using that has since been fixed upstream.
I didn't check that. Will do that in next iteration.
Quoted 32 lines
Quoted 32 lines
drivers/nvdimm/Makefile +0
-0nd_pmem-y := pmem.odrivers/nvdimm/memblockpmem.c new file +24
-0@@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* Copyright (c) 2018 IBM Corporation +*/ + +#define pr_fmt (fmt) "memblock pmem: " fmt + +#include <linux/libnvdimm.h> +#include <linux/bootmem.h> +#include <linux/memblock.h> +#include <linux/mmzone.h> +#include <linux/cpu.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/ctype.h> +#include <linux/slab.h> + +/* +* Align pmem reservations to the section size so we don't have issues with +* memory hotplug +*/ +#ifdef CONFIG_SPARSEMEM +#define BOOTPMEM_ALIGN (1UL << SECTION_SIZE_BITS)
Quoted 9 lines
drivers/nvdimm/memblockpmem.c line 27
Quoted 3 lines
drivers/nvdimm/memblockpmem.c new file +3
-0+#else +#define BOOTPMEM_ALIGN PFN_DEFAULT_ALIGNMENT +#endif Is aligning to the section size sufficient? IIRC I had to align it to the memory block
size on some systems. Of course, that might have been a RHEL bug that has since been fixed upstream.
Ok, I didn't face any issues. But will look more what issues we could face.
Quoted 42 lines
Quoted 27 lines
drivers/nvdimm/memblockpmem.c new file +27
-0+ +static __initdata u64 pmem_size; +static __initdata phys_addr_t pmem_stolen_memory; + +static void alloc_pmem_from_memblock (void ) +{ + + pmem_stolen_memory =memblock_alloc_base (pmem_size, +BOOTPMEM_ALIGN , +MEMBLOCK_ALLOC_ACCESSIBLE ); +if (!pmem_stolen_memory) { +pr_err ("Failed to allocate memory for PMEM from memblock\n" ); +return ; + } + +/* +* Remove from the memblock reserved range +*/ +memblock_free (pmem_stolen_memory, pmem_size); + +/* +* Remove from the memblock memory range. +*/ +memblock_remove (pmem_stolen_memory, pmem_size); +pr_info ("Allocated %ld memory at 0x%lx\n" , (unsigned long )pmem_size, + (unsigned long )pmem_stolen_memory); +return ;drivers/nvdimm/memblockpmem.c line 64
Quoted 10 lines
drivers/nvdimm/memblockpmem.c new file +10
-0+} + +/* +* pmemmap=ss[KMG] +* +* This is similar to the memremap=offset[KMG]!size[KMG] paramater +* for adding a legacy pmem range to the e820 map on x86, but it's +* platform agnostic. +* +* e.g. pmemmap=16G allocates 16G pmem region I'm not really thrilled with this and I'd rather we kept the <size>@<node id> format and the ability to reserve multiple regions that I had in the old version.
Quoted 6 lines
I know getting the nid allocations working is a pain in the ass since
HAVE_MEMBLOCK_NODE_MAPdoesn't specify *when* in the boot process the node map information is actually available, but it's useful functionality and
I think the problems are resolvable.
The reason I dropped the @nid is because, we do set node details in memblock late (memblock_set_node()). We setup our linear mapped page table before that. That implies, we can't steal memory from memblock and use that for pmem backing if we do the pmem backing allocation after node information is set on memblock. Since we can't use nid, I was not sure there is any value in doing multiple pmem region.
Quoted 48 lines
It's also possible that the whole memblock approach to this is wrong and we should look at doing something similar to how gigantic pages are allocated at runtime.
Quoted 44 lines
drivers/nvdimm/memblockpmem.c new file +44
-0+*/ +static int __init parse_pmemmap (char *p) +{ +char *old_p = p; + +if (!p) +return -EINVAL ; + + pmem_size =memparse (p, &p); +if (p == old_p) +return -EINVAL ; + +alloc_pmem_from_memblock (); +return 0 ; +} +early_param ("pmemmap" , parse_pmemmap); + +static __init int register_e820_pmem (void ) +{ +struct resource *res, *conflict; +struct platform_device *pdev; + +if (!pmem_stolen_memory) +return 0 ; + + res =kzalloc (sizeof (*res),GFP_KERNEL ); +if (!res) +return -1 ; + +memset (res,0 ,sizeof (*res)); + res->start = pmem_stolen_memory; + res->end = pmem_stolen_memory + pmem_size -1 ; + res->name ="Persistent Memory (legacy)" ; + res->desc =IORES_DESC_PERSISTENT_MEMORY_LEGACY ; + res->flags =IORESOURCE_MEM ; + + conflict =insert_resource_conflict (&iomem_resource, res); +if (conflict) { +pr_err ("%pR conflicts, try insert below %pR\n" , res, conflict); +kfree (res); +return -1 ; + } +/* +* See drivers/nvdimm/e820.c for the implementation, this is
Quoted 8 lines
drivers/nvdimm/memblockpmem.c
Quoted 8 lines
drivers/nvdimm/memblockpmem.c new file +7
-1+* simply here to trigger the module to load on demand. +*/ + pdev =platform_device_alloc ("e820_pmem" ,-1 ); + +return platform_device_add (pdev); +} +device_initcall (register_e820_pmem); --
-aneesh