diff --git a/doc/device-tree/ibm,opal/power-mgt/self-restore.rst b/doc/device-tree/ibm,opal/power-mgt/self-restore.rst
new file mode 100644
index 00000000..2a2269f7
--- /dev/null
+++ b/doc/device-tree/ibm,opal/power-mgt/self-restore.rst
@@ -0,0 +1,27 @@
+ibm,opal/power-mgt/self-restore device tree entries
+===================================================
+
+This node exports the bitmask representing the special purpose registers that
+the self-restore API currently supports.
+
+Example:
+
+.. code-block:: dts
+
+  self-restore {
+        sprn-bitmask = <0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x42010000 0x0 0x0
+                        0x20000 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
+                        0x0 0x0 0x100000 0x900000 0x0 0x0 0x530000 0x0 0x0 0x0
+                        0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
+                        0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
+                        0x0 0x10000>;
+        phandle = <0x1c7>;
+  };
+
+sprn-bitmask
+------------
+
+This property is a bitmask of of all the existing SPRs and if the SPR is
+supported, the corresponding bit of the SPR number is set to 1.
+The representation of the bits are left-right, i.e the MSB of the first
+doubleword represants the 0th bit.
diff --git a/doc/device-tree/ibm,opal/power-mgt/self-save.rst b/doc/device-tree/ibm,opal/power-mgt/self-save.rst
new file mode 100644
index 00000000..c367720e
--- /dev/null
+++ b/doc/device-tree/ibm,opal/power-mgt/self-save.rst
@@ -0,0 +1,27 @@
+ibm,opal/power-mgt/self-save device tree entries
+===================================================
+
+This node exports the bitmask representing the special purpose registers that
+the self-save API currently supports.
+
+Example:
+
+.. code-block:: dts
+
+  self-save {
+        sprn-bitmask = <0x0 0x0 0x0 0x0 0x100000 0x0 0x0 0x0 0x42010000 0x0 0x0
+                        0x20000 0x0 0x0 0x0 0x10000 0x0 0x0 0x0 0x0 0x0 0x0 0x0
+                        0x0 0x0 0x0 0x100000 0x840000 0x0 0x0 0x0 0x0 0x0 0x0
+                        0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
+                        0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
+                        0x0 0x10000>;
+        phandle = <0x1c8>;
+  };
+
+sprn-bitmask
+------------
+
+This property is a bitmask of of all the existing SPRs and if the SPR is
+supported, the corresponding bit of the SPR number is set to 1.
+The representation of the bits are left-right, i.e the MSB of the first
+doubleword represants the 0th bit.
diff --git a/hw/slw.c b/hw/slw.c
index 9751c04f..fb14bd0c 100644
--- a/hw/slw.c
+++ b/hw/slw.c
@@ -29,6 +29,7 @@
 #include <sbe_xip_image.h>
 
 static uint32_t slw_saved_reset[0x100];
+#define SPR_BITMAP_LENGTH	2048
 
 static bool slw_current_le = false;
 
@@ -750,6 +751,121 @@ static void slw_late_init_p9(struct proc_chip *chip)
 	}
 }
 
