diff --git a/Documentation/cxl/cxl-get-alert-config.txt b/Documentation/cxl/cxl-get-alert-config.txt
new file mode 100644
index 0000000..edebd74
--- /dev/null
+++ b/Documentation/cxl/cxl-get-alert-config.txt
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+
+cxl-get-alert-config(1)
+=======================
+
+NAME
+----
+cxl-get-alert-config - Get Alert Configuration
+
+SYNOPSIS
+--------
+[verse]
+'cxl get-alert-config' <mem0> [<mem1>..<memN>] [<options>]
+
+This command retrieves the device's critical alert and programmable warning
+configuration. In the multi-memdev case the data is concatenated.
+
+OPTIONS
+-------
+-o::
+--output::
+	output file
+
+include::../copyright.txt[]
+
+SEE ALSO
+--------
+CXL-3.0 8.2.9.8.3.2
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
index fd2962a..fd054be 100644
--- a/Documentation/cxl/lib/libcxl.txt
+++ b/Documentation/cxl/lib/libcxl.txt
@@ -125,6 +125,7 @@ struct cxl_cmd *cxl_cmd_new_read_label(struct cxl_memdev *memdev,
 					unsigned int offset, unsigned int length);
 struct cxl_cmd *cxl_cmd_new_write_label(struct cxl_memdev *memdev, void *buf,
 					unsigned int offset, unsigned int length);
