diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index a165e697..8f4e1745 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 persistence_domain;
 };
 
 /**
@@ -755,6 +756,7 @@ static void *add_bus(void *parent, int id, const char *ctl_base)
 	list_head_init(&bus->regions);
 	bus->ctx = ctx;
 	bus->id = id;
+	bus->persistence_domain = PERSISTENCE_UNKNOWN;
 
 	sprintf(path, "%s/dev", ctl_base);
 	if (sysfs_read_attr(ctx, path, buf) < 0
@@ -916,6 +918,17 @@ NDCTL_EXPORT struct ndctl_bus *ndctl_bus_get_by_provider(struct ndctl_ctx *ctx,
 	return NULL;
 }
 
+NDCTL_EXPORT unsigned int
+ndctl_bus_get_persistence_domain(struct ndctl_bus *bus)
+{
+	struct ndctl_region *region;
+
+	/* iterate through region to get the region persistence domain */
+	ndctl_region_foreach(bus, region) {}
+
+	return bus->persistence_domain;
+}
+
 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 +1768,62 @@ static int region_set_type(struct ndctl_region *region, char *path)
 	return 0;
 }
 
+static enum ndctl_persistence 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;
+	FILE *pf;
+	char buf[64];
+	int rc = 0;
+	enum ndctl_persistence pd = 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;
+	}
+
+	pf = fopen(pd_path, "re");
+	if (!pf) {
+		rc = -errno;
+		free(pd_path);
+		return rc;
+	}
+
+	region->persistence_domain = PERSISTENCE_NONE;
+	do {
+		rc = fscanf(pf, "%s", buf);
+		if (rc == EOF) {
+			if (ferror(pf)) {
+				rc = -errno;
+				goto out;
+			}
+		} else if (rc == 1)
+			pd = region_get_pd_type(buf);
+
+		if (region->persistence_domain < pd)
+			region->persistence_domain = pd;
+	} while (rc != EOF);
+
+	rc = 0;
+
+out:
+	fclose(pf);
+	free(pd_path);
+	return rc;
+}
+
 static void *add_region(void *parent, int id, const char *region_base)
 {
 	char buf[SYSFS_ATTR_SIZE];
@@ -1762,6 +1831,7 @@ static void *add_region(void *parent, int id, const char *region_base)
 	struct ndctl_bus *bus = parent;
 	struct ndctl_ctx *ctx = bus->ctx;
 	char *path = calloc(1, strlen(region_base) + 100);
+	int rc;
 
 	if (!path)
 		return NULL;
@@ -1831,6 +1901,17 @@ 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 */
+	rc = region_persistence_scan(region);
+	if (rc < 0)
+		err(ctx, "%s: region persistence scan failed\n",
+				ndctl_region_get_devname(region));
+
+	/* we are looking for the least persistence domain */
+	if (region->bus->persistence_domain > region->persistence_domain)
+		region->bus->persistence_domain = region->persistence_domain;
+
 	return region;
 
  err_read:
@@ -2093,6 +2174,12 @@ NDCTL_EXPORT struct badblock *ndctl_region_get_first_badblock(struct ndctl_regio
 	return ndctl_region_get_next_badblock(region);
 }
 
+NDCTL_EXPORT unsigned int
+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/lib/private.h b/ndctl/lib/private.h
index 1cad06b7..e7787ce8 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -171,6 +171,7 @@ struct ndctl_bus {
 	char *scrub_path;
 	unsigned long cmd_mask;
 	unsigned long nfit_dsm_mask;
+	enum ndctl_persistence persistence_domain;
 };
 
 /**
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index f3a27411..151d48f0 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -115,6 +115,7 @@ 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);
+unsigned int 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 +306,14 @@ struct badblock {
 	unsigned long long offset;
 	unsigned int len;
 };
+
+enum ndctl_persistence {
+	PERSISTENCE_NONE = 0,
+	PERSISTENCE_MEM_CTRL,
+	PERSISTENCE_CPU_CACHE,
+	PERSISTENCE_UNKNOWN,
+};
+
 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 +356,7 @@ 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))
+unsigned int 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 0ca5b6de..f3701ea9 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 pd;
 	int numa;
 
 	if (!jregion)
@@ -174,6 +175,21 @@ 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;
+		default:
+			jobj = NULL;
+	}
+
+	if (jobj)
+		json_object_object_add(jregion, "persistence_domain", jobj);
+
 	return jregion;
  err:
 	fail("\n");