+/* Add device tree properties to determine self-save | restore */
+void add_cpu_self_save_restore_properties(void)
+{
+	struct dt_node *self_restore, *self_save, *power_mgt;
+	uint64_t *self_save_mask, *self_restore_mask;
+	bool self_save_supported = true;
+	uint64_t compVector = -1;
+	struct proc_chip *chip;
+	int i, rc;
+
+	const uint64_t self_restore_regs[] = {
+		P8_SPR_HRMOR,
+		P8_SPR_HMEER,
+		P8_SPR_PMICR,
+		P8_SPR_PMCR,
+		P8_SPR_HID0,
+		P8_SPR_HID1,
+		P8_SPR_HID4,
+		P8_SPR_HID5,
+		P8_SPR_HSPRG0,
+		P8_SPR_LPCR,
+		P8_MSR_MSR
+	};
+
+	const uint64_t self_save_regs[] = {
+		P9_STOP_SPR_DAWR,
+		P9_STOP_SPR_HSPRG0,
+		P9_STOP_SPR_LDBAR,
+		P9_STOP_SPR_LPCR,
+		P9_STOP_SPR_PSSCR,
+		P9_STOP_SPR_MSR,
+		P9_STOP_SPR_HRMOR,
+		P9_STOP_SPR_HMEER,
+		P9_STOP_SPR_PMCR,
+		P9_STOP_SPR_PTCR
+	};
+
+	chip = next_chip(NULL);
+	assert(chip);
+	rc = proc_stop_api_discover_capability((void *) chip->homer_base,
+					       &compVector);
+	if (rc == STOP_SAVE_ARG_INVALID_IMG) {
+		prlog(PR_DEBUG, "HOMER BASE INVALID\n");
+		return;
+	} else if (rc == STOP_SAVE_API_IMG_INCOMPATIBLE) {
+		prlog(PR_DEBUG, "STOP API running incompatible versions\n");
+		if ((compVector & SELF_RESTORE_VER_MISMATCH) == 0) {
+			prlog(PR_DEBUG, "Self-save API unsupported\n");
+			self_save_supported = false;
+		}
+	}
+
+	power_mgt = dt_find_by_path(dt_root, "/ibm,opal/power-mgt");
+	if (!power_mgt) {
+		prerror("SLW: dt node /ibm,opal/power-mgt not found\n");
+		return;
+	}
+
+	self_restore = dt_new(power_mgt, "self-restore");
+	if (!self_restore) {
+		prerror("SLW: Failed to create self restore node");
+		return;
+	}
+
+	self_restore_mask = zalloc(SPR_BITMAP_LENGTH / 8);
+	if (!self_restore_mask)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(self_restore_regs); i++) {
+		int bitmask_idx = self_restore_regs[i] / 64;
+		uint64_t bitmask_pos = self_restore_regs[i] % 64;
+		self_restore_mask[bitmask_idx] |= 1ul << bitmask_pos;
+	}
+
+	for (i = 0; i < (SPR_BITMAP_LENGTH / 64); i++) {
+		self_restore_mask[i] = cpu_to_be64(self_restore_mask[i]);
+	}
+
+	dt_add_property(self_restore, "sprn-bitmask", self_restore_mask,
+			SPR_BITMAP_LENGTH / 8);
+	dt_add_property_string(self_restore, "compatible",
+			       "ibm,opal-self-restore");
+	free(self_restore_mask);
+
+	if (proc_gen != proc_gen_p9 || !self_save_supported) {
+		prlog(PR_INFO, "SLW: self-save not supported on this platform");
+		return;
+	}
+
+	self_save = dt_new(power_mgt, "self-save");
+	if (!self_save) {
+		prerror("SLW: Failed to create self save node");
+		return;
+	}
+
+	self_save_mask = zalloc(SPR_BITMAP_LENGTH / 8);
+	if (!self_save_mask)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(self_save_regs); i++) {
+		int bitmask_idx = self_save_regs[i] / 64;
+		uint64_t bitmask_pos = self_save_regs[i] % 64;
+		self_save_mask[bitmask_idx] |= 1ul << bitmask_pos;
+	}
+
+	for (i = 0; i < (SPR_BITMAP_LENGTH / 64); i++) {
+		self_save_mask[i] = cpu_to_be64(self_save_mask[i]);
+	}
+
+	dt_add_property(self_save, "sprn-bitmask", self_save_mask,
+			SPR_BITMAP_LENGTH / 8);
+	dt_add_property_string(self_save, "compatible", "ibm,opal-self-save");
+	free(self_save_mask);
+}
+
 /* Add device tree properties to describe idle states */
 void add_cpu_idle_state_properties(void)
 {
@@ -1563,4 +1679,6 @@ void slw_init(void)
 		}
 	}
 	add_cpu_idle_state_properties();
+	if (has_deep_states)
+		add_cpu_self_save_restore_properties();
 }
diff --git a/include/skiboot.h b/include/skiboot.h
index 9ced240e..d3631dea 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -209,6 +209,7 @@ extern void early_uart_init(void);
 extern void homer_init(void);
 extern void slw_init(void);
 extern void add_cpu_idle_state_properties(void);
+extern void add_cpu_self_save_restore_properties(void);
 extern void lpc_rtc_init(void);
 
 /* flash support */
