diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index a165e697..ed40fd0e 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -180,6 +180,7 @@ struct ndctl_region {
 	} iset;
 	FILE *badblocks;
 	struct badblock bb;
+	enum ndctl_persistence_domain persistence_domain;
 };
 
 /**
@@ -916,6 +917,22 @@ NDCTL_EXPORT struct ndctl_bus *ndctl_bus_get_by_provider(struct ndctl_ctx *ctx,
 	return NULL;
 }
 
+NDCTL_EXPORT enum ndctl_persistence_domain
+ndctl_bus_get_persistence_domain(struct ndctl_bus *bus)
+{
+	struct ndctl_region *region;
+	enum ndctl_persistence_domain pd = PERSISTENCE_UNKNOWN;
+
+	/* iterate through region to get the region persistence domain */
+	ndctl_region_foreach(bus, region) {
+		/* we are looking for the least persistence domain */
+		if (pd > region->persistence_domain)
+			pd = region->persistence_domain;
+	}
+
+	return pd;
+}
+
 NDCTL_EXPORT struct ndctl_btt *ndctl_region_get_btt_seed(struct ndctl_region *region)
 {
 	struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
@@ -1755,6 +1772,61 @@ static int region_set_type(struct ndctl_region *region, char *path)
 	return 0;
 }
 