+int cxl_memdev_get_alert_config(struct cxl_memdev *memdev);
 int cxl_memdev_zero_label(struct cxl_memdev *memdev, size_t length,
 			  size_t offset);
 int cxl_memdev_read_label(struct cxl_memdev *memdev, void *buf, size_t length,
diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build
index 147ea71..d284eb9 100644
--- a/Documentation/cxl/meson.build
+++ b/Documentation/cxl/meson.build
@@ -41,6 +41,7 @@ cxl_manpages = [
   'cxl-set-partition.txt',
   'cxl-reserve-dpa.txt',
   'cxl-free-dpa.txt',
+  'cxl-get-alert-config.txt',
   'cxl-create-region.txt',
   'cxl-disable-region.txt',
   'cxl-enable-region.txt',
diff --git a/cxl/builtin.h b/cxl/builtin.h
index b28c221..0ca3c4b 100644
--- a/cxl/builtin.h
+++ b/cxl/builtin.h
@@ -10,6 +10,7 @@ int cmd_read_labels(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_init_labels(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_check_labels(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_alert_config(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_disable_memdev(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_reserve_dpa(int argc, const char **argv, struct cxl_ctx *ctx);
diff --git a/cxl/cxl.c b/cxl/cxl.c
index dd1be7a..5c120c7 100644
--- a/cxl/cxl.c
+++ b/cxl/cxl.c
@@ -64,6 +64,7 @@ static struct cmd_struct commands[] = {
 	{ "zero-labels", .c_fn = cmd_zero_labels },
 	{ "read-labels", .c_fn = cmd_read_labels },
 	{ "write-labels", .c_fn = cmd_write_labels },
+	{ "get-alert-config", .c_fn = cmd_get_alert_config },
 	{ "disable-memdev", .c_fn = cmd_disable_memdev },
 	{ "enable-memdev", .c_fn = cmd_enable_memdev },
 	{ "reserve-dpa", .c_fn = cmd_reserve_dpa },
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
index e8c5d44..1db5b2c 100644
--- a/cxl/lib/libcxl.c
+++ b/cxl/lib/libcxl.c
@@ -3140,6 +3140,82 @@ do {									\
 	return !!(c->field & mask);					\
 } while(0)
 
+struct cxl_mbox_get_alert_config_out {
+	u8 valid_alerts;
+	u8 programmable_alerts;
+	u8 life_used_critical_alert_threshold;
+	u8 life_used_prog_warn_threshold;
+	__le16 dev_over_temp_crit_alert_threshold;
+	__le16 dev_under_temp_crit_alert_threshold;
+	__le16 dev_over_temp_prog_warn_threshold;
+	__le16 dev_under_temp_prog_warn_threshold;
+	__le16 corr_vol_mem_err_prog_warn_thresold;
+	__le16 corr_pers_mem_err_prog_warn_threshold;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_get_alert_config(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mbox_get_alert_config_out *alert_config_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_GET_ALERT_CONFIG);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	rc = cxl_cmd_submit(cmd);
+	if (rc < 0) {
+		fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+				cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+		goto out;
+	}
+
+	rc = cxl_cmd_get_mbox_status(cmd);
+	if (rc != 0) {
+		fprintf(stderr, "%s: firmware status: %d\n",
+				cxl_memdev_get_devname(memdev), rc);
+		rc = -ENXIO;
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_ALERT_CONFIG) {
+		fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+				cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_GET_ALERT_CONFIG);
+		return -EINVAL;
+	}
+
+	fprintf(stdout, "alert_config summary\n");
+
+	alert_config_out = (void *)cmd->send_cmd->out.payload;
+
+	fprintf(stdout, "    valid_alerts: 0x%x\n", alert_config_out->valid_alerts);
+	fprintf(stdout, "    programmable_alerts: 0x%x\n", alert_config_out->programmable_alerts);
+	fprintf(stdout, "    life_used_critical_alert_threshold: 0x%x\n",
+		alert_config_out->life_used_critical_alert_threshold);
+	fprintf(stdout, "    life_used_prog_warn_threshold: 0x%x\n",
+		alert_config_out->life_used_prog_warn_threshold);
+
+	fprintf(stdout, "    dev_over_temp_crit_alert_threshold: 0x%x\n",
+		le16_to_cpu(alert_config_out->dev_over_temp_crit_alert_threshold));
+	fprintf(stdout, "    dev_under_temp_crit_alert_threshold: 0x%x\n",
+		le16_to_cpu(alert_config_out->dev_under_temp_crit_alert_threshold));
+	fprintf(stdout, "    dev_over_temp_prog_warn_threshold: 0x%x\n",
+		le16_to_cpu(alert_config_out->dev_over_temp_prog_warn_threshold));
+	fprintf(stdout, "    dev_under_temp_prog_warn_threshold: 0x%x\n",
+		le16_to_cpu(alert_config_out->dev_under_temp_prog_warn_threshold));
+	fprintf(stdout, "    corr_vol_mem_err_prog_warn_thresold: 0x%x\n",
+		le16_to_cpu(alert_config_out->corr_vol_mem_err_prog_warn_thresold));
+	fprintf(stdout, "    corr_pers_mem_err_prog_warn_threshold: 0x%x\n",
+		le16_to_cpu(alert_config_out->corr_pers_mem_err_prog_warn_threshold));
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
 CXL_EXPORT struct cxl_cmd *cxl_cmd_new_get_health_info(
 		struct cxl_memdev *memdev)
 {
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
index 8bb91e0..c6dd658 100644
--- a/cxl/lib/libcxl.sym
+++ b/cxl/lib/libcxl.sym
@@ -20,6 +20,7 @@ global:
 	cxl_memdev_get_pmem_size;
 	cxl_memdev_get_ram_size;
 	cxl_memdev_get_firmware_verison;
+	cxl_memdev_get_alert_config;
 	cxl_cmd_get_devname;
 	cxl_cmd_new_raw;
 	cxl_cmd_set_input_payload;
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
index 9fe4e99..e0b9418 100644
--- a/cxl/libcxl.h
+++ b/cxl/libcxl.h
@@ -60,6 +60,7 @@ int cxl_memdev_read_label(struct cxl_memdev *memdev, void *buf, size_t length,
 		size_t offset);
 int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length,
 		size_t offset);
+int cxl_memdev_get_alert_config(struct cxl_memdev *memdev);
 
 #define cxl_memdev_foreach(ctx, memdev) \
         for (memdev = cxl_memdev_get_first(ctx); \
diff --git a/cxl/memdev.c b/cxl/memdev.c
index 0b3ad02..5d8cf6c 100644
--- a/cxl/memdev.c
+++ b/cxl/memdev.c
@@ -371,6 +371,16 @@ static int action_enable(struct cxl_memdev *memdev, struct action_context *actx)
 	return cxl_memdev_enable(memdev);
 }
 
+static const struct option cmd_get_alert_config_options[] = {
+	BASE_OPTIONS(),
+	OPT_END(),
+};
+
+static int action_cmd_get_alert_config(struct cxl_memdev *memdev, struct action_context *actx)
+{
+	return cxl_memdev_get_alert_config(memdev);
+}
+
 static int action_zero(struct cxl_memdev *memdev, struct action_context *actx)
 {
 	size_t size;
@@ -809,6 +819,14 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
 	return rc;
 }
 
+int cmd_get_alert_config(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+	int rc = memdev_action(argc, argv, ctx, action_cmd_get_alert_config, cmd_get_alert_config_options,
+			"cxl get-alert-config <mem0> [<mem1>..<memN>] [<options>]");
+
+	return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
 int cmd_write_labels(int argc, const char **argv, struct cxl_ctx *ctx)
 {
 	int count = memdev_action(argc, argv, ctx, action_write, write_options,
