Commit a6c7f4c6 authored by Dan Williams's avatar Dan Williams Committed by Rafael J. Wysocki
Browse files

device-dax: Add a driver for "hmem" devices



Platform firmware like EFI/ACPI may publish "hmem" platform devices.
Such a device is a performance differentiated memory range likely
reserved for an application specific use case. The driver gives access
to 100% of the capacity via a device-dax mmap instance by default.

However, if over-subscription and other kernel memory management is
desired the resulting dax device can be assigned to the core-mm via the
kmem driver.

This consumes "hmem" devices the producer of "hmem" devices is saved for
a follow-on patch so that it can reference the new CONFIG_DEV_DAX_HMEM
symbol to gate performing the enumeration work.

Reported-by: default avatarkbuild test robot <lkp@intel.com>
Reviewed-by: default avatarDave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Acked-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 460370ab
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
@@ -32,19 +32,36 @@ config DEV_DAX_PMEM

	  Say M if unsure

config DEV_DAX_HMEM
	tristate "HMEM DAX: direct access to 'specific purpose' memory"
	depends on EFI_SOFT_RESERVE
	default DEV_DAX
	help
	  EFI 2.8 platforms, and others, may advertise 'specific purpose'
	  memory. For example, a high bandwidth memory pool. The
	  indication from platform firmware is meant to reserve the
	  memory from typical usage by default. This driver creates
	  device-dax instances for these memory ranges, and that also
	  enables the possibility to assign them to the DEV_DAX_KMEM
	  driver to override the reservation and add them to kernel
	  "System RAM" pool.

	  Say M if unsure.

config DEV_DAX_KMEM
	tristate "KMEM DAX: volatile-use of persistent memory"
	default DEV_DAX
	depends on DEV_DAX
	depends on MEMORY_HOTPLUG # for add_memory() and friends
	help
	  Support access to persistent memory as if it were RAM.  This
	  allows easier use of persistent memory by unmodified
	  applications.
	  Support access to persistent, or other performance
	  differentiated memory as if it were System RAM. This allows
	  easier use of persistent memory by unmodified applications, or
	  adds core kernel memory services to heterogeneous memory types
	  (HMEM) marked "reserved" by platform firmware.

	  To use this feature, a DAX device must be unbound from the
	  device_dax driver (PMEM DAX) and bound to this kmem driver
	  on each boot.
	  device_dax driver and bound to this kmem driver on each boot.

	  Say N if unsure.

+2 −0
Original line number Diff line number Diff line
@@ -2,9 +2,11 @@
obj-$(CONFIG_DAX) += dax.o
obj-$(CONFIG_DEV_DAX) += device_dax.o
obj-$(CONFIG_DEV_DAX_KMEM) += kmem.o
obj-$(CONFIG_DEV_DAX_HMEM) += dax_hmem.o

dax-y := super.o
dax-y += bus.o
device_dax-y := device.o
dax_hmem-y := hmem.o

obj-y += pmem/

drivers/dax/hmem.c

0 → 100644
+56 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include <linux/platform_device.h>
#include <linux/memregion.h>
#include <linux/module.h>
#include <linux/pfn_t.h>
#include "bus.h"

static int dax_hmem_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct dev_pagemap pgmap = { };
	struct dax_region *dax_region;
	struct memregion_info *mri;
	struct dev_dax *dev_dax;
	struct resource *res;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENOMEM;

	mri = dev->platform_data;
	memcpy(&pgmap.res, res, sizeof(*res));

	dax_region = alloc_dax_region(dev, pdev->id, res, mri->target_node,
			PMD_SIZE, PFN_DEV|PFN_MAP);
	if (!dax_region)
		return -ENOMEM;

	dev_dax = devm_create_dev_dax(dax_region, 0, &pgmap);
	if (IS_ERR(dev_dax))
		return PTR_ERR(dev_dax);

	/* child dev_dax instances now own the lifetime of the dax_region */
	dax_region_put(dax_region);
	return 0;
}

static int dax_hmem_remove(struct platform_device *pdev)
{
	/* devm handles teardown */
	return 0;
}

static struct platform_driver dax_hmem_driver = {
	.probe = dax_hmem_probe,
	.remove = dax_hmem_remove,
	.driver = {
		.name = "hmem",
	},
};

module_platform_driver(dax_hmem_driver);

MODULE_ALIAS("platform:hmem*");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Intel Corporation");
+4 −0
Original line number Diff line number Diff line
@@ -4,6 +4,10 @@
#include <linux/types.h>
#include <linux/errno.h>

struct memregion_info {
	int target_node;
};

#ifdef CONFIG_MEMREGION
int memregion_alloc(gfp_t gfp);
void memregion_free(int id);