+static enum ndctl_persistence_domain region_get_pd_type(char *name)
+{
+	if (strncmp("cpu_cache", name, 9) == 0)
+		return PERSISTENCE_CPU_CACHE;
+	else if (strncmp("memory_controller", name, 17) == 0)
+		return PERSISTENCE_MEM_CTRL;
+	else
+		return PERSISTENCE_UNKNOWN;
+}
+
+static int region_persistence_scan(struct ndctl_region *region)
+{
+	struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
+	char *pd_path;
+	char buf[SYSFS_ATTR_SIZE], *attrib;
+	int rc = 0;
+	enum ndctl_persistence_domain pd = PERSISTENCE_NONE;
+
+	region->persistence_domain = PERSISTENCE_NONE;
+	if (asprintf(&pd_path, "%s/persistence_domain",
+				region->region_path) < 0) {
+		rc = -errno;
+		err(ctx, "region persist domain path allocation failure\n");
+		return rc;
+	}
+
+	if (sysfs_read_attr(ctx, pd_path, buf) < 0) {
+		region->persistence_domain = PERSISTENCE_UNKNOWN;
+		free(pd_path);
+		return -ENXIO;
+	}
+
+	attrib = strtok(buf, " ");
+	/* empty string */
+	if (!attrib)
+		goto out;
+
+	pd = region_get_pd_type(attrib);
+	if (region->persistence_domain < pd)
+		region->persistence_domain = pd;
+
+	do {
+		attrib = strtok(NULL, " ");
+		if (!attrib)
+			break;
+		pd = region_get_pd_type(attrib);
+		if (region->persistence_domain < pd)
+			region->persistence_domain = pd;
+	} while (attrib);
+
+out:
+	free(pd_path);
+	return 0;
+}
+
 static void *add_region(void *parent, int id, const char *region_base)
 {
 	char buf[SYSFS_ATTR_SIZE];
@@ -1831,6 +1903,12 @@ static void *add_region(void *parent, int id, const char *region_base)
 	list_add(&bus->regions, &region->list);
 
 	free(path);
+
+	/* get the persistence domain attribs */
+	if (region_persistence_scan(region) < 0)
+		err(ctx, "%s: region persistence scan failed\n",
+				ndctl_region_get_devname(region));
+
 	return region;
 
  err_read:
@@ -2093,6 +2171,12 @@ NDCTL_EXPORT struct badblock *ndctl_region_get_first_badblock(struct ndctl_regio
 	return ndctl_region_get_next_badblock(region);
 }
 
+NDCTL_EXPORT enum ndctl_persistence_domain
+ndctl_region_get_persistence_domain(struct ndctl_region *region)
+{
+	return region->persistence_domain;
+}
+
 static struct nd_cmd_vendor_tail *to_vendor_tail(struct ndctl_cmd *cmd)
 {
 	struct nd_cmd_vendor_tail *tail = (struct nd_cmd_vendor_tail *)
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 21276614..3209aefe 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -350,4 +350,6 @@ global:
 	ndctl_dimm_cmd_new_ack_shutdown_count;
 	ndctl_region_get_numa_node;
 	ndctl_dimm_fw_update_supported;
+	ndctl_region_get_persistence_domain;
+	ndctl_bus_get_persistence_domain;
 } LIBNDCTL_14;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index f3a27411..cf6a77fd 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -18,6 +18,7 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <errno.h>
+#include <limits.h>
 
 #ifdef HAVE_LIBUUID
 #include <uuid/uuid.h>
@@ -115,6 +116,8 @@ int ndctl_bus_is_cmd_supported(struct ndctl_bus *bus, int cmd);
 unsigned int ndctl_bus_get_revision(struct ndctl_bus *bus);
 unsigned int ndctl_bus_get_id(struct ndctl_bus *bus);
 const char *ndctl_bus_get_provider(struct ndctl_bus *bus);
+enum ndctl_persistence_domain ndctl_bus_get_persistence_domain(
+		struct ndctl_bus *bus);
 int ndctl_bus_wait_probe(struct ndctl_bus *bus);
 int ndctl_bus_wait_for_scrub_completion(struct ndctl_bus *bus);
 unsigned int ndctl_bus_get_scrub_count(struct ndctl_bus *bus);
@@ -305,6 +308,14 @@ struct badblock {
 	unsigned long long offset;
 	unsigned int len;
 };
+
+enum ndctl_persistence_domain {
+	PERSISTENCE_NONE = 0,
+	PERSISTENCE_MEM_CTRL = 10,
+	PERSISTENCE_CPU_CACHE = 20,
+	PERSISTENCE_UNKNOWN = INT_MAX,
+};
+
 struct ndctl_region;
 struct ndctl_region *ndctl_region_get_first(struct ndctl_bus *bus);
 struct ndctl_region *ndctl_region_get_next(struct ndctl_region *region);
@@ -347,6 +358,8 @@ struct ndctl_region *ndctl_bus_get_region_by_physical_address(struct ndctl_bus *
         for (dimm = ndctl_region_get_first_dimm(region); \
              dimm != NULL; \
              dimm = ndctl_region_get_next_dimm(region, dimm))
+enum ndctl_persistence_domain ndctl_region_get_persistence_domain(
+		struct ndctl_region *region);
 int ndctl_region_is_enabled(struct ndctl_region *region);
 int ndctl_region_enable(struct ndctl_region *region);
 int ndctl_region_disable_invalidate(struct ndctl_region *region);
diff --git a/ndctl/list.c b/ndctl/list.c
index fe8036ea..6cf7c393 100644
--- a/ndctl/list.c
+++ b/ndctl/list.c
@@ -73,6 +73,7 @@ static struct json_object *region_to_json(struct ndctl_region *region,
 	struct ndctl_interleave_set *iset;
 	struct ndctl_mapping *mapping;
 	unsigned int bb_count = 0;
+	enum ndctl_persistence_domain pd;
 	int numa;
 
 	if (!jregion)
@@ -174,6 +175,25 @@ static struct json_object *region_to_json(struct ndctl_region *region,
 	if ((flags & UTIL_JSON_MEDIA_ERRORS) && jbbs)
 		json_object_object_add(jregion, "badblocks", jbbs);
 
+	pd = ndctl_region_get_persistence_domain(region);
+	switch (pd) {
+	case PERSISTENCE_CPU_CACHE:
+		jobj = json_object_new_string("cpu_cache");
+		break;
+	case PERSISTENCE_MEM_CTRL:
+		jobj = json_object_new_string("memory_controller");
+		break;
+	case PERSISTENCE_NONE:
+		jobj = json_object_new_string("none");
+		break;
+	default:
+		jobj = json_object_new_string("unknown");
+		break;
+	}
+
+	if (jobj)
+		json_object_object_add(jregion, "persistence_domain", jobj);
+
 	return jregion;
  err:
 	fail("\n");
