anitazha / rpms / ndctl

Forked from rpms/ndctl 2 years ago
Clone
Blob Blame History Raw
diff --git a/cligen/gen/base.cxl.c b/cligen/gen/base.cxl.c
index ee2d6b0..2ef95d1 100644
--- a/cligen/gen/base.cxl.c
+++ b/cligen/gen/base.cxl.c
@@ -69,7 +69,7 @@ static struct cmd_struct commands[] = {
 	{ "write-labels", .c_fn = cmd_write_labels },
 	{ "id-cmd", .c_fn = cmd_identify },
 	{ "get-supported-logs", .c_fn = cmd_get_supported_logs },
-	{ "get-cel-log", .c_fn = cmd_get_cel_log },
+	{ "get-log", .c_fn = cmd_get_log },
 	{ "get-event-interrupt-policy", .c_fn = cmd_get_event_interrupt_policy },
 	{ "set-event-interrupt-policy", .c_fn = cmd_set_event_interrupt_policy },
 	{ "get-timestamp", .c_fn = cmd_get_timestamp },
diff --git a/cligen/gen/base.memdev.c b/cligen/gen/base.memdev.c
index 56c3ebd..c5ec60e 100644
--- a/cligen/gen/base.memdev.c
+++ b/cligen/gen/base.memdev.c
@@ -668,10 +668,10 @@ int cmd_get_supported_logs(int argc, const char **argv, struct cxl_ctx *ctx)
 	return rc >= 0 ? 0 : EXIT_FAILURE;
 }
 
-int cmd_get_cel_log(int argc, const char **argv, struct cxl_ctx *ctx)
+int cmd_get_log(int argc, const char **argv, struct cxl_ctx *ctx)
 {
-	int rc = memdev_action(argc, argv, ctx, action_cmd_get_cel_log, cmd_get_cel_log_options,
-			"cxl get-cel-log <mem0> [<mem1>..<memN>] [<options>]");
+	int rc = memdev_action(argc, argv, ctx, action_cmd_get_log, cmd_get_log_options,
+			"cxl get-log <mem0> [<mem1>..<memN>] [<options>]");
 
 	return rc >= 0 ? 0 : EXIT_FAILURE;
 }
diff --git a/cxl/builtin.h b/cxl/builtin.h
index 5775f4a..e66d027 100644
--- a/cxl/builtin.h
+++ b/cxl/builtin.h
@@ -17,7 +17,7 @@ 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_identify(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_get_supported_logs(int argc, const char **argv, struct cxl_ctx *ctx);
-int cmd_get_cel_log(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_log(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_get_event_interrupt_policy(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_set_event_interrupt_policy(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_get_timestamp(int argc, const char **argv, struct cxl_ctx *ctx);
@@ -116,4 +116,44 @@ int cmd_osa_data_read(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_dimm_spd_read(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_ddr_training_status(int argc, const char **argv, struct cxl_ctx *ctx);
 int cmd_dimm_slot_info(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_pmic_vtmon_info(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_margin_run(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_margin_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_margin_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_stats_run(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_stats_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_reboot_mode_set(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_curr_cxl_boot_mode_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_pcie_eye_run(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_pcie_eye_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_pcie_eye_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_cxl_link_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_device_info(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_read_ddr_temp(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_cxl_hpa_to_dpa(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_cxl_membridge_errors(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_ddr_bw(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_ddr_latency(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_i2c_read(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_i2c_write(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_ddr_ecc_err_info(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_start_ddr_ecc_scrub(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_ecc_scrub_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_cont_scrub_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_cont_scrub_set(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_init_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_cxl_membridge_stats(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_trigger_coredump(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_err_inj_en(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_dimm_level_training_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_param_set(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_param_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_core_volt_set(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_core_volt_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_oem_err_inj_viral(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_err_inj_ll_poison(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_pci_err_inj(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_read_ltssm_states(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_page_select_set(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_page_select_get(int argc, const char **argv, struct cxl_ctx *ctx);
 #endif /* _CXL_BUILTIN_H_ */
diff --git a/cxl/cxl.c b/cxl/cxl.c
index 4b430b5..c44bb75 100644
--- a/cxl/cxl.c
+++ b/cxl/cxl.c
@@ -73,7 +73,7 @@ static struct cmd_struct commands[] = {
 	{ "write-labels", .c_fn = cmd_write_labels },
 	{ "id-cmd", .c_fn = cmd_identify },
 	{ "get-supported-logs", .c_fn = cmd_get_supported_logs },
-	{ "get-cel-log", .c_fn = cmd_get_cel_log },
+	{ "get-log", .c_fn = cmd_get_log },
 	{ "get-event-interrupt-policy", .c_fn = cmd_get_event_interrupt_policy },
 	{ "set-event-interrupt-policy", .c_fn = cmd_set_event_interrupt_policy },
 	{ "get-timestamp", .c_fn = cmd_get_timestamp },
@@ -172,6 +172,46 @@ static struct cmd_struct commands[] = {
 	{ "dimm-spd-read", .c_fn = cmd_dimm_spd_read },
 	{ "ddr-training-status", .c_fn = cmd_ddr_training_status },
 	{ "dimm-slot-info", .c_fn = cmd_dimm_slot_info },
+	{ "pmic-vtmon-info", .c_fn = cmd_pmic_vtmon_info },
+	{ "ddr-margin-run", .c_fn = cmd_ddr_margin_run },
+	{ "ddr-margin-status", .c_fn = cmd_ddr_margin_status },
+	{ "ddr-margin-get", .c_fn = cmd_ddr_margin_get },
+	{ "ddr-stats-run", .c_fn = cmd_ddr_stats_run },
+	{ "ddr-stats-get", .c_fn = cmd_ddr_stats_get },
+	{ "reboot-mode-set", .c_fn = cmd_reboot_mode_set },
+	{ "curr-cxl-boot-mode-get", .c_fn = cmd_curr_cxl_boot_mode_get },
+	{ "pcie-eye-run", .c_fn = cmd_pcie_eye_run },
+	{ "pcie-eye-status", .c_fn = cmd_pcie_eye_status },
+	{ "pcie-eye-get", .c_fn = cmd_pcie_eye_get },
+	{ "get-cxl-link-status", .c_fn = cmd_get_cxl_link_status },
+	{ "get-device-info", .c_fn = cmd_get_device_info },
+	{ "read-ddr-temp", .c_fn = cmd_read_ddr_temp },
+	{ "cxl-hpa-to-dpa", .c_fn = cmd_cxl_hpa_to_dpa },
+	{ "get-cxl-membridge-errors", .c_fn = cmd_get_cxl_membridge_errors },
+	{ "get-ddr-bw", .c_fn = cmd_get_ddr_bw },
+	{ "get-ddr-latency", .c_fn = cmd_get_ddr_latency },
+	{ "i2c-read", .c_fn = cmd_i2c_read },
+	{ "i2c-write", .c_fn = cmd_i2c_write },
+	{ "get-ddr-ecc-err-info", .c_fn = cmd_get_ddr_ecc_err_info },
+	{ "start-ddr-ecc-scrub", .c_fn = cmd_start_ddr_ecc_scrub },
+	{ "ddr-ecc-scrub-status", .c_fn = cmd_ddr_ecc_scrub_status },
+	{ "ddr-cont-scrub-status", .c_fn = cmd_ddr_cont_scrub_status },
+	{ "ddr-cont-scrub-set", .c_fn = cmd_ddr_cont_scrub_set },
+	{ "ddr-init-status", .c_fn = cmd_ddr_init_status },
+	{ "get-cxl-membridge-stats", .c_fn = cmd_get_cxl_membridge_stats },
+	{ "trigger-coredump", .c_fn = cmd_trigger_coredump },
+	{ "ddr-err-inj-en", .c_fn = cmd_ddr_err_inj_en },
+	{ "ddr-dimm-level-training-status", .c_fn = cmd_ddr_dimm_level_training_status },
+	{ "ddr-param-set", .c_fn = cmd_ddr_param_set },
+	{ "ddr-param-get", .c_fn = cmd_ddr_param_get },
+	{ "core-volt-set", .c_fn = cmd_core_volt_set },
+	{ "core-volt-get", .c_fn = cmd_core_volt_get },
+	{ "oem-err-inj-viral", .c_fn = cmd_oem_err_inj_viral },
+	{ "err-inj-ll-poison", .c_fn = cmd_err_inj_ll_poison },
+	{ "pci-err-inj", .c_fn = cmd_pci_err_inj },
+	{ "read-ltssm-states", .c_fn = cmd_read_ltssm_states },
+	{ "ddr-page-select-set", .c_fn = cmd_ddr_page_select_set },
+	{ "ddr-page-select-get", .c_fn = cmd_ddr_page_select_get },
 };
 
 int main(int argc, const char **argv)
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
index ba265ed..6fcb20e 100644
--- a/cxl/lib/libcxl.c
+++ b/cxl/lib/libcxl.c
@@ -1471,6 +1471,7 @@ out:
 }
 
 #define CEL_UUID "0da9c0b5-bf41-4b78-8f79-96b1623b3f17"
+#define VENDOR_LOG_UUID "5e1819d9-11a9-400c-811f-d60719403d86"
 
 struct cxl_mbox_get_log {
 	uuid_t uuid;
@@ -1483,13 +1484,15 @@ struct cel_entry {
 	__le16 effect;
 } __attribute__((packed));
 
-CXL_EXPORT int cxl_memdev_get_cel_log(struct cxl_memdev *memdev, const char* uuid)
+CXL_EXPORT int cxl_memdev_get_log(struct cxl_memdev *memdev, const char* uuid, const unsigned int data_size)
 {
 	struct cxl_cmd *cmd;
 	struct cxl_mbox_get_log *get_log_input;
 	struct cel_entry *cel_entries;
 	int no_cel_entries;
 	int rc = 0;
+	int remaining_bytes = data_size;
+	unsigned int bytes_read = 0;
 
 	if (!uuid) {
 		fprintf(stderr, "%s: Please specify log uuid argument\n",
@@ -1497,49 +1500,63 @@ CXL_EXPORT int cxl_memdev_get_cel_log(struct cxl_memdev *memdev, const char* uui
 		return -EINVAL;
 	}
 
-	cmd = cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_GET_LOG);
-	if (!cmd) {
-		fprintf(stderr, "%s: cxl_memdev_get_cel_log returned Null output\n",
-				cxl_memdev_get_devname(memdev));
-		return -ENOMEM;
-	}
+	do {
+		cmd = cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_GET_LOG);
+		if (!cmd) {
+			fprintf(stderr, "%s: cxl_memdev_get_log returned Null output\n",
+					cxl_memdev_get_devname(memdev));
+			return -ENOMEM;
+		}
 
-	get_log_input = (void *) cmd->send_cmd->in.payload;
-	uuid_parse(uuid, get_log_input->uuid);
-	get_log_input->offset = 0;
-	get_log_input->length = cmd->memdev->payload_max;
+		get_log_input = (void *) cmd->send_cmd->in.payload;
+		uuid_parse(uuid, get_log_input->uuid);
+		get_log_input->offset = bytes_read;
+		get_log_input->length = cmd->memdev->payload_max;
+		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_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%s\n",
+					cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+			rc = -ENXIO;
+			goto out;
+		}
 
-	rc = cxl_cmd_get_mbox_status(cmd);
-	if (rc != 0) {
-		fprintf(stderr, "%s: firmware status: %d:\n%s\n",
-				cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
-		rc = -ENXIO;
-		goto out;
-	}
+		if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_LOG) {
+			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_LOG);
+			return -EINVAL;
+		}
 
-	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_LOG) {
-		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_LOG);
-		return -EINVAL;
-	}
+		fprintf(stdout, "payload info\n");
+		fprintf(stdout, "    out size: 0x%x\n", cmd->send_cmd->out.size);
+
+		if (!strcmp(uuid, CEL_UUID)) {
+			cel_entries = (void *)cmd->send_cmd->out.payload;
+			no_cel_entries = (cmd->send_cmd->out.size)/sizeof(struct cel_entry);
+			fprintf(stdout, "    no_cel_entries size: %d\n", no_cel_entries);
+			for (int e = 0; e < no_cel_entries; ++e) {
+				fprintf(stdout, "    cel_entry[%d] opcode: 0x%x, effect: 0x%x\n", e,
+						le16_to_cpu(cel_entries[e].opcode),
+						le16_to_cpu(cel_entries[e].effect));
+			}
+		} else if (!strcmp(uuid, VENDOR_LOG_UUID)) {
+			fprintf(stdout, " number of received bytes = %d\n", cmd->send_cmd->out.size);
+			fprintf(stdout, "%s", (char *)cmd->send_cmd->out.payload);
+		}
 
-	fprintf(stdout, "payload info\n");
-	fprintf(stdout, "    out size: 0x%x\n", cmd->send_cmd->out.size);
-	cel_entries = (void *)cmd->send_cmd->out.payload;
-	no_cel_entries = (cmd->send_cmd->out.size)/sizeof(struct cel_entry);
-	fprintf(stdout, "    no_cel_entries size: %d\n", no_cel_entries);
-	for (int e = 0; e < no_cel_entries; ++e) {
-		fprintf(stdout, "    cel_entry[%d] opcode: 0x%x, effect: 0x%x\n", e,
-				le16_to_cpu(cel_entries[e].opcode),
-				le16_to_cpu(cel_entries[e].effect));
-	}
+		/* keep getting the data in chunks of payload max */
+		bytes_read += cmd->send_cmd->out.size;
+		if (remaining_bytes >= cmd->send_cmd->out.size)
+			remaining_bytes -= cmd->send_cmd->out.size;
+		else
+			remaining_bytes = 0;
+	} while(remaining_bytes);
 out:
 	cxl_cmd_unref(cmd);
 	return rc;
@@ -2342,6 +2359,7 @@ out:
 
 #define CXL_MEM_COMMAND_ID_GET_FW_INFO CXL_MEM_COMMAND_ID_RAW
 #define CXL_MEM_COMMAND_ID_GET_FW_INFO_OPCODE 512
+#define CXL_MEM_COMMAND_ID_GET_OS_INFO_OPCODE 0xcd03
 #define CXL_MEM_COMMAND_ID_GET_FW_INFO_PAYLOAD_OUT_SIZE 80
 
 
@@ -2356,7 +2374,7 @@ struct cxl_mbox_get_fw_info_out {
 	char slot_4_fw_rev[16];
 }  __attribute__((packed));
 
-CXL_EXPORT int cxl_memdev_get_fw_info(struct cxl_memdev *memdev)
+CXL_EXPORT int cxl_memdev_get_fw_info(struct cxl_memdev *memdev, bool is_os_img)
 {
 	struct cxl_cmd *cmd;
 	struct cxl_mbox_get_fw_info_out *get_fw_info_out;
@@ -2365,8 +2383,19 @@ CXL_EXPORT int cxl_memdev_get_fw_info(struct cxl_memdev *memdev)
 	u8 active_slot;
 	u8 staged_slot_mask;
 	u8 staged_slot;
+	int opcode;
+	char *fw_name;
+
+	//select vendor cci command if os image is specified, else default to cxl FW_INFO command
+	if (is_os_img) {
+		opcode = CXL_MEM_COMMAND_ID_GET_OS_INFO_OPCODE;
+		fw_name = "OS";
+	} else {
+		opcode = CXL_MEM_COMMAND_ID_GET_FW_INFO_OPCODE;
+		fw_name = "FW";
+	}
 
-	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_FW_INFO_OPCODE);
+	cmd = cxl_cmd_new_raw(memdev, opcode);
 	if (!cmd) {
 		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
 				cxl_memdev_get_devname(memdev));
@@ -2401,17 +2430,17 @@ CXL_EXPORT int cxl_memdev_get_fw_info(struct cxl_memdev *memdev)
 	staged_slot = get_fw_info_out->fw_slot_info & staged_slot_mask;
 	staged_slot = staged_slot>>3;
 	fprintf(stdout, "================================= get fw info ==================================\n");
-	fprintf(stdout, "FW Slots Supported: %x\n", get_fw_info_out->fw_slots_supp);
-	fprintf(stdout, "Active FW Slot: %x\n", active_slot);
+	fprintf(stdout, "%s Slots Supported: %x\n", fw_name, get_fw_info_out->fw_slots_supp);
+	fprintf(stdout, "Active %s Slot: %x\n", fw_name, active_slot);
 	if (staged_slot)
 	{
-		fprintf(stdout, "Staged FW Slot: %x\n", staged_slot);
+		fprintf(stdout, "Staged %s Slot: %x\n", fw_name, staged_slot);
 	}
-	fprintf(stdout, "FW Activation Capabilities: %x\n", get_fw_info_out->fw_activation_capas);
-	fprintf(stdout, "Slot 1 FW Revision: %s\n", get_fw_info_out->slot_1_fw_rev);
-	fprintf(stdout, "Slot 2 FW Revision: %s\n", get_fw_info_out->slot_2_fw_rev);
-	fprintf(stdout, "Slot 3 FW Revision: %s\n", get_fw_info_out->slot_3_fw_rev);
-	fprintf(stdout, "Slot 4 FW Revision: %s\n", get_fw_info_out->slot_4_fw_rev);
+	fprintf(stdout, "%s Activation Capabilities: %x\n", fw_name, get_fw_info_out->fw_activation_capas);
+	fprintf(stdout, "Slot 1 %s Revision: %s\n", fw_name, get_fw_info_out->slot_1_fw_rev);
+	fprintf(stdout, "Slot 2 %s Revision: %s\n", fw_name, get_fw_info_out->slot_2_fw_rev);
+	fprintf(stdout, "Slot 3 %s Revision: %s\n", fw_name, get_fw_info_out->slot_3_fw_rev);
+	fprintf(stdout, "Slot 4 %s Revision: %s\n", fw_name, get_fw_info_out->slot_4_fw_rev);
 
 out:
 	cxl_cmd_unref(cmd);
@@ -6301,8 +6330,8 @@ struct cxl_mbox_health_counters_get_out {
 	__le32 cxl_mem_link_crc_errors;
 	__le32 cxl_io_link_lcrc_errors;
 	__le32 cxl_io_link_ecrc_errors;
-	__le32 num_ddr_single_ecc_errors;
-	__le32 num_ddr_double_ecc_errors;
+	__le32 num_ddr_correctable_ecc_errors;
+	__le32 num_ddr_uncorrectable_ecc_errors;
 	__le32 link_recovery_events;
 	__le32 time_in_throttled;
 	__le32 over_temperature_warning_level_exceeded;
@@ -6311,6 +6340,16 @@ struct cxl_mbox_health_counters_get_out {
 	__le32 rx_retry_request;
 	__le32 rcmd_qs0_hi_threshold_detect;
 	__le32 rcmd_qs1_hi_threshold_detect;
+	__le32 num_pscan_correctable_ecc_errors;
+	__le32 num_pscan_uncorrectable_ecc_errors;
+	__le32 num_ddr_dimm0_correctable_ecc_errors;
+	__le32 num_ddr_dimm0_uncorrectable_ecc_errors;
+	__le32 num_ddr_dimm1_correctable_ecc_errors;
+	__le32 num_ddr_dimm1_uncorrectable_ecc_errors;
+	__le32 num_ddr_dimm2_correctable_ecc_errors;
+	__le32 num_ddr_dimm2_uncorrectable_ecc_errors;
+	__le32 num_ddr_dimm3_correctable_ecc_errors;
+	__le32 num_ddr_dimm3_uncorrectable_ecc_errors;
 }  __attribute__((packed));
 
 CXL_EXPORT int cxl_memdev_health_counters_get(struct cxl_memdev *memdev)
@@ -6358,14 +6397,23 @@ CXL_EXPORT int cxl_memdev_health_counters_get(struct cxl_memdev *memdev)
 	fprintf(stdout, "6: CXL_MEM_LINK_CRC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->cxl_mem_link_crc_errors));
 	fprintf(stdout, "7: CXL_IO_LINK_LCRC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->cxl_io_link_lcrc_errors));
 	fprintf(stdout, "8: CXL_IO_LINK_ECRC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->cxl_io_link_ecrc_errors));
-	fprintf(stdout, "9: NUM_DDR_SINGLE_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_single_ecc_errors));
-	fprintf(stdout, "10: NUM_DDR_DOUBLE_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_double_ecc_errors));
+	fprintf(stdout, "9: NUM_DDR_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_correctable_ecc_errors));
+	fprintf(stdout, "10: NUM_DDR_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_uncorrectable_ecc_errors));
 	fprintf(stdout, "11: LINK_RECOVERY_EVENTS = %d\n", le32_to_cpu(health_counters_get_out->link_recovery_events));
 	fprintf(stdout, "12: TIME_IN_THROTTLED = %d\n", le32_to_cpu(health_counters_get_out->time_in_throttled));
 	fprintf(stdout, "13: RX_RETRY_REQUEST = %d\n", le32_to_cpu(health_counters_get_out->rx_retry_request));
 	fprintf(stdout, "14: RCMD_QS0_HI_THRESHOLD_DETECT = %d\n", le32_to_cpu(health_counters_get_out->rcmd_qs0_hi_threshold_detect));
 	fprintf(stdout, "15: RCMD_QS1_HI_THRESHOLD_DETECT = %d\n", le32_to_cpu(health_counters_get_out->rcmd_qs1_hi_threshold_detect));
-
+	fprintf(stdout, "16: NUM_PSCAN_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_pscan_correctable_ecc_errors));
+	fprintf(stdout, "17: NUM_PSCAN_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_pscan_uncorrectable_ecc_errors));
+	fprintf(stdout, "18: NUM_DDR_DIMM0_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm0_correctable_ecc_errors));
+	fprintf(stdout, "19: NUM_DDR_DIMM0_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm0_uncorrectable_ecc_errors));
+	fprintf(stdout, "20: NUM_DDR_DIMM1_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm1_correctable_ecc_errors));
+	fprintf(stdout, "21: NUM_DDR_DIMM1_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm1_uncorrectable_ecc_errors));
+	fprintf(stdout, "22: NUM_DDR_DIMM2_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm2_correctable_ecc_errors));
+	fprintf(stdout, "23: NUM_DDR_DIMM2_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm2_uncorrectable_ecc_errors));
+	fprintf(stdout, "24: NUM_DDR_DIMM3_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm3_correctable_ecc_errors));
+	fprintf(stdout, "25: NUM_DDR_DIMM3_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm3_uncorrectable_ecc_errors));
 out:
 	cxl_cmd_unref(cmd);
 	return rc;
@@ -10123,3 +10171,4373 @@ out:
 	cxl_cmd_unref(cmd);
 	return rc;
 }
+
+#define MAX_PMIC 8
+#define PMIC_NAME_MAX_SIZE 20
+
+struct pmic_data {
+	char pmic_name[PMIC_NAME_MAX_SIZE];
+	float vin;
+	float vout;
+	float iout;
+	float powr;
+	float temp;
+};
+struct cxl_pmic_vtmon_info_out {
+	struct pmic_data pmic_data[MAX_PMIC];
+}  __attribute__((packed));
+
+#define CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO_OPCODE 0xFB00
+#define CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO_PAYLOAD_IN_SIZE 0
+
+CXL_EXPORT int cxl_memdev_pmic_vtmon_info(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_pmic_vtmon_info_out *pmic_vtmon_info;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	cinfo->size_in = CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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%s\n",
+				cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+		rc = -ENXIO;
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO) {
+		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_PMIC_VTMON_INFO);
+		return -EINVAL;
+	}
+
+	pmic_vtmon_info = (void *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "=========================== PMIC VTMON SLOT INFO ============================\n");
+	for (int i = 0; i < MAX_PMIC; i++) {
+		fprintf(stdout, "pmic name: %s\n", pmic_vtmon_info->pmic_data[i].pmic_name);
+		fprintf(stdout, "vin: %f\n", pmic_vtmon_info->pmic_data[i].vin);
+		fprintf(stdout, "vout: %f\n", pmic_vtmon_info->pmic_data[i].vout);
+		fprintf(stdout, "iout: %f\n", pmic_vtmon_info->pmic_data[i].iout);
+		fprintf(stdout, "powr: %f\n", pmic_vtmon_info->pmic_data[i].powr);
+		fprintf(stdout, "temp: %f\n", pmic_vtmon_info->pmic_data[i].temp);
+	}
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+/* DDR MARGIN */
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN_OPCODE 0xFB0A
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN_PAYLOAD_IN_SIZE 4
+
+struct cxl_mbox_ddr_margin_run_in {
+	u8 slice_num;
+	u8 rd_wr_margin;
+	u8 ddr_id;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_margin_run(struct cxl_memdev *memdev,
+	u8 slice_num, u8 rd_wr_margin, u8 ddr_id)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_mbox_ddr_margin_run_in *ddr_margin_run_in;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	ddr_margin_run_in = (void *) cmd->send_cmd->in.payload;
+
+	ddr_margin_run_in->slice_num = slice_num;
+	ddr_margin_run_in->rd_wr_margin = rd_wr_margin;
+	ddr_margin_run_in->ddr_id = ddr_id;
+	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_DDR_MARGIN_SW_RUN) {
+		 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_DDR_MARGIN_SW_RUN);
+		return -EINVAL;
+	}
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_STATUS_OPCODE 0xFB0B
+
+struct cxl_ddr_margin_status_out {
+	int run_status;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_margin_status(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_ddr_margin_status_out *ddr_margin_status_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_STATUS_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_STATUS) {
+		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_DDR_MARGIN_SW_STATUS);
+		return -EINVAL;
+	}
+	ddr_margin_status_out = (void *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "%s\n", ddr_margin_status_out->run_status ?
+			"DDR MARGIN IS RUNNING" : "DDR MARGIN IS NOT RUNNING/FINISHED");
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_GET_SW CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_GET_SW_OPCODE 0xFB0C
+
+/* MAX_NUM_ROWS per BIT_COUNT should be in Sync with the FW Mbox DDR MARGIN code */
+#define MAX_NUM_ROWS 1024
+#define MAX_MARGIN_BIT_COUNT 8
+
+struct ddr_margin_info
+{
+	uint32_t slicenumber;
+	uint32_t bitnumber;
+	int32_t vreflevel;
+	int margin_low;
+	int margin_high;
+	double min_delay_ps;
+	double max_delay_ps;
+} __attribute__((packed));;
+
+struct cxl_ddr_margin_get_sw_out
+{
+  uint32_t row_count;
+  struct ddr_margin_info ddr_margin_slice_data[MAX_NUM_ROWS * MAX_MARGIN_BIT_COUNT];
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_margin_get(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_ddr_margin_get_sw_out *ddr_margin_get_sw_out;
+	int rc = 0;
+	uint32_t i;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_MARGIN_GET_SW_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_MARGIN_GET_SW) {
+		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_DDR_MARGIN_GET_SW);
+		return -EINVAL;
+	}
+	ddr_margin_get_sw_out = (struct cxl_ddr_margin_get_sw_out *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "SliceNo,bitNo, VrefLv, MinDelay, MaxDelay, MinDly(ps), MaxDly(ps)\n");
+
+	for(i = 0; i < ddr_margin_get_sw_out->row_count; i++)
+	{
+			fprintf(stdout, "%d,%d,%d,%d,%d,%3.2f,%3.2f\n",
+					ddr_margin_get_sw_out->ddr_margin_slice_data[i].slicenumber,
+					ddr_margin_get_sw_out->ddr_margin_slice_data[i].bitnumber,
+					ddr_margin_get_sw_out->ddr_margin_slice_data[i].vreflevel,
+					ddr_margin_get_sw_out->ddr_margin_slice_data[i].margin_low,
+					ddr_margin_get_sw_out->ddr_margin_slice_data[i].margin_high,
+					ddr_margin_get_sw_out->ddr_margin_slice_data[i].min_delay_ps,
+					ddr_margin_get_sw_out->ddr_margin_slice_data[i].max_delay_ps);
+	}
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+/* DDR STATS START */
+#define CXL_MEM_COMMAND_ID_DDR_STATS_RUN CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_STATS_RUN_OPCODE 0xFB1B
+#define CXL_MEM_COMMAND_ID_DDR_STATS_RUN_PAYLOAD_IN_SIZE 9
+
+struct cxl_mbox_ddr_stats_run_in {
+  uint8_t ddr_id;
+  uint32_t monitor_time;
+  uint32_t loop_count;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_stats_run(struct cxl_memdev *memdev,
+	u8 ddr_id, uint32_t monitor_time, uint32_t loop_count)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_mbox_ddr_stats_run_in *ddr_stats_run_in;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_STATS_RUN_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_STATS_RUN_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	ddr_stats_run_in = (void *) cmd->send_cmd->in.payload;
+
+	ddr_stats_run_in->ddr_id = ddr_id;
+	ddr_stats_run_in->monitor_time = monitor_time;
+	ddr_stats_run_in->loop_count = loop_count;
+	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_DDR_STATS_RUN) {
+		 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_DDR_STATS_RUN);
+		return -EINVAL;
+	}
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_STATS_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_STATS_STATUS_OPCODE 0xFB1C
+
+struct cxl_ddr_stats_status_out {
+	int run_status;
+	uint32_t loop_count;
+}  __attribute__((packed));
+
+/* DDR STATS STATUS */
+CXL_EXPORT int cxl_memdev_ddr_stats_status(struct cxl_memdev *memdev, int* run_status, uint32_t* loop_count)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_ddr_stats_status_out *ddr_stats_status_out;
+
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_STATS_STATUS_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_STATS_STATUS) {
+		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_DDR_STATS_STATUS);
+		return -EINVAL;
+	}
+	ddr_stats_status_out = (void *)cmd->send_cmd->out.payload;
+	*run_status = ddr_stats_status_out->run_status;
+	*loop_count = ddr_stats_status_out->loop_count;
+
+	fprintf(stdout, "%s\n", ddr_stats_status_out->run_status ?
+			"DDR STATS IS BUSY" : "DDR STATS IS NOT RUNNING/FINISHED");
+
+	fprintf(stdout, "Loop Count = %d\n", ddr_stats_status_out->loop_count);
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_STATS_GET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_STATS_GET_OPCODE 0xFB1D
+
+#define NUM_BANK 16
+#define NUM_CS 4
+
+struct dfi_cs_pm {
+  uint32_t mrw_cnt;
+  uint32_t refresh_cnt;
+  uint32_t act_cnt;
+  uint32_t write_cnt;
+  uint32_t read_cnt;
+  uint32_t pre_cnt;
+  uint32_t rr_cnt;
+  uint32_t ww_cnt;
+  uint32_t rw_cnt;
+} __attribute__((packed));
+
+struct dfi_cs_bank_pm {
+  uint32_t bank_act_cnt;
+  uint32_t bank_wr_cnt;
+  uint32_t bank_rd_cnt;
+  uint32_t bank_pre_cnt;
+} __attribute__((packed));
+
+struct dfi_mc_pm {
+  uint32_t cmd_queue_full_events;
+  uint32_t info_fifo_full_events;
+  uint32_t wrdata_hold_fifo_full_events;
+  uint32_t port_cmd_fifo0_full_events;
+  uint32_t port_wrresp_fifo0_full_events;
+  uint32_t port_wr_fifo0_full_events;
+  uint32_t port_rd_fifo0_full_events;
+  uint32_t port_cmd_fifo1_full_events;
+  uint32_t port_wrresp_fifo1_full_events;
+  uint32_t port_wr_fifo1_full_events;
+  uint32_t port_rd_fifo1_full_events;
+  uint32_t ecc_dataout_corrected;
+  uint32_t ecc_dataout_uncorrected;
+  uint32_t pd_ex;
+  uint32_t pd_en;
+  uint32_t srex;
+  uint32_t sren;
+  uint32_t write;
+  uint32_t read;
+  uint32_t rmw;
+  uint32_t bank_act;
+  uint32_t precharge;
+  uint32_t precharge_all;
+  uint32_t mrw;
+  uint32_t auto_ref;
+  uint32_t rw_auto_pre;
+  uint32_t zq_cal_short;
+  uint32_t zq_cal_long;
+  uint32_t same_addr_ww_collision;
+  uint32_t same_addr_wr_collision;
+  uint32_t same_addr_rw_collision;
+  uint32_t same_addr_rr_collision;
+} __attribute__((packed));
+
+struct ddr_pmon_data {
+  uint64_t fr_cnt;
+  uint32_t idle_cnt;
+  uint32_t rd_ot_cnt;
+  uint32_t wr_ot_cnt;
+  uint32_t wrd_ot_cnt;
+  uint32_t rd_cmd_cnt;
+  uint32_t rd_cmd_busy_cnt;
+  uint32_t wr_cmd_cnt;
+  uint32_t wr_cmd_busy_cnt;
+  uint32_t rd_data_cnt;
+  uint32_t rd_data_busy_cnt;
+  uint32_t wr_data_cnt;
+  uint32_t wr_data_busy_cnt;
+  uint64_t rd_avg_lat;
+  uint64_t wr_avg_lat;
+  uint32_t rd_trans_smpl_cnt;
+  uint32_t wr_trans_smpl_cnt;
+} __attribute__((packed));
+
+struct ddr_data {
+  struct ddr_pmon_data pmon;
+  struct dfi_cs_pm cs_pm[NUM_CS];
+  struct dfi_cs_bank_pm cs_bank_pm[NUM_CS][NUM_BANK];
+  struct dfi_mc_pm mc_pm;
+} __attribute__((packed));
+
+struct ddr_stats_data {
+  struct ddr_data stats;
+} __attribute__((packed));
+
+typedef struct ddr_stats_data ddr_stats_data_t;
+
+#define MAX_CXL_TRANSFER_SZ (16 * 1024)
+
+static void display_pmon_stats(ddr_stats_data_t* disp_stats, uint32_t loop_count) {
+  uint32_t loop;
+  fprintf(stderr,"PMON STATS:\n");
+  fprintf(stderr,
+      "iteration, fr_cnt, idle_cnt, rd_ot_cnt, wr_ot_cnt, wrd_ot_cnt, "
+      "rd_cmd_cnt, rd_cmd_busy_cnt, wr_cmd_cnt, wr_cmd_busy_cnt, rd_data_cnt, "
+      "rd_data_busy_cnt, wr_data_cnt, wr_data_busy_cnt, "
+      "rd_avg_lat, wr_avg_lat, rd_trans_smpl_cnt, wr_trans_smpl_cnt\n");
+  for (loop = 0; loop < loop_count; loop++) {
+    fprintf(stderr,
+        "[%d], %lu, %u, %u, %u, %u, "
+        "%u, %u, %u, %u, %u, "
+        "%u, %u, %u, "
+        "%lu, %lu, %u, %u\n",
+        loop,
+        disp_stats->stats.pmon.fr_cnt,
+        disp_stats->stats.pmon.idle_cnt,
+        disp_stats->stats.pmon.rd_ot_cnt,
+        disp_stats->stats.pmon.wr_ot_cnt,
+        disp_stats->stats.pmon.wrd_ot_cnt,
+        disp_stats->stats.pmon.rd_cmd_cnt,
+        disp_stats->stats.pmon.rd_cmd_busy_cnt,
+        disp_stats->stats.pmon.wr_cmd_cnt,
+        disp_stats->stats.pmon.wr_cmd_busy_cnt,
+        disp_stats->stats.pmon.rd_data_cnt,
+        disp_stats->stats.pmon.rd_data_busy_cnt,
+        disp_stats->stats.pmon.wr_data_cnt,
+        disp_stats->stats.pmon.wr_data_busy_cnt,
+        disp_stats->stats.pmon.rd_avg_lat,
+        disp_stats->stats.pmon.wr_avg_lat,
+        disp_stats->stats.pmon.rd_trans_smpl_cnt,
+        disp_stats->stats.pmon.wr_trans_smpl_cnt);
+    disp_stats++;
+  }
+  fprintf(stderr,"\n");
+}
+
+static void display_cs_pm_stats(ddr_stats_data_t* disp_stats, uint32_t loop_count) {
+  uint32_t rank, loop;
+
+  fprintf(stderr, "CS PM STATS:\n");
+  fprintf(stderr,
+      "iteration, rank, mrw_cnt, refresh_cnt, act_cnt, write_cnt, "
+      "read_cnt, pre_cnt, rr_cnt, ww_cnt, rw_cnt\n ");
+
+  for (loop = 0; loop < loop_count; loop++) {
+    for (rank = 0; rank < NUM_CS; rank++) {
+      fprintf(stderr,
+          "[%d], %d, %u, %u, %u, %u, "
+          "%u, %u, %u, %u, %u\n",
+          loop,
+          rank,
+          disp_stats->stats.cs_pm[rank].mrw_cnt,
+          disp_stats->stats.cs_pm[rank].refresh_cnt,
+          disp_stats->stats.cs_pm[rank].act_cnt,
+          disp_stats->stats.cs_pm[rank].write_cnt,
+          disp_stats->stats.cs_pm[rank].read_cnt,
+          disp_stats->stats.cs_pm[rank].pre_cnt,
+          disp_stats->stats.cs_pm[rank].rr_cnt,
+          disp_stats->stats.cs_pm[rank].ww_cnt,
+          disp_stats->stats.cs_pm[rank].rw_cnt);
+    }
+    disp_stats++;
+  }
+  fprintf(stderr, "\n");
+}
+
+static void display_cs_bank_pm_stats(ddr_stats_data_t* disp_stats, uint32_t loop_count) {
+  uint32_t rank, bank, loop;
+
+  fprintf(stderr, "CS BANK STATS:\n");
+  fprintf(stderr,
+      "iteration, rank, bank, bank_act_cnt, bank_wr_cnt, bank_rd_cnt, bank_pre_cnt\n");
+  for (loop = 0; loop < loop_count; loop++) {
+    for (rank = 0; rank < NUM_CS; rank++) {
+      for (bank = 0; bank < NUM_BANK; bank++) {
+        fprintf(stderr,
+            "[%d], %d, %d, %u, %u, %u, %u\n",
+            loop,
+            rank,
+            bank,
+            disp_stats->stats.cs_bank_pm[rank][bank].bank_act_cnt,
+            disp_stats->stats.cs_bank_pm[rank][bank].bank_wr_cnt,
+            disp_stats->stats.cs_bank_pm[rank][bank].bank_rd_cnt,
+            disp_stats->stats.cs_bank_pm[rank][bank].bank_pre_cnt);
+      }
+    }
+    disp_stats++;
+  }
+  fprintf(stderr, "\n");
+}
+
+static void display_mc_pm_stats(ddr_stats_data_t* disp_stats, uint32_t loop_count) {
+  uint32_t loop;
+
+  fprintf(stderr, "PM STATS:\n");
+  fprintf(stderr,
+      "iteration, cmd_queue_full_events, info_fifo_full_events, "
+      "wrdata_hold_fifo_full_events, port_cmd_fifo0_full_events, "
+      "port_wrresp_fifo0_full_events, port_wr_fifo0_full_events, "
+      "port_rd_fifo0_full_events, port_cmd_fifo1_full_events, "
+      "port_wrresp_fifo1_full_events, port_wr_fifo1_full_events, "
+      "port_rd_fifo1_full_events, ecc_dataout_corrected, "
+      "ecc_dataout_uncorrected, pd_ex, pd_en, srex, sren, "
+      "write, read, rmw, bank_act, precharge, precharge_all, "
+      "mrw, auto_ref, rw_auto_pre, zq_cal_short, zq_cal_long, "
+      "same_addr_ww_collision, same_addr_wr_collision, "
+      "same_addr_rw_collision, same_addr_rr_collision\n");
+
+  for (loop = 0; loop < loop_count; loop++) {
+    fprintf(stderr,
+        "[%d], %u, %u, "
+        "%u, %u, "
+        "%u, %u, "
+        "%u, %u, "
+        "%u, %u, "
+        "%u, %u, "
+        "%u, %u, %u, %u, %u,"
+        "%u, %u, %u, %u, %u, %u,"
+        "%u, %u, %u, %u, %u,"
+        "%u, %u, "
+        "%u, %u\n",
+        loop,
+        disp_stats->stats.mc_pm.cmd_queue_full_events,
+        disp_stats->stats.mc_pm.info_fifo_full_events,
+        disp_stats->stats.mc_pm.wrdata_hold_fifo_full_events,
+        disp_stats->stats.mc_pm.port_cmd_fifo0_full_events,
+        disp_stats->stats.mc_pm.port_wrresp_fifo0_full_events,
+        disp_stats->stats.mc_pm.port_wr_fifo0_full_events,
+        disp_stats->stats.mc_pm.port_rd_fifo0_full_events,
+        disp_stats->stats.mc_pm.port_cmd_fifo1_full_events,
+        disp_stats->stats.mc_pm.port_wrresp_fifo1_full_events,
+        disp_stats->stats.mc_pm.port_wr_fifo1_full_events,
+        disp_stats->stats.mc_pm.port_rd_fifo1_full_events,
+        disp_stats->stats.mc_pm.ecc_dataout_corrected,
+        disp_stats->stats.mc_pm.ecc_dataout_uncorrected,
+        disp_stats->stats.mc_pm.pd_ex,
+        disp_stats->stats.mc_pm.pd_en,
+        disp_stats->stats.mc_pm.srex,
+        disp_stats->stats.mc_pm.sren,
+        disp_stats->stats.mc_pm.write,
+        disp_stats->stats.mc_pm.read,
+        disp_stats->stats.mc_pm.rmw,
+        disp_stats->stats.mc_pm.bank_act,
+        disp_stats->stats.mc_pm.precharge,
+        disp_stats->stats.mc_pm.precharge_all,
+        disp_stats->stats.mc_pm.mrw,
+        disp_stats->stats.mc_pm.auto_ref,
+        disp_stats->stats.mc_pm.rw_auto_pre,
+        disp_stats->stats.mc_pm.zq_cal_short,
+        disp_stats->stats.mc_pm.zq_cal_long,
+        disp_stats->stats.mc_pm.same_addr_ww_collision,
+        disp_stats->stats.mc_pm.same_addr_wr_collision,
+        disp_stats->stats.mc_pm.same_addr_rw_collision,
+        disp_stats->stats.mc_pm.same_addr_rr_collision);
+    disp_stats++;
+  }
+  fprintf(stderr, "\n");
+}
+
+struct cxl_ddr_stats_get_in {
+	uint32_t offset;
+	uint32_t transfer_sz;
+}  __attribute__((packed));
+
+#define CXL_MEM_COMMAND_ID_DDR_STATS_GET_PAYLOAD_IN_SIZE 8
+
+static int cxl_ddr_stats_get(struct cxl_memdev *memdev, unsigned char *dst, int offset, int bytes_to_cpy)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_ddr_stats_get_in *ddr_stats_get_in;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_STATS_GET_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_STATS_GET_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	ddr_stats_get_in = (void *) cmd->send_cmd->in.payload;
+	ddr_stats_get_in->offset = offset;
+	ddr_stats_get_in->transfer_sz = bytes_to_cpy;
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_STATS_GET) {
+		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_DDR_STATS_GET);
+		return -EINVAL;
+	}
+
+	memcpy(dst, (unsigned char*) cmd->send_cmd->out.payload, cmd->send_cmd->out.size);
+
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+/* DDR GET STATS */
+CXL_EXPORT int cxl_memdev_ddr_stats_get(struct cxl_memdev *memdev)
+{
+	unsigned char *buf;
+	int total_bytes = 0, bytes_to_cpy = 0, bytes_copied = 0;
+	ddr_stats_data_t* ddr_stats_start;
+	int rc = 0;
+	int run_status;
+	uint32_t loop_count;
+
+	rc = cxl_memdev_ddr_stats_status(memdev, &run_status, &loop_count);
+	if (rc < 0)
+		return rc;
+
+	if (run_status)
+		return -EBUSY;
+
+	total_bytes = sizeof(ddr_stats_data_t) * loop_count;
+
+	buf =(unsigned char *)malloc(total_bytes);
+	ddr_stats_start = (ddr_stats_data_t*)buf;
+
+	while(bytes_copied < total_bytes)
+	{
+		bytes_to_cpy = (total_bytes - bytes_copied) < MAX_CXL_TRANSFER_SZ ?
+			       (total_bytes - bytes_copied) : MAX_CXL_TRANSFER_SZ;
+		rc = cxl_ddr_stats_get(memdev, buf + bytes_copied, bytes_copied, bytes_to_cpy);
+		bytes_copied = bytes_copied + bytes_to_cpy;
+		if (rc < 0)
+			goto out;
+	}
+
+	display_pmon_stats(ddr_stats_start, loop_count);
+	display_cs_pm_stats(ddr_stats_start, loop_count);
+	display_cs_bank_pm_stats(ddr_stats_start, loop_count);
+	display_mc_pm_stats(ddr_stats_start, loop_count);
+out:
+	free(buf);
+	return rc;
+}
+
+/* REBOOT MODE SET */
+#define CXL_MEM_COMMAND_ID_REBOOT_MODE_SET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_REBOOT_MODE_SET_OPCODE 0xFB0D
+#define CXL_MEM_COMMAND_ID_REBOOT_MODE_SET_PAYLOAD_IN_SIZE 4
+
+#define CXL_IO_MEM_MODE 0x0
+#define CXL_IO_MODE 0xCE
+
+struct cxl_mbox_reboot_mode_set_in {
+	u8 reboot_mode;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_reboot_mode_set(struct cxl_memdev *memdev, u8 reboot_mode)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_mbox_reboot_mode_set_in *reboot_mode_set_in;
+	int rc = 0;
+
+	if ((reboot_mode != CXL_IO_MEM_MODE) && (reboot_mode != CXL_IO_MODE)) {
+        fprintf(stderr,"Invalid Reboot Mode");
+        return -EINVAL;
+    }
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_REBOOT_MODE_SET_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_REBOOT_MODE_SET_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	reboot_mode_set_in = (void *) cmd->send_cmd->in.payload;
+
+	reboot_mode_set_in->reboot_mode = reboot_mode;
+	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_REBOOT_MODE_SET) {
+		 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_REBOOT_MODE_SET);
+		return -EINVAL;
+	}
+
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_CXL_CURR_BOOT_MODE_GET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CXL_CURR_BOOT_MODE_GET_OPCODE 0xFB0E
+
+struct cxl_curr_cxl_boot_mode_out
+{
+  uint8_t curr_cxl_boot;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_curr_cxl_boot_mode_get(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_curr_cxl_boot_mode_out *curr_cxl_boot_mode_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CXL_CURR_BOOT_MODE_GET_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_CXL_CURR_BOOT_MODE_GET) {
+		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_CXL_CURR_BOOT_MODE_GET);
+		return -EINVAL;
+	}
+
+	curr_cxl_boot_mode_out = (struct cxl_curr_cxl_boot_mode_out *)cmd->send_cmd->out.payload;
+	if (curr_cxl_boot_mode_out->curr_cxl_boot == CXL_IO_MEM_MODE)
+			fprintf(stdout, "CXL_IO_MEM_MODE\n");
+	else if (curr_cxl_boot_mode_out->curr_cxl_boot == CXL_IO_MODE)
+			fprintf(stdout, "CXL_IO_MODE\n");
+	else
+			fprintf(stdout, "Invalid Mode\n");
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN_OPCODE 0xFB02
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN_PAYLOAD_IN_SIZE 4
+
+struct cxl_mbox_pcie_eye_run_in {
+	u8 lane;
+	u8 sw_scan;
+	u8 ber;
+}  __attribute__((packed));
+
+struct cxl_pcie_eye_run_out {
+	int pcie_eye_run_status;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_pcie_eye_run(struct cxl_memdev *memdev,
+	u8 lane, u8 sw_scan, u8 ber)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_mbox_pcie_eye_run_in *pcie_eye_run_in;
+	struct cxl_pcie_eye_run_out *pcie_eye_run_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	pcie_eye_run_in = (void *) cmd->send_cmd->in.payload;
+
+	pcie_eye_run_in->lane = lane;
+	pcie_eye_run_in->sw_scan = sw_scan;
+	pcie_eye_run_in->ber = ber;
+	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_PCIE_EYE_SW_RUN) {
+		 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_PCIE_EYE_SW_RUN);
+		return -EINVAL;
+	}
+
+	pcie_eye_run_out = (void *)cmd->send_cmd->out.payload;
+	if (!pcie_eye_run_out->pcie_eye_run_status)
+		fprintf(stdout, "pcie eye is running\n");
+	else
+		fprintf(stdout, "pcie eye already running OR fault, error : %d\n",
+				pcie_eye_run_out->pcie_eye_run_status);
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+	return 0;
+}
+
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_STATUS_OPCODE 0xFB03
+
+struct cxl_pcie_eye_status_out {
+	int pcie_eye_status;
+	int error;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_pcie_eye_status(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_pcie_eye_status_out *pcie_eye_status_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCIE_EYE_SW_STATUS_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PCIE_EYE_SW_STATUS) {
+		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_PCIE_EYE_SW_STATUS);
+		return -EINVAL;
+	}
+	pcie_eye_status_out = (void *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "%s\n", pcie_eye_status_out->pcie_eye_status ?
+			"PCIE EYE SW IS RUNNING" : "PCIE EYE SW IS NOT RUNNING/FINISHED");
+	if(pcie_eye_status_out->error)
+		fprintf(stdout, "pcie eye run error %d:\n", pcie_eye_status_out->error);
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+	return 0;
+}
+
+
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_GET_SW CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_GET_SW_OPCODE 0xFB04
+
+#define NUM_EYESCOPE_HORIZ_VALS 40
+#define TOTAL_EYESCOPE_HORIZ_VALS ((NUM_EYESCOPE_HORIZ_VALS * 2) + 1)
+
+struct cxl_pcie_eye_get_sw_out {
+	char pcie_eye_data[TOTAL_EYESCOPE_HORIZ_VALS + 1];
+}  __attribute__((packed));
+
+struct cxl_pcie_eye_get_sw_in {
+	uint offset;
+}  __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_pcie_eye_get_sw(struct cxl_memdev *memdev, uint offset)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_pcie_eye_get_sw_in *pcie_eye_get_sw_in;
+	struct cxl_pcie_eye_get_sw_out *pcie_eye_get_sw_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCIE_EYE_GET_SW_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	pcie_eye_get_sw_in = (void *) cmd->send_cmd->in.payload;
+	pcie_eye_get_sw_in->offset = offset;
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PCIE_EYE_GET_SW) {
+		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_PCIE_EYE_GET_SW);
+		return -EINVAL;
+	}
+	pcie_eye_get_sw_out = (void *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "%s\n", pcie_eye_get_sw_out->pcie_eye_data);
+
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+	return 0;
+}
+
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_GET_HW CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_GET_HW_OPCODE 0xFB05
+
+struct eyescope_results {
+        double merged_horizontal_eye_left;
+        double merged_horizontal_eye_right;
+        double merged_vertical_eye_top;
+        double merged_vertical_eye_bottom;
+};
+
+struct rx_settings_t {
+        int iskew_signed;
+        int qskew_signed;
+        int dlev00_signed;
+        int dlev01_signed;
+        int dlev10_signed;
+        int dlev11_signed;
+        int irphase_signed;
+        int h1po;
+        int h1no;
+        int h1pe;
+        int h1ne;
+        int h2;
+        int h3;
+        int h4;
+        int h5;
+        int h6;
+        int h7;
+        int h8;
+        int h9;
+        int aeq;
+        int vga;
+        int appmd;
+        int rxrt;
+        int shd;
+        int step;
+        int wm;
+};
+
+
+struct cxl_pcie_eye_get_hw_out {
+	struct eyescope_results eyescope_results;
+	struct rx_settings_t rx_settings_t;
+	int eyescope_request_status;
+}  __attribute__((packed));
+
+
+void display_rx_setttings(struct rx_settings_t *settings);
+void display_rx_setttings(struct rx_settings_t *settings)
+{
+        fprintf(stdout, "rx_settings: \n");
+        fprintf(stdout, "dlv0123 = [%d, %d, %d, %d],", settings->dlev00_signed, settings->dlev01_signed,
+           settings->dlev10_signed, settings->dlev11_signed);
+        fprintf(stdout, "*vga, aeq = [%d, %d],", settings->vga, settings->aeq);
+        fprintf(stdout, "h2-9 = [%d, %d, %d, %d, %d, %d, %d, %d],",
+           settings->h2, settings->h3, settings->h4, settings->h5,
+           settings->h6, settings->h7, settings->h8, settings->h9);
+        fprintf(stdout, "appmd, rxrt, shd, wm = [%d, %d, 'g%d', %d],",
+           settings->appmd, settings->rxrt, settings->shd, settings->wm);
+        fprintf(stdout, "h1ne/0, pe/o = [%d %d %d %d],", settings->h1ne, settings->h1no,
+           settings->h1pe, settings->h1po);
+        fprintf(stdout, "iskw, qskw = [%d %d]", settings->iskew_signed, settings->qskew_signed);
+        fprintf(stdout, "\n");
+}
+
+void display_merged_eye_results(struct eyescope_results *eyescope_results);
+void display_merged_eye_results(struct eyescope_results *eyescope_results){
+
+        fprintf(stdout, "Merged Top (mV): %f\n",
+              eyescope_results->merged_vertical_eye_top);
+        fprintf(stdout, "Merged Bottom (mV): %f\n",
+              eyescope_results->merged_vertical_eye_bottom);
+        fprintf(stdout, "Merged Right Eye (UI): %f\n",
+              eyescope_results->merged_horizontal_eye_right);
+        fprintf(stdout, "Merged Left Eye (UI): %f\n",
+                    eyescope_results->merged_horizontal_eye_left);
+}
+
+CXL_EXPORT int cxl_memdev_pcie_eye_get_hw(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_pcie_eye_get_hw_out *pcie_eye_get_hw_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCIE_EYE_GET_HW_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PCIE_EYE_GET_HW) {
+		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_PCIE_EYE_GET_HW);
+		return -EINVAL;
+	}
+	pcie_eye_get_hw_out = (void *)cmd->send_cmd->out.payload;
+	if (pcie_eye_get_hw_out->eyescope_request_status) {
+		fprintf(stdout, "eyescope request status: PASS\n");
+		display_rx_setttings(&pcie_eye_get_hw_out->rx_settings_t);
+		display_merged_eye_results(&pcie_eye_get_hw_out->eyescope_results);
+	} else {
+		fprintf(stdout, "eyescope request status: FAIL\n");
+	}
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_BER CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_BER_OPCODE 0xFB06
+
+struct cxl_pcie_eye_get_sw_ber_out {
+	float horiz_margin;
+	float vert_margin;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_pcie_eye_get_sw_ber(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_pcie_eye_get_sw_ber_out *pcie_eye_get_sw_ber_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCIE_EYE_SW_BER_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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: Read failed OR BER is not enabled, firmware status: %d\n",
+				cxl_memdev_get_devname(memdev), rc);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PCIE_EYE_SW_BER) {
+		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_PCIE_EYE_SW_BER);
+		return -EINVAL;
+	}
+	pcie_eye_get_sw_ber_out = (void *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "Extrapolation for BER at 1e-12\n");
+	if(pcie_eye_get_sw_ber_out->vert_margin > 18 && pcie_eye_get_sw_ber_out->horiz_margin > 0.2) {
+		fprintf(stdout, "Eye Height and width margins are > 0.2UI and 18mV, Test PASSED\n");
+		fprintf(stdout, "Eye width margin at 1e-12 is %f UI\n", pcie_eye_get_sw_ber_out->horiz_margin);
+		fprintf(stdout, "Eye height margin at 1e-12 is %f mV\n", pcie_eye_get_sw_ber_out->vert_margin);
+	} else {
+		fprintf(stdout, "Eye Height and width margins are not greater than 0.2UI and 18mV, Test FAILED\n");
+	}
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_CXL_LINK_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_CXL_LINK_STATUS_OPCODE 0xFB07
+
+char ltssm_state_name[][20] =
+{
+	"DETECT_QUIET",
+	"DETECT_ACT",
+	"POLL_ACTIVE",
+	"POLL_COMPLIANCE",
+	"POLL_CONFIG",
+	"PRE_DETECT_QUIET",
+	"DETECT_WAIT",
+	"CFG_LINKWD_START",
+	"CFG_LINKWD_ACEPT",
+	"CFG_LANENUM_WAIT",
+	"CFG_LANENUM_ACEPT",
+	"CFG_COMPLETE",
+	"CFG_IDLE",
+	"RCVRY_LOCK",
+	"RCVRY_SPEED",
+	"RCVRY_RCVRCFG",
+	"RCVRY_IDLE",
+	"L0",
+	"L0S",
+	"L123_SEND_EIDLE",
+	"L1_IDLE",
+	"L2_IDLE",
+	"L2_WAKE",
+	"DISABLED_ENTRY",
+	"DISABLED_IDLE",
+	"DISABLED",
+	"LPBK_ENTRY",
+	"LPBK_ACTIVE",
+	"LPBK_EXIT",
+	"LPBK_EXIT_TIMEOUT",
+	"HOT_RESET_ENTRY",
+	"HOT_RESET",
+	"RCVRY_EQ0",
+	"RCVRY_EQ1",
+	"RCVRY_EQ2",
+	"RCVRY_EQ3"
+};
+
+struct cxl_get_cxl_link_status_out {
+	float cxl_link_status;
+	uint32_t link_width;
+	uint32_t link_speed;
+	uint32_t ltssm_val;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_get_cxl_link_status(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_get_cxl_link_status_out *get_cxl_link_status_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_CXL_LINK_STATUS_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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: Read failed, firmware status: %d\n",
+				cxl_memdev_get_devname(memdev), rc);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_CXL_LINK_STATUS) {
+		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_CXL_LINK_STATUS);
+		return -EINVAL;
+	}
+	get_cxl_link_status_out = (void *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "Link is in CXL%0.1f mode\n", get_cxl_link_status_out->cxl_link_status);
+	fprintf(stdout, "Negotiated link width: x%d\n", get_cxl_link_status_out->link_width);
+	fprintf(stdout, "Negotiated link speed: Gen%d\n", get_cxl_link_status_out->link_speed);
+	fprintf(stdout, "ltssm state: %s, code 0x%x\n", ltssm_state_name[get_cxl_link_status_out->ltssm_val], get_cxl_link_status_out->ltssm_val);
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_DEVICE_INFO CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_DEVICE_INFO_OPCODE 0xFB08
+
+struct cxl_get_device_info_out {
+	uint16_t device_id;
+	uint8_t revision_id;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_get_device_info(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_get_device_info_out *get_device_info_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_DEVICE_INFO_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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: Read failed, firmware status: %d\n",
+				cxl_memdev_get_devname(memdev), rc);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_DEVICE_INFO) {
+		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_DEVICE_INFO);
+		return -EINVAL;
+	}
+	get_device_info_out = (void *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "Device id: 0x%x\n", get_device_info_out->device_id);
+	fprintf(stdout, "Revision id: 0x%x\n", get_device_info_out->revision_id);
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_READ_DDR_TEMP CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_READ_DDR_TEMP_OPCODE 0xC531
+#define DDR_MAX_DIMM_CNT 4
+
+struct ddr_dimm_temp_info {
+    uint8_t ddr_temp_valid;
+    uint8_t dimm_id;
+    uint8_t spd_idx;
+    uint8_t rsvd;
+    float dimm_temp;
+};
+
+struct cxl_read_ddr_temp_out {
+    struct ddr_dimm_temp_info ddr_dimm_temp_info[DDR_MAX_DIMM_CNT];
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_read_ddr_temp(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_read_ddr_temp_out *read_ddr_temp_out;
+	int rc = 0;
+	int idx;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_READ_DDR_TEMP_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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: Read failed, firmware status: %d\n",
+				cxl_memdev_get_devname(memdev), rc);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_READ_DDR_TEMP) {
+		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_READ_DDR_TEMP);
+		return -EINVAL;
+	}
+	read_ddr_temp_out = (void *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "DDR DIMM temperature info:\n");
+	for(idx = 0; idx < DDR_MAX_DIMM_CNT; idx++) {
+		fprintf(stdout, "dimm_id : 0x%x\n", read_ddr_temp_out->ddr_dimm_temp_info[idx].dimm_id);
+		fprintf(stdout, "spd_idx: 0x%x\n", read_ddr_temp_out->ddr_dimm_temp_info[idx].spd_idx);
+		fprintf(stdout, "dimm temp: %f\n", read_ddr_temp_out->ddr_dimm_temp_info[idx].dimm_temp);
+		fprintf(stdout, "ddr temperature is %s\n\n", read_ddr_temp_out->ddr_dimm_temp_info[idx].ddr_temp_valid ? "valid" : "invalid");
+	}
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA_OPCODE 0xFB14
+#define CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA_IN_PAYLOAD_SIZE sizeof(u64)
+
+CXL_EXPORT int cxl_memdev_cxl_hpa_to_dpa(struct cxl_memdev *memdev, u64 hpa_address)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_command_info *cinfo;
+	struct cxl_mem_query_commands *query;
+	int rc = 0;
+	u64 *dpa_address_out;
+	u64 *hpa_address_in;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA_IN_PAYLOAD_SIZE;
+	if (cinfo->size_in > 0) {
+		cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	hpa_address_in = (void *)cmd->send_cmd->in.payload;
+	*hpa_address_in = hpa_address;
+
+	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: Read failed, firmware status: %d\n",
+				cxl_memdev_get_devname(memdev), rc);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA) {
+		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_CXL_HPA_TO_DPA);
+		return -EINVAL;
+	}
+	dpa_address_out = (void*)cmd->send_cmd->out.payload;
+	fprintf(stdout, "dpa address:0x%lx\n", *dpa_address_out);
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_ERRORS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_ERRORS_OPCODE 0xFB13
+
+typedef enum {
+	WSTRB_PARITY_ERROR = 0,
+	WDATA_PARITY_ERROR,
+	RDATA_RRESP_PARITY_ERROR,
+	RDATA_RESP_RID_PARITY_ERROR,
+	RDATA_PARITY_ERROR,
+	R_RESP_PARITY_ERROR,
+	B_RESP_PARITY_ERROR,
+	AW_QOS_PARITY_ERROR,
+	AW_MISC_PARITY_ERROR,
+	AW_ID_PARITY_ERROR,
+	AW_ADDR_RANGE_PARITY_ERROR,
+	AW_ADDR_PARITY_ERROR,
+	AR_QOS_PARITY_ERROR,
+	AR_MISC_PARITY_ERROR,
+	AR_ID_PARITY_ERROR,
+	AR_ADDR_RANGE_PARITY_ERROR,
+	AR_ADDR_PARITY_ERROR,
+	AXI_B_ID_PARITY_ERROR,
+	AXI_B_PARITY_ERROR,
+	AXI_R_ID_PARITY_ERROR,
+	AXI_R_DATA_PARITY_ERROR,
+	AXI_R_PARITY_ERROR,
+	DDR_PARITY_ERROR_COUNT = 22,
+} ddr_parity_errors;
+
+char *ddr_parity_error_strings[DDR_PARITY_ERROR_COUNT] = {
+	"WSTRB_PARITY_ERROR",
+	"WDATA_PARITY_ERROR",
+	"RDATA_RRESP_PARITY_ERROR",
+	"RDATA_RESP_RID_PARITY_ERROR",
+	"RDATA_PARITY_ERROR",
+	"R_RESP_PARITY_ERROR",
+	"B_RESP_PARITY_ERROR",
+	"AW_QOS_PARITY_ERROR",
+	"AW_MISC_PARITY_ERROR",
+	"AW_ID_PARITY_ERROR",
+	"AW_ADDR_RANGE_PARITY_ERROR",
+	"AW_ADDR_PARITY_ERROR",
+	"AR_QOS_PARITY_ERROR",
+	"AR_MISC_PARITY_ERROR",
+	"AR_ID_PARITY_ERROR",
+	"AR_ADDR_RANGE_PARITY_ERROR",
+	"AR_ADDR_PARITY_ERROR",
+	"AXI_B_ID_PARITY_ERROR",
+	"AXI_B_PARITY_ERROR",
+	"AXI_R_ID_PARITY_ERROR",
+	"AXI_R_DATA_PARITY_ERROR",
+	"AXI_R_PARITY_ERROR",
+};
+
+typedef enum {
+	S2M_NDR_FIFO = 0,
+	S2M_DRC_FIFO,
+	M2S_RWD_FIFO,
+	M2S_REQ_FIFO,
+	DDR1_W_REQ_FIFO,
+	DDR1_RDATA_RESP_FIFO,
+	DDR1_R_RESP_FIFO,
+	DDR1_B_RESP_FIFO,
+	DDR1_AW_REQ_FIFO,
+	DDR1_AR_REQ_FIFO,
+	DDR0_W_REQ_FIFO,
+	DDR0_RDATA_RESP_FIFO,
+	DDR0_R_RESP_FIFO,
+	DDR0_B_RESP_FIFO,
+	DDR0_AW_REQ_FIFO,
+	DDR0_AR_REQ_FIFO,
+	FIFO_ERROR_COUNT = 16,
+} fifo_errors;
+
+char *fifo_error_strings[FIFO_ERROR_COUNT] = {
+	"S2M_NDR_FIFO",
+	"S2M_DRC_FIFO",
+	"M2S_RWD_FIFO",
+	"M2S_REQ_FIFO",
+	"DDR1_W_REQ_FIFO",
+	"DDR1_RDATA_RESP_FIFO",
+	"DDR1_R_RESP_FIFO",
+	"DDR1_B_RESP_FIFO",
+	"DDR1_AW_REQ_FIFO",
+	"DDR1_AR_REQ_FIFO",
+	"DDR0_W_REQ_FIFO",
+	"DDR0_RDATA_RESP_FIFO",
+	"DDR0_R_RESP_FIFO",
+	"DDR0_B_RESP_FIFO",
+	"DDR0_AW_REQ_FIFO",
+	"DDR0_AR_REQ_FIFO"
+};
+
+typedef enum {
+	NDR_TAG_PARITY_ERROR = 0,
+	NDR_RESP_PARITY_ERROR,
+	M2S_RWD_ECC_CHECK_ERR_MULTPL_FAIL,
+	M2S_RWD_ECC_CHECK_ERR_DETECT_FAIL,
+	M2S_REQ_ECC_CHECK_ERR_MULTPL_FAIL,
+	M2S_REQ_ECC_CHECK_ERR_DETECT_FAIL,
+	DRC_TAG_PARITY_ERROR,
+	DRC_RESP_PARITY_ERROR,
+	DRC_DATA_PARITY_ERROR,
+	AW_MST_RWD_PARITY_ERROR,
+	AR_MST_REQ_PARITY_ERROR,
+	M2S_REQ_DUP_ADDR_PARITY_ERROR,
+	M2S_RWD_DUP_ADDR_PARITY_ERROR,
+	PARITY_ERROR_COUNT = 13,
+} parity_errors;
+
+char *parity_error_strings[PARITY_ERROR_COUNT] = {
+	"NDR_TAG_PARITY_ERROR",
+	"NDR_RESP_PARITY_ERROR",
+	"M2S_RWD_ECC_CHECK_ERR_MULTPL_FAIL",
+	"M2S_RWD_ECC_CHECK_ERR_DETECT_FAIL",
+	"M2S_REQ_ECC_CHECK_ERR_MULTPL_FAIL",
+	"M2S_REQ_ECC_CHECK_ERR_DETECT_FAIL",
+	"DRC_TAG_PARITY_ERROR",
+	"DRC_RESP_PARITY_ERROR",
+	"DRC_DATA_PARITY_ERROR",
+	"AW_MST_RWD_PARITY_ERROR",
+	"AR_MST_REQ_PARITY_ERROR",
+	"M2S_REQ_DUP_ADDR_PARITY_ERROR",
+	"M2S_RWD_DUP_ADDR_PARITY_ERROR",
+};
+
+typedef enum {
+	MST_M2S_RWD_ERR_MULTPL = 0,
+	MST_M2S_RWD_ERR_DETECT,
+	MST_M2S_REQ_ERR_MULTPL,
+	MST_M2S_REQ_ERR_DETECT,
+	POISON_RECEIVED_IN_RWD,
+	RWD_ADDRESS_INVALID,
+	REQ_ADDRESS_INVALID,
+	DDR1_RRESP_ERROR,
+	DDR1_BRESP_ERROR,
+	DDR0_RRESP_ERROR,
+	DDR0_BRESP_ERROR,
+	DDR1_RPARITY_ERROR,
+	DDR1_BPARITY_ERROR,
+	DDR0_RPARITY_ERROR,
+	DDR0_BPARITY_ERROR,
+	HDM_DEC1_ERR_NOT_COMMITED,
+	RX_DEINIT_TIMEOUT,
+	TX_DEINIT_TIMEOUT,
+	VIRAL,
+	DDR0_BRESP_DEC_ERROR,
+	DDR1_BRESP_DEC_ERROR,
+	DDR0_RRESP_DEC_ERROR,
+	DDR1_RRESP_DEC_ERROR,
+	MEMBRIDGE_COMMON_ERROR_COUNT = 23
+} membridge_common_errors;
+
+char *membridge_common_error_strings[MEMBRIDGE_COMMON_ERROR_COUNT] = {
+	"MST_M2S_RWD_ERR_MULTPL",
+	"MST_M2S_RWD_ERR_DETECT",
+	"MST_M2S_REQ_ERR_MULTPL",
+	"MST_M2S_REQ_ERR_DETECT",
+	"POISON_RECEIVED_IN_RWD",
+	"RWD_ADDRESS_INVALID",
+	"REQ_ADDRESS_INVALID",
+	"DDR1_RRESP_ERROR",
+	"DDR1_BRESP_ERROR",
+	"DDR0_RRESP_ERROR",
+	"DDR0_BRESP_ERROR",
+	"DDR1_RPARITY_ERROR",
+	"DDR1_BPARITY_ERROR",
+	"DDR0_RPARITY_ERROR",
+	"DDR0_BPARITY_ERROR",
+	"HDM_DEC1_ERR_NOT_COMMITED",
+	"RX_DEINIT_TIMEOUT",
+	"TX_DEINIT_TIMEOUT",
+	"VIRAL",
+	"DDR0_BRESP_DEC_ERROR",
+	"DDR1_BRESP_DEC_ERROR",
+	"DDR0_RRESP_DEC_ERROR",
+	"DDR1_RRESP_DEC_ERROR",
+};
+
+struct cxl_membridge_errors_out {
+  uint32_t fifo_overflow;
+  uint32_t fifo_overflows[FIFO_ERROR_COUNT];
+  uint32_t fifo_underflow;
+  uint32_t fifo_underflows[FIFO_ERROR_COUNT];
+  uint32_t ddr0_parity_error;
+  uint32_t ddr0_parity_errors[DDR_PARITY_ERROR_COUNT];
+  uint32_t ddr1_parity_error;
+  uint32_t ddr1_parity_errors[DDR_PARITY_ERROR_COUNT];
+  uint32_t parity_error;
+  uint32_t parity_errors[PARITY_ERROR_COUNT];
+  uint32_t common_errors[MEMBRIDGE_COMMON_ERROR_COUNT];
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_get_cxl_membridge_errors(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_membridge_errors_out *get_cxl_membridge_errors_out;
+	int rc = 0;
+	int idx;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_ERRORS_OPCODE);
+
+	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: Read failed, firmware status: %d\n",
+				cxl_memdev_get_devname(memdev), rc);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_ERRORS) {
+		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_CXL_MEMBRIDGE_ERRORS);
+		return -EINVAL;
+	}
+
+	get_cxl_membridge_errors_out = (void *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "fifo_overflow errors : %d\n", get_cxl_membridge_errors_out->fifo_overflow);
+	for(idx = 0; idx < FIFO_ERROR_COUNT; idx++) {
+		if (get_cxl_membridge_errors_out->fifo_overflows[idx] != 0)
+			fprintf(stdout, "%s : 0x%x\n", fifo_error_strings[idx],
+					get_cxl_membridge_errors_out->fifo_overflows[idx]);
+	}
+
+	fprintf(stdout, "fifo_underflow errors : %d\n", get_cxl_membridge_errors_out->fifo_underflow);
+	for(idx = 0; idx < FIFO_ERROR_COUNT; idx++) {
+		if (get_cxl_membridge_errors_out->fifo_underflows[idx] != 0)
+			fprintf(stdout, "%s : 0x%x\n", fifo_error_strings[idx],
+					get_cxl_membridge_errors_out->fifo_underflows[idx]);
+	}
+
+	fprintf(stdout, "ddr0 parity errors : %d\n", get_cxl_membridge_errors_out->ddr0_parity_error);
+	for(idx = 0; idx < DDR_PARITY_ERROR_COUNT; idx++) {
+		if (get_cxl_membridge_errors_out->ddr0_parity_errors[idx] != 0)
+			fprintf(stdout, "%s : 0x%x\n", ddr_parity_error_strings[idx],
+					get_cxl_membridge_errors_out->ddr0_parity_errors[idx]);
+	}
+
+	fprintf(stdout, "ddr1 parity errors : %d\n", get_cxl_membridge_errors_out->ddr1_parity_error);
+	for(idx = 0; idx < DDR_PARITY_ERROR_COUNT; idx++) {
+		if (get_cxl_membridge_errors_out->ddr1_parity_errors[idx] != 0)
+			fprintf(stdout, "%s : 0x%x\n", ddr_parity_error_strings[idx],
+					get_cxl_membridge_errors_out->ddr1_parity_errors[idx]);
+	}
+
+	fprintf(stdout, "membridge common errors :\n");
+	for(idx = 0; idx < MEMBRIDGE_COMMON_ERROR_COUNT; idx++) {
+		if (get_cxl_membridge_errors_out->common_errors[idx] != 0)
+			fprintf(stdout, "%s : 0x%x\n", membridge_common_error_strings[idx],
+					get_cxl_membridge_errors_out->common_errors[idx]);
+	}
+
+	fprintf(stdout, "parity errors : %d\n", get_cxl_membridge_errors_out->parity_error);
+	for(idx = 0; idx < PARITY_ERROR_COUNT; idx++) {
+		if (get_cxl_membridge_errors_out->parity_errors[idx] != 0)
+			fprintf(stdout, "%s : 0x%x\n", parity_error_strings[idx],
+					get_cxl_membridge_errors_out->parity_errors[idx]);
+	}
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_DDR_BW CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_DDR_BW_OPCODE 0xFB09
+
+struct cxl_get_ddr_bw_in {
+	u32 timeout;
+	u32 iterations;
+}  __attribute__((packed));
+
+typedef enum {
+  DDR_CTRL0 = 0,
+  DDR_CTRL1 = 1,
+  DDR_MAX_SUBSYS,
+} ddr_subsys;
+
+struct cxl_get_ddr_bw_out {
+	float peak_bw[DDR_MAX_SUBSYS];
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_get_ddr_bw(struct cxl_memdev *memdev, u32 timeout, u32 iterations)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_get_ddr_bw_in *get_ddr_bw_in;
+	struct cxl_get_ddr_bw_out *get_ddr_bw_out;
+	float total_peak_bw = 0;
+	int rc = 0;
+	int i;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_DDR_BW_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	get_ddr_bw_in = (void *) cmd->send_cmd->in.payload;
+
+	get_ddr_bw_in->timeout = timeout;
+	get_ddr_bw_in->iterations = iterations;
+	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: Read failed, firmware status: %d\n",
+				cxl_memdev_get_devname(memdev), rc);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_DDR_BW) {
+		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_DDR_BW);
+		return -EINVAL;
+	}
+	get_ddr_bw_out = (void *)cmd->send_cmd->out.payload;
+	for(i = 0; i < DDR_MAX_SUBSYS; i++) {
+		fprintf(stdout, "ddr%d peak bandwidth = %f GB/s\n", i, get_ddr_bw_out->peak_bw[i]);
+		total_peak_bw += get_ddr_bw_out->peak_bw[i];
+	}
+	fprintf(stdout, "total peak bandwidth = %f GB/s\n", total_peak_bw);
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_I2C_READ CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_I2C_READ_OPCODE 0xFB10
+#define I2C_MAX_SIZE_NUM_BYTES 128
+
+struct cxl_i2c_read_in {
+	u16 slave_addr;
+	u8 reg_addr;
+	u8 num_bytes;
+}  __attribute__((packed));
+
+struct cxl_i2c_read_out {
+	char buf[I2C_MAX_SIZE_NUM_BYTES];
+	u8 num_bytes;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_i2c_read(struct cxl_memdev *memdev, u16 slave_addr, u8 reg_addr, u8 num_bytes)
+{
+        struct cxl_cmd *cmd;
+        struct cxl_mem_query_commands *query;
+        struct cxl_command_info *cinfo;
+        struct cxl_i2c_read_in *i2c_read_in;
+        struct cxl_i2c_read_out *i2c_read_out;
+        int rc = 0;
+        int i;
+
+	if(num_bytes > I2C_MAX_SIZE_NUM_BYTES) {
+                fprintf(stderr, "%s: Max number of bytes supported is %d, cmd submission failed: %d (%s)\n",
+                                cxl_memdev_get_devname(memdev), I2C_MAX_SIZE_NUM_BYTES, rc, strerror(-rc));
+                return -EINVAL;
+	}
+
+        cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_I2C_READ_OPCODE);
+        if (!cmd) {
+                fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+                                cxl_memdev_get_devname(memdev));
+                return -ENOMEM;
+        }
+
+        query = cmd->query_cmd;
+        cinfo = &query->commands[cmd->query_idx];
+
+        /* used to force correct payload size */
+        cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+        if (cinfo->size_in > 0) {
+                cmd->input_payload = calloc(1, cinfo->size_in);
+                if (!cmd->input_payload)
+                        return -ENOMEM;
+                cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+                cmd->send_cmd->in.size = cinfo->size_in;
+        }
+
+        i2c_read_in = (void *) cmd->send_cmd->in.payload;
+
+        i2c_read_in->slave_addr = slave_addr;
+        i2c_read_in->reg_addr = reg_addr;
+        i2c_read_in->num_bytes= num_bytes;
+
+        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: Read failed, firmware status: %d\n",
+                                cxl_memdev_get_devname(memdev), rc);
+                goto out;
+        }
+
+        if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_I2C_READ) {
+                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_I2C_READ);
+                return -EINVAL;
+        }
+        i2c_read_out = (void *)cmd->send_cmd->out.payload;
+        fprintf(stdout, "i2c read output:");
+        for(i = 0; i < i2c_read_out->num_bytes; i++) {
+                fprintf(stdout, "0x%x\t", i2c_read_out->buf[i]);
+        }
+        fprintf(stdout, "\n");
+
+out:
+        cxl_cmd_unref(cmd);
+        return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_I2C_WRITE CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_I2C_WRITE_OPCODE 0xFB11
+
+struct cxl_i2c_write_in {
+        u16 slave_addr;
+        u8 reg_addr;
+        u8 data;
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_i2c_write(struct cxl_memdev *memdev, u16 slave_addr, u8 reg_addr, u8 data)
+{
+        struct cxl_cmd *cmd;
+        struct cxl_mem_query_commands *query;
+        struct cxl_command_info *cinfo;
+        struct cxl_i2c_write_in *i2c_write_in;
+        int rc = 0;
+
+        cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_I2C_WRITE_OPCODE);
+        if (!cmd) {
+                fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+                                cxl_memdev_get_devname(memdev));
+                return -ENOMEM;
+        }
+
+        query = cmd->query_cmd;
+        cinfo = &query->commands[cmd->query_idx];
+
+        /* used to force correct payload size */
+        cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+        if (cinfo->size_in > 0) {
+                cmd->input_payload = calloc(1, cinfo->size_in);
+                if (!cmd->input_payload)
+                        return -ENOMEM;
+                cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+                cmd->send_cmd->in.size = cinfo->size_in;
+        }
+
+        i2c_write_in = (void *) cmd->send_cmd->in.payload;
+
+        i2c_write_in->slave_addr = slave_addr;
+        i2c_write_in->reg_addr = reg_addr;
+        i2c_write_in->data = data;
+
+        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: Read failed, firmware status: %d\n",
+                                cxl_memdev_get_devname(memdev), rc);
+                goto out;
+        }
+
+        if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_I2C_WRITE) {
+                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_I2C_WRITE);
+                return -EINVAL;
+        }
+		fprintf(stdout, "i2c write success\n");
+
+out:
+        cxl_cmd_unref(cmd);
+        return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_DDR_LATENCY CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_DDR_LATENCY_OPCODE 0xFB12
+
+struct ddr_lat_op {
+    uint64_t readlat;
+    uint64_t writelat;
+    uint32_t rdsamplecnt;
+    uint32_t wrsamplecnt;
+    float avg_rdlatency;
+    float avg_wrlatency;
+};
+
+struct cxl_get_ddr_latency_in {
+	u32 measure_time;
+}  __attribute__((packed));
+
+struct cxl_get_ddr_latency_out {
+	struct ddr_lat_op ddr_lat_op[DDR_MAX_SUBSYS];
+}  __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_get_ddr_latency(struct cxl_memdev *memdev, u32 measure_time)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_get_ddr_latency_in *get_ddr_lat_in;
+	struct cxl_get_ddr_latency_out *get_ddr_lat_out;
+	int rc = 0;
+	int ddr_id;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_DDR_LATENCY_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	get_ddr_lat_in = (void *) cmd->send_cmd->in.payload;
+
+	get_ddr_lat_in->measure_time = measure_time;
+	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: Read failed, firmware status: %d\n",
+				cxl_memdev_get_devname(memdev), rc);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_DDR_LATENCY) {
+		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_DDR_LATENCY);
+		return -EINVAL;
+	}
+	get_ddr_lat_out = (void *)cmd->send_cmd->out.payload;
+	for(ddr_id = 0; ddr_id < DDR_MAX_SUBSYS; ddr_id++) {
+		fprintf(stdout, "\nDDR%d Latency:\n", ddr_id);
+		fprintf(stdout,
+		       "readLat: %lu, rdSampleCnt: %u\n, writeLat: %lu, wrSampleCnt: %u\n",
+		       get_ddr_lat_out->ddr_lat_op[ddr_id].readlat,
+		       get_ddr_lat_out->ddr_lat_op[ddr_id].rdsamplecnt,
+		       get_ddr_lat_out->ddr_lat_op[ddr_id].writelat,
+		       get_ddr_lat_out->ddr_lat_op[ddr_id].wrsamplecnt);
+
+		fprintf(stdout, "Average Latency:\n");
+		fprintf(stdout,
+			"Avg Read Latency  : %f ns \n Avg Write Latency : %f ns \n",
+			get_ddr_lat_out->ddr_lat_op[ddr_id].avg_rdlatency,
+			get_ddr_lat_out->ddr_lat_op[ddr_id].avg_wrlatency);
+	}
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_DDR_ECC_ERR_INFO CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_DDR_ECC_ERR_INFO_OPCODE 0xFB0F
+
+struct ddr_parity_err {
+  uint32_t parity_crit_bit2_cnt; /* Parity error on the address/control bus*/
+  uint32_t parity_crit_bit1_cnt; /* Overlapping write data parity error */
+  uint32_t parity_crit_bit0_cnt; /* Write data parity error */
+};
+
+struct ddr_dfi_err {
+  uint32_t dfi_crit_bit5_cnt; /* DFI tINIT_COMPLETE value has timed out */
+  uint32_t dfi_crit_bit2_cnt; /* Error received from the PHY on the DFI bus */
+
+  uint32_t dfi_warn_bit1_cnt; /* DFI PHY Master Interface error has occurred */
+  uint32_t dfi_warn_bit0_cnt; /* DFI update error has occurred */
+};
+
+struct ddr_crc_err {
+  uint32_t crc_crit_bit1_cnt; /* CA Parity or a CRC error happened during CRC
+                                Retry. */
+  uint32_t crc_crit_bit0_cnt; /* CRC error occurred on the write data bus */
+};
+
+struct ddr_userif_err {
+  uint32_t
+      userif_crit_bit2_cnt; /* Error occurred on the port command channel. */
+  uint32_t userif_crit_bit1_cnt; /* Multiple accesses outside the defined
+                                    PHYSICAL memory space have occurred. */
+  uint32_t userif_crit_bit0_cnt; /* A Memory access outside the defined PHYSICAL
+                                    memory space has occurred */
+};
+
+struct ddr_ecc_err {
+  uint32_t ecc_warn_bit6_cnt; /* One or more ECC writeback commands
+                                could not be executed */
+  uint32_t ecc_crit_bit3_cnt; /* Multiple uncorrectable ECC events
+                                have been detected */
+  uint32_t ecc_crit_bit2_cnt; /* A uncorrectable ECC event has been detected */
+  uint32_t ecc_crit_bit8_cnt; /* An ECC correctable error has been detected in a
+                                 scrubbing read operation */
+  uint32_t ecc_warn_bit1_cnt; /* Multiple correctable ECC events
+                                 have been detected */
+  uint32_t ecc_warn_bit0_cnt; /* A correctable ECC event has been detected */
+};
+
+struct ddr_controller_errors {
+  struct ddr_parity_err parity;
+  struct ddr_dfi_err dfi;
+  struct ddr_crc_err crc;
+  struct ddr_userif_err userif;
+  struct ddr_ecc_err ecc;
+};
+
+struct cxl_get_ddr_ecc_err_info_out {
+	struct ddr_controller_errors ddr_ctrl_err[DDR_MAX_SUBSYS];
+} __attribute__((packed));
+
+void display_error_count(struct ddr_controller_errors *ddr_ctrl_err, ddr_subsys ddr_id);
+
+void display_error_count(struct ddr_controller_errors *ddr_ctrl_err, ddr_subsys ddr_id) {
+  if (ddr_ctrl_err[ddr_id].parity.parity_crit_bit2_cnt) {
+    fprintf(stdout,
+        "DDR-%d: FATAL: Parity error on the address/control bus "
+        "(parity_crit_bit2_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].parity.parity_crit_bit2_cnt);
+  }
+  if (ddr_ctrl_err[ddr_id].parity.parity_crit_bit1_cnt) {
+    fprintf(stdout,
+        "DDR-%d: FATAL: Overlapping write data parity error "
+        "(parity_crit_bit1_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].parity.parity_crit_bit1_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].parity.parity_crit_bit0_cnt) {
+    fprintf(stdout,
+        "DDR-%d: FATAL: Write data parity error "
+        "(parity_crit_bit0_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].parity.parity_crit_bit0_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].dfi.dfi_crit_bit5_cnt) {
+    fprintf(stdout,
+        "DDR-%d: FATAL: DFI tINIT_COMPLETE value has timed out "
+        "(dfi_crit_bit5_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].dfi.dfi_crit_bit5_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].dfi.dfi_crit_bit2_cnt) {
+    fprintf(stdout,
+        "DDR-%d: FATAL : Error received from the PHY on the DFI bus "
+        "(dfi_crit_bit2_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].dfi.dfi_crit_bit2_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].dfi.dfi_warn_bit1_cnt) {
+    fprintf(stdout,
+        "DDR-%d: WARN: DFI PHY Master Interface error has occurred "
+        "(dfi_warn_bit1_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].dfi.dfi_warn_bit1_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].dfi.dfi_warn_bit0_cnt) {
+    fprintf(stdout,
+        "DDR-%d: WARN: DFI update error has occurred "
+        "(dfi_warn_bit0_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].dfi.dfi_warn_bit0_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].crc.crc_crit_bit1_cnt) {
+    fprintf(stdout,
+        "DDR-%d: FATAL: CA Parity or a CRC error happened during CRC Retry "
+        "(crc_crit_bit1_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].crc.crc_crit_bit1_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].crc.crc_crit_bit0_cnt) {
+    fprintf(stdout,
+        "DDR-%d: FATAL: CRC error occurred on the write data bus "
+        "(crc_crit_bit0_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].crc.crc_crit_bit0_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].userif.userif_crit_bit2_cnt) {
+    fprintf(stdout,
+        "DDR-%d: FATAL: Error occurred on the port command channel "
+        "(userif_crit_bit2_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].userif.userif_crit_bit2_cnt);
+  }
+  if (ddr_ctrl_err[ddr_id].userif.userif_crit_bit1_cnt) {
+    fprintf(stdout,
+        "DDR-%d: FATAL: Multiple accesses outside the defined PHYSICAL "
+        "memory space have occurred "
+        "(userif_crit_bit1_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].userif.userif_crit_bit1_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].userif.userif_crit_bit0_cnt) {
+    fprintf(stdout,
+        "DDR-%d: FATAL: A Memory access outside the defined PHYSICAL "
+        "memory space has occurred "
+        "(userif_crit_bit0_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].userif.userif_crit_bit0_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit6_cnt) {
+    fprintf(stdout,
+        "DDR-%d: WARN: One or more ECC writeback commands "
+        "could not be executed "
+        "(ecc_warn_bit6_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit6_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit3_cnt) {
+    fprintf(stdout,
+        "DDR-%d:FATAL: Multiple uncorrectable ECC events have been detected "
+        "(ecc_crit_bit3_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit3_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit2_cnt) {
+    fprintf(stdout,
+        "DDR-%d: FATAL: A uncorrectable ECC event has been detected "
+        "(ecc_crit_bit2_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit2_cnt);
+  }
+ if (ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit8_cnt) {
+    fprintf(stdout,
+        "DDR-%d: CRIT: An ECC correctable error has been detected "
+        "in a scrubbing read operation "
+        "(ecc_crit_bit8_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit8_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit1_cnt) {
+    fprintf(stdout,
+        "DDR-%d: WARN: Multiple correctable ECC events have been detected "
+        "(ecc_warn_bit1_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit1_cnt);
+  }
+
+  if (ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit0_cnt) {
+    fprintf(stdout,
+        "DDR-%d: WARN: A correctable ECC event has been detected "
+        "(ecc_warn_bit0_cnt= %u)\n",
+        ddr_id,
+        ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit0_cnt);
+  }
+}
+
+CXL_EXPORT int cxl_memdev_get_ddr_ecc_err_info(struct cxl_memdev *memdev)
+{
+        struct cxl_cmd *cmd;
+        struct cxl_mem_query_commands *query;
+        struct cxl_command_info *cinfo;
+        struct cxl_get_ddr_ecc_err_info_out *get_ddr_ecc_err_info_out;
+        int rc = 0;
+
+        cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_DDR_ECC_ERR_INFO_OPCODE);
+        if (!cmd) {
+                fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+                                cxl_memdev_get_devname(memdev));
+                return -ENOMEM;
+        }
+
+        query = cmd->query_cmd;
+        cinfo = &query->commands[cmd->query_idx];
+
+        /* used to force correct payload size */
+        cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+        if (cinfo->size_in > 0) {
+                cmd->input_payload = calloc(1, cinfo->size_in);
+                if (!cmd->input_payload)
+                        return -ENOMEM;
+                cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+                cmd->send_cmd->in.size = cinfo->size_in;
+        }
+
+        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: Read failed, firmware status: %d\n",
+                                cxl_memdev_get_devname(memdev), rc);
+                goto out;
+        }
+
+        if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_DDR_ECC_ERR_INFO) {
+                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_DDR_ECC_ERR_INFO);
+                return -EINVAL;
+        }
+        get_ddr_ecc_err_info_out = (void *)cmd->send_cmd->out.payload;
+	display_error_count(get_ddr_ecc_err_info_out->ddr_ctrl_err, DDR_CTRL0);
+	display_error_count(get_ddr_ecc_err_info_out->ddr_ctrl_err, DDR_CTRL1);
+
+out:
+        cxl_cmd_unref(cmd);
+        return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_START_DDR_ECC_SCRUB CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_START_DDR_ECC_SCRUB_OPCODE 0xFB15
+
+CXL_EXPORT int cxl_memdev_start_ddr_ecc_scrub(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_START_DDR_ECC_SCRUB_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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: Read failed, firmware status: %d\n",
+				cxl_memdev_get_devname(memdev), rc);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_START_DDR_ECC_SCRUB) {
+		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_START_DDR_ECC_SCRUB);
+		return -EINVAL;
+	}
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_ECC_SCRUB_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_ECC_SCRUB_STATUS_OPCODE 0xFB16
+
+
+struct cxl_ddr_ecc_scrub_status_out {
+  int ecc_scrub_status[DDR_MAX_SUBSYS];
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_ddr_ecc_scrub_status(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_ddr_ecc_scrub_status_out *ddr_ecc_scrub_status_out;
+	int rc = 0;
+	int subsys;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_ECC_SCRUB_STATUS_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_ECC_SCRUB_STATUS) {
+		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_DDR_ECC_SCRUB_STATUS);
+		return -EINVAL;
+	}
+	ddr_ecc_scrub_status_out = (void *)cmd->send_cmd->out.payload;
+	for(subsys = DDR_CTRL0; subsys < DDR_MAX_SUBSYS; subsys++)
+	{
+		fprintf(stdout, "DDR-%d %s\n", subsys, ddr_ecc_scrub_status_out->ecc_scrub_status[subsys] ?
+				"ECC SCRUB IS IN PROGRESS" : "DDR SCRUB IS NOT RUNNING/FINISHED");
+	}
+
+out:
+        cxl_cmd_unref(cmd);
+        return rc;
+}
+
+/* DDR CONTINUOUS SCRUB STATUS */
+
+#define CXL_MEM_COMMAND_ID_DDR_CONT_SCRUB_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_CONT_SCRUB_STATUS_OPCODE 0xFB28
+
+struct cxl_ddr_cont_scrub_status_out {
+  uint32_t cont_scrub_status;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_cont_scrub_status(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_ddr_cont_scrub_status_out *ddr_cont_scrub_status_out;
+	int rc = 0;
+	int subsys;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_CONT_SCRUB_STATUS_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_CONT_SCRUB_STATUS) {
+		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_DDR_CONT_SCRUB_STATUS);
+		return -EINVAL;
+	}
+	ddr_cont_scrub_status_out = (void *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "%s\n", ddr_cont_scrub_status_out->cont_scrub_status ?
+		"CONTINUOUS SCRUB IS ON" : "CONTINUOUS SCRUB IS OFF");
+
+out:
+        cxl_cmd_unref(cmd);
+        return rc;
+}
+
+/* DDR CONTINUOUS SCRUB SET */
+#define CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET_OPCODE 0xFB29
+#define CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET_PAYLOAD_IN_SIZE 4
+
+struct cxl_mbox_ddr_cont_scrub_set_in {
+  uint32_t cont_scrub_status;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_cont_scrub_set(struct cxl_memdev *memdev, uint32_t cont_scrub_status)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_mbox_ddr_cont_scrub_set_in *ddr_cont_scrub_set_in;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	ddr_cont_scrub_set_in = (void *) cmd->send_cmd->in.payload;
+
+	ddr_cont_scrub_set_in->cont_scrub_status = cont_scrub_status;
+	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_DDR_CONT_SRUB_SET) {
+		 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_DDR_CONT_SRUB_SET);
+		return -EINVAL;
+	}
+
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_INIT_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_INIT_STATUS_OPCODE 0xFB17
+
+typedef enum {
+  DDR_INIT_INPROGRESS = 0,
+  DDR_INIT_PASSED = 1,
+  DDR_INIT_FAILED = -1,
+  DDR_INIT_FAILED_NO_CH0_DIMM0 = -2,
+  DDR_INIT_FAILED_UNKNOWN_DIMM = -3,
+} ddr_status;
+
+typedef enum {
+  CH_0 = 0,
+  CH_1 = 1,
+  CH_NA = -1,
+} f_channel_id;
+
+struct ddr_init_boot_status {
+  int8_t ddr_init_status;
+  int8_t failed_channel_id;
+  char failed_dimm_silk_screen;
+};
+
+struct cxl_ddr_init_status_out {
+struct ddr_init_boot_status init_status;
+} __packed;
+
+CXL_EXPORT int cxl_memdev_ddr_init_status(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_ddr_init_status_out *ddr_init_status_out;
+	int rc = 0;
+	int8_t status;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_INIT_STATUS_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_INIT_STATUS) {
+		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_DDR_INIT_STATUS);
+		return -EINVAL;
+	}
+	ddr_init_status_out = (void *)cmd->send_cmd->out.payload;
+	status = ddr_init_status_out->init_status.ddr_init_status;
+	switch (status)
+	{
+		case DDR_INIT_INPROGRESS:
+				fprintf(stdout, "DDR INIT IS IN PROGRESS\n");
+				break;
+		case DDR_INIT_PASSED:
+				fprintf(stdout, "DDR INIT PASSED\n");
+				break;
+		case DDR_INIT_FAILED:
+				fprintf(stdout, "DDR INIT FAILED for CH:%d DIMM:%c\n",
+					ddr_init_status_out->init_status.failed_channel_id,
+					ddr_init_status_out->init_status.failed_dimm_silk_screen);
+
+				fprintf(stdout, "RECOVERY REMEDY: REPLACE CH:%d DIMM:%c and RE-TRY\n",
+					ddr_init_status_out->init_status.failed_channel_id,
+					ddr_init_status_out->init_status.failed_dimm_silk_screen);
+				break;
+		case DDR_INIT_FAILED_NO_CH0_DIMM0:
+				fprintf(stdout, "DDR INIT FAILED. CH:%d DIMM:%c is NOT PLUGGED IN\n",
+					ddr_init_status_out->init_status.failed_channel_id,
+					ddr_init_status_out->init_status.failed_dimm_silk_screen);
+
+				fprintf(stdout, "RECOVERY REMEDY: PLUG IN CH:%d DIMM:%c\n",
+					ddr_init_status_out->init_status.failed_channel_id,
+					ddr_init_status_out->init_status.failed_dimm_silk_screen);
+				break;
+		case DDR_INIT_FAILED_UNKNOWN_DIMM:
+				fprintf(stdout, "DDR INIT FAILED. UN-SUPPORTED/UNKNOWN DIMM\n");
+				fprintf(stdout, "RECOVERY REMEDY: PLUG IN SUPPORTED DIMMs\n");
+				break;
+		default:
+				fprintf(stdout, "DDR INIT STATUS invalid\n");
+	}
+
+out:
+        cxl_cmd_unref(cmd);
+        return rc;
+}
+
+struct cxl_cmd_membridge_stats_out {
+  // mem transaction counters
+  uint64_t m2s_req_count;
+  uint64_t m2s_rwd_count;
+  uint64_t s2m_drs_count;
+  uint64_t s2m_ndr_count;
+  // HPA logs for poison & out-of-range
+  uint64_t rwd_first_poison_hpa_log;
+  uint64_t rwd_latest_poison_hpa_log;
+  uint64_t req_first_hpa_log;
+  uint64_t rwd_first_hpa_log;
+  // correctible errors counters
+  uint32_t mst_m2s_req_corr_err_count;
+  uint32_t mst_m2s_rwd_corr_err_count;
+  // membridge fifo full/empty status
+  uint32_t fifo_full_status;
+  uint32_t fifo_empty_status;
+  // credit counters
+  uint8_t m2s_rwd_credit_count;
+  uint8_t m2s_req_credit_count;
+  uint8_t s2m_ndr_credit_count;
+  uint8_t s2m_drc_credit_count;
+  // rx state machine status 0
+  uint8_t rx_fsm_status_rx_deinit;
+  uint8_t rx_fsm_status_m2s_req;
+  uint8_t rx_fsm_status_m2s_rwd;
+  uint8_t rx_fsm_status_ddr0_ar_req;
+    uint8_t rx_fsm_status_ddr0_aw_req;
+  uint8_t rx_fsm_status_ddr0_w_req;
+  // rx state machine status 1
+  uint8_t rx_fsm_status_ddr1_ar_req;
+  uint8_t rx_fsm_status_ddr1_aw_req;
+  uint8_t rx_fsm_status_ddr1_w_req;
+  // tx state machine status 0
+  uint8_t tx_fsm_status_tx_deinit;
+  uint8_t tx_fsm_status_s2m_ndr;
+  uint8_t tx_fsm_status_s2m_drc;
+  // stat QoS TEL
+  uint8_t stat_qos_tel_dev_load_read;
+  uint8_t stat_qos_tel_dev_load_type2_read;
+  uint8_t stat_qos_tel_dev_load_write;
+  uint8_t resvd;
+} __attribute__((packed));
+
+#define CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_STATS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_STATS_OPCODE 0xFB18
+
+CXL_EXPORT int cxl_memdev_get_cxl_membridge_stats(struct cxl_memdev *memdev)
+{
+        struct cxl_cmd *cmd;
+        struct cxl_cmd_membridge_stats_out *stats;
+        int rc = 0;
+
+        cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_STATS_OPCODE);
+
+        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: Read failed, firmware status: %d\n",
+                                cxl_memdev_get_devname(memdev), rc);
+                goto out;
+        }
+
+        if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_STATS) {
+                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_CXL_MEMBRIDGE_STATS);
+                return -EINVAL;
+        }
+
+        stats = (void *)cmd->send_cmd->out.payload;
+        // print membridge statistics info
+        fprintf(stderr, "m2s_req_count:              %lu\n", stats->m2s_req_count);
+        fprintf(stderr, "m2s_rwd_count:              %lu\n", stats->m2s_rwd_count);
+        fprintf(stderr, "s2m_drs_count:              %lu\n", stats->s2m_drs_count);
+        fprintf(stderr, "s2m_ndr_count:              %lu\n", stats->s2m_ndr_count);
+        fprintf(stderr, "rwd_first_poison_hpa:       0x%lx\n", stats->rwd_first_poison_hpa_log);
+        fprintf(stderr, "rwd_latest_poison_hpa:      0x%lx\n", stats->rwd_latest_poison_hpa_log);
+        fprintf(stderr, "req_first_hpa_log:          0x%lx\n", stats->req_first_hpa_log);
+        fprintf(stderr, "rwd_first_hpa_log:          0x%lx\n", (u64)stats->rwd_first_hpa_log);
+        fprintf(stderr, "m2s_req_corr_err_count:     %u\n", stats->mst_m2s_req_corr_err_count);
+        fprintf(stderr, "m2s_rwd_corr_err_count:     %u\n", stats->mst_m2s_rwd_corr_err_count);
+        fprintf(stderr, "fifo_full_status:           0x%x\n", stats->fifo_full_status);
+        fprintf(stderr, "fifo_empty_status:          0x%x\n", stats->fifo_empty_status);
+        fprintf(stderr, "m2s_rwd_credit_count:       %u\n", stats->m2s_rwd_credit_count);
+        fprintf(stderr, "m2s_req_credit_count:       %u\n", stats->m2s_req_credit_count);
+        fprintf(stderr, "s2m_ndr_credit_count:       %u\n", stats->s2m_ndr_credit_count);
+        fprintf(stderr, "s2m_drc_credit_count:       %u\n", stats->s2m_drc_credit_count);
+        fprintf(stderr, "rx_status_rx_deinit:        0x%x\n", stats->rx_fsm_status_rx_deinit);
+        fprintf(stderr, "rx_status_m2s_req:          0x%x\n", stats->rx_fsm_status_m2s_req);
+        fprintf(stderr, "rx_status_m2s_rwd:          0x%x\n", stats->rx_fsm_status_m2s_rwd);
+        fprintf(stderr, "rx_status_ddr0_ar_req:      0x%x\n", stats->rx_fsm_status_ddr0_ar_req);
+        fprintf(stderr, "rx_status_ddr0_aw_req:      0x%x\n", stats->rx_fsm_status_ddr0_aw_req);
+        fprintf(stderr, "rx_status_ddr0_w_req:       0x%x\n", stats->rx_fsm_status_ddr0_w_req);
+        fprintf(stderr, "rx_status_ddr1_ar_req:      0x%x\n", stats->rx_fsm_status_ddr1_ar_req);
+        fprintf(stderr, "rx_status_ddr1_aw_req:      0x%x\n", stats->rx_fsm_status_ddr1_aw_req);
+        fprintf(stderr, "rx_status_ddr1_w_req:       0x%x\n", stats->rx_fsm_status_ddr1_w_req);
+        fprintf(stderr, "tx_status_tx_deinit:        0x%x\n", stats->tx_fsm_status_tx_deinit);
+        fprintf(stderr, "tx_status_s2m_ndr:          0x%x\n", stats->tx_fsm_status_s2m_ndr);
+        fprintf(stderr, "tx_status_s2m_drc:          0x%x\n", stats->tx_fsm_status_s2m_drc);
+        fprintf(stderr, "qos_tel_dev_load_read:      %u\n", stats->stat_qos_tel_dev_load_read);
+        fprintf(stderr, "qos_tel_dev_load_type2_read:%u\n", stats->stat_qos_tel_dev_load_type2_read);
+        fprintf(stderr, "qos_tel_dev_load_write:     %u\n", stats->stat_qos_tel_dev_load_write);
+
+out:
+        cxl_cmd_unref(cmd);
+        return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_TRIGGER_COREDUMP CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_TRIGGER_COREDUMP_OPCODE 0xFB1A
+
+CXL_EXPORT int cxl_memdev_trigger_coredump(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_TRIGGER_COREDUMP_OPCODE);
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_TRIGGER_COREDUMP) {
+                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_TRIGGER_COREDUMP);
+                return -EINVAL;
+        }
+
+out:
+        cxl_cmd_unref(cmd);
+        return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_ERR_INJ_EN CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_ERR_INJ_EN_OPCODE 0xFB19
+
+
+struct cxl_ddr_err_inj_en_in {
+	uint32_t ddr_id;
+	uint32_t err_type;
+	uint64_t ecc_fwc_mask;
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_ddr_err_inj_en(struct cxl_memdev *memdev, u32 ddr_id, u32 err_type, u64 ecc_fwc_mask)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_ddr_err_inj_en_in *ddr_err_inj_en_in;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_ERR_INJ_EN_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	ddr_err_inj_en_in = (void *) cmd->send_cmd->in.payload;
+	ddr_err_inj_en_in->ddr_id = ddr_id;
+	ddr_err_inj_en_in->err_type = err_type;
+	ddr_err_inj_en_in->ecc_fwc_mask = ecc_fwc_mask;
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_ERR_INJ_EN) {
+		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_DDR_ERR_INJ_EN);
+		return -EINVAL;
+	}
+	fprintf(stderr, "Error injection enabled on DDR%d\n", ddr_id);
+
+out:
+        cxl_cmd_unref(cmd);
+        return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_DIMM_LEVEL_TRAINING_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_DIMM_LEVEL_TRAINING_STATUS_OPCODE 0xFB20
+
+#define DDR_MAX_CS 4
+#define DDR_CS_DEVICE_MAX 18
+#define DDR_REG_MAX_NIBBLE 9
+#define DDR_MAX_SLICE 9
+#define DDR_MAX_SLICE_BIT 8
+
+struct ddr_phy_pll_status {
+	uint32_t bs0_status;
+	uint32_t bs1_status;
+};
+
+struct ddr_wr_levelling_status {
+	uint32_t lower_nibble_err[DDR_REG_MAX_NIBBLE];
+	uint32_t upper_nibble_err[DDR_REG_MAX_NIBBLE];
+};
+
+struct ddr_read_gate_training_status {
+	uint32_t lower_nibble_min_err[DDR_REG_MAX_NIBBLE];
+	uint32_t lower_nibble_max_err[DDR_REG_MAX_NIBBLE];
+	uint32_t upper_nibble_min_err[DDR_REG_MAX_NIBBLE];
+	uint32_t upper_nibble_max_err[DDR_REG_MAX_NIBBLE];
+};
+
+struct ddr_margin_vref_data {
+	float  lower_nibble_vref_low_volt[DDR_REG_MAX_NIBBLE];
+	float  lower_nibble_vref_high_volt[DDR_REG_MAX_NIBBLE];
+	float  upper_nibble_vref_low_volt[DDR_REG_MAX_NIBBLE];
+	float  upper_nibble_vref_high_volt[DDR_REG_MAX_NIBBLE];
+};
+
+struct ddr_margin_write_dq_vref_data {
+	float  vref_low_volt[DDR_CS_DEVICE_MAX];
+	float  vref_high_volt[DDR_CS_DEVICE_MAX];
+};
+
+struct ddr_margin_write_dq_vref_data_cs {
+	float  vref_low_volt_cs[DDR_MAX_CS][DDR_CS_DEVICE_MAX];
+	float  vref_high_volt_cs[DDR_MAX_CS][DDR_CS_DEVICE_MAX];
+};
+
+struct ddr_margin_rdlvl_delay_dqs_rise_data {
+	uint32_t te_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+	uint32_t le_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+	float te_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+	float le_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+};
+
+struct ddr_margin_rdlvl_delay_dqs_fall_data {
+	uint32_t te_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+	uint32_t le_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+	float te_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+	float le_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+};
+
+struct ddr_margin_wrdqlvl_delay_data {
+	uint32_t te_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+	uint32_t le_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+	float te_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+	float le_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+};
+
+struct ddr_dimm_training_status {
+	struct ddr_phy_pll_status phy_pll_status;
+	struct ddr_wr_levelling_status wr_levl_status;
+	struct ddr_read_gate_training_status rd_gate_tr_status;
+	struct ddr_margin_vref_data vref_data;
+	struct ddr_margin_write_dq_vref_data wdq_vref_data;
+	struct ddr_margin_write_dq_vref_data_cs wdq_vref_data_cs;
+	struct ddr_margin_rdlvl_delay_dqs_rise_data rddqslvl_rise_data;
+	struct ddr_margin_rdlvl_delay_dqs_fall_data rddqslvl_fall_data;
+	struct ddr_margin_wrdqlvl_delay_data wrdqlvl_delay_data;
+	uint32_t err_status;
+};
+
+struct cxl_ddr_dimm_level_training_status_out {
+	struct ddr_dimm_training_status dimm_training_status[2];
+} __attribute__((packed));
+
+void print_ddr_training_status(uint32_t instance, struct ddr_dimm_training_status *dimm_tr_status);
+void print_read_gate_training_status(uint32_t instance, struct ddr_read_gate_training_status* rd_gate_tr_status);
+void print_write_levelling_status(uint32_t instance, struct ddr_wr_levelling_status* wr_levl_status);
+void print_ddr_phy_pll_status(uint32_t instance, struct ddr_phy_pll_status* phy_pll_status);
+void print_ddr_training_status(uint32_t instance, struct ddr_dimm_training_status *dimm_tr_status);
+void print_margin_vref_low_high(uint32_t instance, struct ddr_dimm_training_status *dimm_tr_status);
+void print_margin_rdlvl_delay_window(int instance, struct ddr_dimm_training_status *dimm_tr_status);
+void print_margin_wrdqlvl_delay_window(int instance, struct ddr_dimm_training_status *dimm_tr_status);
+void print_err_status(int instance, struct ddr_dimm_training_status *dimm_tr_status);
+
+/* DDR phy pll status */
+void print_ddr_phy_pll_status(uint32_t instance, struct ddr_phy_pll_status* phy_pll_status) {
+	uint32_t read_data;
+
+	read_data = phy_pll_status->bs0_status;
+	fprintf(stdout, "DDR%d PHY PLL Status: \n", instance);
+	fprintf(stdout, "\tOBS0: \n");
+	fprintf(stdout, "\t\tPLL Lock Status   = %d \n", (read_data & 1));
+	fprintf(stdout, "\t\tReady			 = %d \n", ((read_data & 0x2) >> 1));
+	fprintf(stdout, "\t\tLock assert count = 0x%x \n", ((read_data & 0x7F8) >> 3));
+
+	read_data = phy_pll_status->bs1_status;
+	fprintf(stdout, "\tOBS1: \n");
+	fprintf(stdout, "\t\tPLL Lock Status   = %d \n", (read_data & 1));
+	fprintf(stdout, "\t\tReady			 = %d \n", ((read_data & 0x2) >> 1));
+	fprintf(stdout, "\t\tLock assert count = 0x%x \n\n", ((read_data & 0x7F8) >> 3));
+}
+
+void print_write_levelling_status(uint32_t instance, struct ddr_wr_levelling_status* wr_levl_status) {
+	uint32_t read_data = 0;
+	int i = 0;
+
+	fprintf(stdout, "\t\tBYTE# \t\t\t\t 0 \t 1 \t 2 \t 3 \t 4 \t 5 \t 6 \t 7 \t 8\n");
+	read_data = wr_levl_status->lower_nibble_err[i++];
+	fprintf(stdout, "\t\tLOWER NIBBLE ERROR FLAG \t %d", (read_data & 0x1000)>> 12);
+	read_data = wr_levl_status->lower_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+	read_data = wr_levl_status->lower_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+	read_data = wr_levl_status->lower_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+	read_data = wr_levl_status->lower_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+	read_data = wr_levl_status->lower_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+	read_data = wr_levl_status->lower_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+	read_data = wr_levl_status->lower_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+	read_data = wr_levl_status->lower_nibble_err[i++];
+	fprintf(stdout, "\t %d\n", (read_data & 0x1000)>> 12);
+
+	i = 0;
+	read_data = wr_levl_status->upper_nibble_err[i++];
+	fprintf(stdout, "\t\tUPPER NIBBLE ERROR FLAG \t %d", (read_data & 0x4000)>> 14);
+	read_data = wr_levl_status->upper_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+	read_data = wr_levl_status->upper_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+	read_data = wr_levl_status->upper_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+	read_data = wr_levl_status->upper_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+	read_data = wr_levl_status->upper_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+	read_data = wr_levl_status->upper_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+	read_data = wr_levl_status->upper_nibble_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+	read_data = wr_levl_status->upper_nibble_err[i++];
+	fprintf(stdout, "\t %d\n", (read_data & 0x4000)>> 14);
+}
+
+void print_read_gate_training_status(uint32_t instance, struct ddr_read_gate_training_status* rd_gate_tr_status)
+{
+	uint32_t read_data = 0;
+	int i = 0;
+
+	fprintf(stdout, "\t\tBYTE# \t\t\t\t 0 \t 1 \t 2 \t 3 \t 4 \t 5 \t 6 \t 7 \t 8\n");
+	read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+	fprintf(stdout, "\t\tLOWER NIBBLE MIN ERROR \t\t %d", (read_data & 0x80)>> 7);
+	read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+	read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+	read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+	read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+	read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+	read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+	read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+	read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+	fprintf(stdout, "\t %d\n", (read_data & 0x80)>> 7);
+
+	i = 0;
+	read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+	fprintf(stdout, "\t\tLOWER NIBBLE MAX ERROR \t\t %d", (read_data & 0x100)>> 8);
+	read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+	read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+	read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+	read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+	read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+	read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+	read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+	read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+	fprintf(stdout, "\t %d\n", (read_data & 0x100)>> 8);
+
+	i = 0;
+	read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+	fprintf(stdout, "\t\tUPPER NIBBLE MIN ERROR \t\t %d", (read_data & 0x200)>> 9);
+	read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+	read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+	read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+	read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+	read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+	read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+	read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+	read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+	fprintf(stdout, "\t %d\n", (read_data & 0x200)>> 9);
+
+	i = 0;
+	read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+	fprintf(stdout, "\t\tUPPER NIBBLE MAX ERROR \t\t %d", (read_data & 0x400)>> 10);
+	read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+	read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+	read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+	read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+	read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+	read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+	read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+	fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+	read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+	fprintf(stdout, "\t %d\n", (read_data & 0x400)>> 10);
+}
+
+void print_ddr_training_status(uint32_t instance, struct ddr_dimm_training_status *dimm_tr_status) {
+	fprintf(stdout, "DDR%d TRAINING STATUS: \n", instance);
+	fprintf(stdout, "\tWRITE LEVELLING STATUS: \n");
+	print_write_levelling_status(instance, &dimm_tr_status->wr_levl_status);
+	fprintf(stdout, "\n\tREAD GATE TRAINING STATUS: \n");
+	print_read_gate_training_status(instance, &dimm_tr_status->rd_gate_tr_status);
+}
+
+void print_margin_vref_low_high(uint32_t instance, struct ddr_dimm_training_status *dimm_tr_status)
+{
+	int i = 0, j = 0;
+	float vref_low_volt, vref_high_volt;
+
+	fprintf(stdout, "DDR%d MARGIN VALUES:\n", instance);
+	fprintf(stdout, "\tREAD LEVEL VREF: \n");
+	fprintf(stdout, "\t\t					 VREF_LOW   VREF_LOW_VOLT(mV)   VREF_HIGH   VREF_HIGH_VOLT(mV)   VREF_MARGIN(mV)\n");
+	for(i=0; i<9; i++)
+	{
+		fprintf(stdout, "\t\tSlice%d Lower Nibble:   ", i);
+		vref_low_volt = dimm_tr_status->vref_data.lower_nibble_vref_low_volt[i];
+		fprintf(stdout, "%04.2f			  ", vref_low_volt);
+		vref_high_volt = dimm_tr_status->vref_data.lower_nibble_vref_high_volt[i];
+		fprintf(stdout, "%04.2f			", vref_high_volt);
+		fprintf(stdout, "%0.2f\n", (vref_high_volt - vref_low_volt));
+
+		fprintf(stdout, "\t\tSlice%d Upper Nibble:   ", i);
+		vref_low_volt = dimm_tr_status->vref_data.upper_nibble_vref_low_volt[i];
+		fprintf(stdout, "%04.2f			  ", vref_low_volt);
+		vref_high_volt = dimm_tr_status->vref_data.upper_nibble_vref_high_volt[i];
+		fprintf(stdout, "%04.2f			", vref_high_volt);
+		fprintf(stdout, "%0.2f\n\n", (vref_high_volt - vref_low_volt));
+	}
+	fprintf(stdout, "\tWRITE DQ LEVEL VREF: \n");
+	fprintf(stdout, "\t\t					 VREF_LOW   VREF_LOW_VOLT(mV)   VREF_HIGH   VREF_HIGH_VOLT(mV)   VREF_MARGIN(mV)\n");
+	for(i=0; i<18; i++)
+	{
+		fprintf(stdout, "\t\tCS0 Device%d :\t", i);
+		vref_low_volt = dimm_tr_status->wdq_vref_data.vref_low_volt[i];
+		fprintf(stdout, "%04.1f			", vref_low_volt);
+		vref_high_volt = dimm_tr_status->wdq_vref_data.vref_high_volt[i];
+		fprintf(stdout, "%04.1f			  ", vref_high_volt);
+		fprintf(stdout, "%0.1f		  \n", (vref_high_volt - vref_low_volt));
+	}
+	for(j=1; j<4; j++)
+	{
+		for(i=0; i<18; i++)
+		{
+			fprintf(stdout, "\t\tCS%d Device%d :\t", j, i);
+			vref_low_volt = dimm_tr_status->wdq_vref_data_cs.vref_low_volt_cs[j][i];
+			fprintf(stdout, "%04.1f			", vref_low_volt);
+			vref_high_volt = dimm_tr_status->wdq_vref_data_cs.vref_high_volt_cs[j][i];
+			fprintf(stdout, "%04.1f			  ", vref_high_volt);
+			fprintf(stdout, "%0.1f		   \n", (vref_high_volt - vref_low_volt));
+		}
+		fprintf(stdout, "\n");
+	}
+}
+
+void print_margin_rdlvl_delay_window(int instance, struct ddr_dimm_training_status *dimm_tr_status)
+{
+	uint32_t te_delay_data = 0, le_delay_data = 0;
+	int i = 0, j = 0;
+	float te_delay_time, le_delay_time;
+
+	printf("DDR%d Margin Delays: \n", instance);
+	printf("\tREAD DQSLEVEL RISE DELAY WINDOW: \n");
+	printf("\t\t		   TE_DATA   TE_DELAY(ns)   LE_DATA   LE_DELAY(ns)   RD_RISE_DELAY(ns)\n");
+	for(j=0; j<9; j++)
+	{
+		for(i=0; i<8; i++)
+		{
+			printf("\t\tSLICE%d BIT%d   ", j, i);
+					te_delay_data = dimm_tr_status->rddqslvl_rise_data.te_delay_data[j][i];
+			printf("%d	  ", te_delay_data);
+					te_delay_time = dimm_tr_status->rddqslvl_rise_data.te_delay_time[j][i];
+			printf("%0.03f		  ", te_delay_time);
+					le_delay_data = dimm_tr_status->rddqslvl_rise_data.le_delay_data[j][i];
+			printf("%02d		", le_delay_data);
+					le_delay_time = dimm_tr_status->rddqslvl_rise_data.le_delay_time[j][i];
+			printf("%0.03f			", le_delay_time);
+			printf("%0.03f\n", (te_delay_time - le_delay_time));
+		}
+		printf("\n");
+	}
+	printf("\tREAD DQSLEVEL FALL DELAY WINDOW: \n");
+	printf("\t\t		   TE_DATA   TE_DELAY(ns)   LE_DATA   LE_DELAY(ns)   RD_FALL_DELAY(ns)\n");
+	for(j=0; j<9; j++)
+	{
+		for(i=0; i<8; i++)
+		{
+			printf("\t\tSLICE%d BIT%d   ", j, i);
+			te_delay_data = dimm_tr_status->rddqslvl_fall_data.te_delay_data[j][i];
+			printf("%d	  ", te_delay_data);
+			te_delay_time = dimm_tr_status->rddqslvl_fall_data.te_delay_time[j][i];
+			printf("%0.03f		  ", te_delay_time);
+			le_delay_data = dimm_tr_status->rddqslvl_fall_data.le_delay_data[j][i];
+			printf("%02d		", le_delay_data);
+			le_delay_time = dimm_tr_status->rddqslvl_fall_data.le_delay_time[j][i];
+			printf("%0.03f			", le_delay_time);
+			printf("%0.03f\n", (te_delay_time - le_delay_time));
+		}
+		printf("\n");
+	}
+}
+
+void print_margin_wrdqlvl_delay_window(int instance, struct ddr_dimm_training_status *dimm_tr_status)
+{
+	uint32_t te_delay_data = 0, le_delay_data = 0;
+	int i = 0, j = 0;
+	float te_delay_time, le_delay_time;
+
+	printf("\tWRITE DQLEVEL DELAY WINDOW: \n");
+	printf("\t\t		   TE_DATA   TE_DELAY(ns)   LE_DATA   LE_DELAY(ns)   WRDQLVL_DELAY(ns)\n");
+	for(j=0; j<9; j++)
+	{
+		for(i=0; i<8; i++)
+		{
+			printf("\t\tSLICE%d BIT%d   ", j, i);
+			te_delay_data = dimm_tr_status->wrdqlvl_delay_data.te_delay_data[j][i];
+			printf("%d	  ", te_delay_data);
+			te_delay_time = dimm_tr_status->wrdqlvl_delay_data.te_delay_time[j][i];
+			printf("%0.03f		  ", te_delay_time);
+			le_delay_data = dimm_tr_status->wrdqlvl_delay_data.le_delay_data[j][i];
+			printf("%02d		", le_delay_data);
+			le_delay_time = dimm_tr_status->wrdqlvl_delay_data.le_delay_time[j][i];
+			printf("%0.03f			", le_delay_time);
+			printf("%0.03f\n", (te_delay_time - le_delay_time));
+		}
+		printf("\n");
+	}
+}
+
+void print_err_status(int instance, struct ddr_dimm_training_status *dimm_tr_status)
+{
+	uint32_t read_data = dimm_tr_status->err_status;
+
+    fprintf(stdout, "DIMM %d Tranining status\n", instance);
+    fprintf(stdout, "\tWRLVL_ERR	 = %d\n", (read_data>>4)&0x1);
+    fprintf(stdout, "\tGTLVL_ERR	 = %d\n", (read_data>>3)&0x1);
+    fprintf(stdout, "\tRDLVL_ERR	 = %d\n", (read_data>>2)&0x1);
+    fprintf(stdout, "\tWDQLVL_ERR	= %d\n", (read_data>>5)&0x1);
+    fprintf(stdout, "\tCA PARTIY ERR = %d\n", (read_data>>1)&0x1);
+}
+
+CXL_EXPORT int cxl_memdev_ddr_dimm_level_training_status(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_ddr_dimm_level_training_status_out *dimm_tr_status;
+	int rc = 0;
+	int i;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_DIMM_LEVEL_TRAINING_STATUS_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_DIMM_LEVEL_TRAINING_STATUS) {
+		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_DDR_DIMM_LEVEL_TRAINING_STATUS);
+		return -EINVAL;
+	}
+	dimm_tr_status = (void *)cmd->send_cmd->out.payload;
+	for (i = DDR_CTRL0; i < DDR_MAX_SUBSYS; i++) {
+	    fprintf(stdout, "dimm:%d level training status\n", i);
+		print_ddr_phy_pll_status(i, &dimm_tr_status->dimm_training_status[i].phy_pll_status);
+		print_ddr_training_status(i, &dimm_tr_status->dimm_training_status[i]);
+		print_margin_vref_low_high(i, &dimm_tr_status->dimm_training_status[i]);
+		print_margin_rdlvl_delay_window(i, &dimm_tr_status->dimm_training_status[i]);
+		print_margin_wrdqlvl_delay_window(i, &dimm_tr_status->dimm_training_status[i]);
+		print_err_status(i, &dimm_tr_status->dimm_training_status[i]);
+	}
+out:
+		cxl_cmd_unref(cmd);
+		return rc;
+}
+
+/* DDR PARAM SET */
+#define CXL_MEM_COMMAND_ID_DDR_PARAM_SET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_PARAM_SET_OPCODE 0xFB1E
+#define CXL_MEM_COMMAND_ID_DDR_PARAM_SET_PAYLOAD_IN_SIZE 4
+
+struct ddr_interleave_options {
+  uint8_t ddr_interleave_sz;
+  uint8_t ddr_interleave_ctrl_choice;
+} __attribute__((packed));
+
+
+struct cxl_mbox_ddr_param_set_in {
+	struct ddr_interleave_options ddr_inter;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_param_set(struct cxl_memdev *memdev, u32 ddr_interleave_sz,
+            u32 ddr_interleave_ctrl_choice)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_mbox_ddr_param_set_in *ddr_param_set_in;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_PARAM_SET_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_PARAM_SET_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	ddr_param_set_in = (void *) cmd->send_cmd->in.payload;
+
+	ddr_param_set_in->ddr_inter.ddr_interleave_sz = ddr_interleave_sz;
+	ddr_param_set_in->ddr_inter.ddr_interleave_ctrl_choice = ddr_interleave_ctrl_choice;
+	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_DDR_PARAM_SET) {
+		 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_DDR_PARAM_SET);
+		return -EINVAL;
+	}
+
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+/* DDR PARAM GET */
+#define CXL_MEM_COMMAND_ID_CXL_DDR_PARAM_GET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CXL_DDR_PARAM_GET_OPCODE 0xFB1F
+
+struct cxl_ddr_param_get_out
+{
+  struct ddr_interleave_options ddr_inter;
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_ddr_param_get(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_ddr_param_get_out *ddr_param_get_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CXL_DDR_PARAM_GET_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_CXL_DDR_PARAM_GET) {
+		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_CXL_DDR_PARAM_GET);
+		return -EINVAL;
+	}
+
+	ddr_param_get_out = (struct cxl_ddr_param_get_out *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "ddr_interleave_sz: %d\n", ddr_param_get_out->ddr_inter.ddr_interleave_sz);
+	fprintf(stdout, "ddr_interleave_ctrl_choice: %d\n", ddr_param_get_out->ddr_inter.ddr_interleave_ctrl_choice);
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+/* CORE VOLTAGE SET */
+#define CXL_MEM_COMMAND_ID_CORE_VOLT_SET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CORE_VOLT_SET_OPCODE 0xFB26
+#define CXL_MEM_COMMAND_ID_CORE_VOLT_SET_PAYLOAD_IN_SIZE 4
+
+struct cxl_mbox_core_volt_set_in {
+	float core_volt;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_core_volt_set(struct cxl_memdev *memdev, float core_volt)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_mbox_core_volt_set_in *core_volt_set_in;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CORE_VOLT_SET_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_CORE_VOLT_SET_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	core_volt_set_in = (void *) cmd->send_cmd->in.payload;
+
+	core_volt_set_in->core_volt = core_volt;
+	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_CORE_VOLT_SET) {
+		 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_CORE_VOLT_SET);
+		return -EINVAL;
+	}
+
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+/* CORE VOLTAGE GET */
+#define CXL_MEM_COMMAND_ID_CXL_CORE_VOLT_GET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CXL_CORE_VOLT_GET_OPCODE 0xFB27
+
+struct cxl_core_volt_get_out
+{
+  float core_volt;
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_core_volt_get(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_core_volt_get_out *core_volt_get_out;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CXL_CORE_VOLT_GET_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* used to force correct payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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);
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_CXL_CORE_VOLT_GET) {
+		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_CXL_CORE_VOLT_GET);
+		return -EINVAL;
+	}
+
+	core_volt_get_out = (struct cxl_core_volt_get_out *)cmd->send_cmd->out.payload;
+	fprintf(stdout, "Core Voltage: %f V\n", core_volt_get_out->core_volt);
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL_OPCODE 0xFB21
+#define CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL_PAYLOAD_IN_SIZE 4
+
+struct cxl_mbox_oem_err_inj_viral_in {
+	u32 viral_type;
+}  __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_oem_err_inj_viral(struct cxl_memdev *memdev,
+	u32 viral_type)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_mbox_oem_err_inj_viral_in *err_inj_viral_in;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	err_inj_viral_in = (void *) cmd->send_cmd->in.payload;
+
+	err_inj_viral_in->viral_type = viral_type;
+	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%s\n",
+				cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+		rc = -ENXIO;
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL) {
+		 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_OEM_ERR_INJ_VIRAL);
+		return -EINVAL;
+	}
+
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+	return 0;
+}
+
+#define CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON_OPCODE 0xFB22
+#define CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON_PAYLOAD_IN_SIZE 8
+
+struct cxl_mbox_err_inj_ll_poison_in {
+	u32 en_dis;
+	u32 ll_err_type;
+}  __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_err_inj_ll_poison(struct cxl_memdev *memdev,
+	u32 en_dis, u32 ll_err_type)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_mbox_err_inj_ll_poison_in *err_inj_ll_poison_in;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	err_inj_ll_poison_in = (void *) cmd->send_cmd->in.payload;
+
+	err_inj_ll_poison_in->ll_err_type = ll_err_type;
+	err_inj_ll_poison_in->en_dis = en_dis;
+	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%s\n",
+				cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+		rc = -ENXIO;
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON) {
+		 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_ERR_INJ_LL_POISON);
+		return -EINVAL;
+	}
+
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+	return 0;
+}
+
+#define CXL_MEM_COMMAND_ID_PCI_ERR_INJ CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCI_ERR_INJ_OPCODE 0xFB25
+#define CXL_MEM_COMMAND_ID_PCI_ERR_INJ_PAYLOAD_IN_SIZE 24
+
+struct cxl_mbox_pci_err_inj_in {
+	u32 en_dis;
+	u32 err_type;
+	u32 err_subtype;
+	u32 count;
+	u32 opt_param1;
+	u32 opt_param2;
+}  __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_pci_err_inj(struct cxl_memdev *memdev,
+	u32 en_dis,
+	u32 err_type,
+	u32 err_subtype,
+	u32 count,
+	u32 opt_param1,
+	u32 opt_param2)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_mbox_pci_err_inj_in *pci_err_inj_in;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCI_ERR_INJ_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_PCI_ERR_INJ_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	pci_err_inj_in = (void *) cmd->send_cmd->in.payload;
+	pci_err_inj_in->en_dis = en_dis;
+	pci_err_inj_in->err_type = err_type;
+	pci_err_inj_in->err_subtype = err_subtype;
+	pci_err_inj_in->count = count;
+	pci_err_inj_in->opt_param1 = opt_param1;
+	pci_err_inj_in->opt_param2 = opt_param2;
+
+	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%s\n",
+				cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+		rc = -ENXIO;
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PCI_ERR_INJ) {
+		 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_PCI_ERR_INJ);
+		return -EINVAL;
+	}
+
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+	return 0;
+}
+
+#define CXL_MEM_COMMAND_ID_READ_LTSSM_STATES CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_READ_LTSSM_STATES_OPCODE 0xFB01
+#define LTSSM_DUMP_SIZE 0x200
+#define LTSSM_EXPECTED_STATE 0x11
+#define LTSSM_STATE_DUMP_COUNT_MAX (LTSSM_DUMP_SIZE / 4)
+
+struct cxl_mbox_read_ltssm_states_out {
+	uint32_t ltssm_states[LTSSM_STATE_DUMP_COUNT_MAX];
+}  __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_read_ltssm_states(struct cxl_memdev *memdev)
+{
+	struct cxl_cmd *cmd;
+	struct cxl_mem_query_commands *query;
+	struct cxl_command_info *cinfo;
+	struct cxl_mbox_read_ltssm_states_out *read_ltssm_states;
+	uint32_t *ltssm_val;
+	uint32_t offset = 0;
+	uint32_t curr_state;
+	int rc = 0;
+
+	cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_READ_LTSSM_STATES_OPCODE);
+	if (!cmd) {
+		fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+				cxl_memdev_get_devname(memdev));
+		return -ENOMEM;
+	}
+
+	query = cmd->query_cmd;
+	cinfo = &query->commands[cmd->query_idx];
+
+	/* update payload size */
+	cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+	if (cinfo->size_in > 0) {
+		 cmd->input_payload = calloc(1, cinfo->size_in);
+		if (!cmd->input_payload)
+			return -ENOMEM;
+		cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+		cmd->send_cmd->in.size = cinfo->size_in;
+	}
+
+	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%s\n",
+				cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+		rc = -ENXIO;
+		goto out;
+	}
+
+	if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_READ_LTSSM_STATES) {
+		 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_READ_LTSSM_STATES);
+		return -EINVAL;
+	}
+
+	read_ltssm_states = (struct  cxl_mbox_read_ltssm_states_out*)cmd->send_cmd->out.payload;
+	fprintf(stdout, "LTSSM STATE CHANGES\n");
+	ltssm_val = read_ltssm_states->ltssm_states;
+	if ((ltssm_val[offset] == ltssm_val[offset + 1]) && (ltssm_val[offset + 1] == 0x0)) {
+		fprintf(stdout, "ltssm state changes are not collected\n");
+		goto out;
+	}
+	while (offset < LTSSM_STATE_DUMP_COUNT_MAX) {
+		if ((ltssm_val[offset] == ltssm_val[offset + 1]) && (ltssm_val[offset + 1] == 0x0))
+			break;
+		curr_state = ltssm_val[offset++];
+		fprintf(stdout,
+			"ltssm state val = 0x%x, %s\n",
+			curr_state,
+			ltssm_state_name[curr_state]);
+	}
+
+out:
+	cxl_cmd_unref(cmd);
+	return rc;
+	return 0;
+}
+
+/* DDR PAGE SELECT SET */
+#define CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET_OPCODE 0xFB2A
+#define CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET_PAYLOAD_IN_SIZE 4
+
+struct page_policy_selection {
+    uint8_t page_policy_reg_val;
+} __attribute__((packed)) page_policy_select;
+
+
+struct cxl_mbox_handle_page_selection_in {
+  struct page_policy_selection pp_select;
+} __attribute__((packed));
+
+
+
+CXL_EXPORT int cxl_memdev_ddr_page_select_set(struct cxl_memdev *memdev,
+                 u32 page_select_option)
+{
+    struct cxl_cmd *cmd;
+    struct cxl_mem_query_commands *query;
+    struct cxl_command_info *cinfo;
+    struct cxl_mbox_handle_page_selection_in *handle_page_selection_in;
+    int rc = 0;
+
+    cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET_OPCODE);
+    if (!cmd) {
+        fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+                cxl_memdev_get_devname(memdev));
+        return -ENOMEM;
+    }
+
+    query = cmd->query_cmd;
+    cinfo = &query->commands[cmd->query_idx];
+
+    /* update payload size */
+    cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET_PAYLOAD_IN_SIZE;
+    if (cinfo->size_in > 0) {
+        cmd->input_payload = calloc(1, cinfo->size_in);
+        if (!cmd->input_payload)
+            return -ENOMEM;
+        cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+        cmd->send_cmd->in.size = cinfo->size_in;
+    }
+
+    handle_page_selection_in = (void *) cmd->send_cmd->in.payload;
+
+    handle_page_selection_in->pp_select.page_policy_reg_val = page_select_option;
+
+    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_DDR_PAGE_SELECT_SET) {
+        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_DDR_PAGE_SELECT_SET);
+        return -EINVAL;
+    }
+
+out:
+    cxl_cmd_unref(cmd);
+    return rc;
+}
+
+/* DDR PAGE SELECT GET */
+#define CXL_MEM_COMMAND_ID_CXL_DDR_PAGE_SELECT_GET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CXL_DDR_PAGE_SELECT_GET_OPCODE 0xFB2B
+
+struct cxl_mbox_handle_page_selection_out {
+  struct page_policy_selection pp_select;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_page_select_get(struct cxl_memdev *memdev)
+{
+    struct cxl_cmd *cmd;
+    struct cxl_mem_query_commands *query;
+    struct cxl_command_info *cinfo;
+    struct cxl_mbox_handle_page_selection_out *handle_page_selection_out;
+    int rc = 0;
+
+    cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CXL_DDR_PAGE_SELECT_GET_OPCODE);
+    if (!cmd) {
+        fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+                cxl_memdev_get_devname(memdev));
+        return -ENOMEM;
+    }
+
+    query = cmd->query_cmd;
+    cinfo = &query->commands[cmd->query_idx];
+
+    /* used to force correct payload size */
+    cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+    if (cinfo->size_in > 0) {
+        cmd->input_payload = calloc(1, cinfo->size_in);
+        if (!cmd->input_payload)
+            return -ENOMEM;
+        cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+        cmd->send_cmd->in.size = cinfo->size_in;
+    }
+
+    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);
+        goto out;
+    }
+
+    if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_CXL_DDR_PAGE_SELECT_GET) {
+        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_CXL_DDR_PAGE_SELECT_GET);
+        return -EINVAL;
+    }
+
+    handle_page_selection_out = (struct cxl_mbox_handle_page_selection_out *)cmd->send_cmd->out.payload;
+    fprintf(stdout, "Page_Policy_Reg_Value is selected for %s\n", (handle_page_selection_out->pp_select.page_policy_reg_val)?"open":"close");
+
+out:
+    cxl_cmd_unref(cmd);
+    return rc;
+}
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
index aaf2d65..e36b0d4 100644
--- a/cxl/lib/libcxl.sym
+++ b/cxl/lib/libcxl.sym
@@ -70,7 +70,7 @@ global:
 	cxl_memdev_get_lsa;
 	cxl_memdev_cmd_identify;
 	cxl_memdev_get_supported_logs;
-	cxl_memdev_get_cel_log;
+	cxl_memdev_get_log;
 	cxl_memdev_get_event_interrupt_policy;
 	cxl_memdev_set_event_interrupt_policy;
 	cxl_memdev_get_timestamp;
@@ -169,4 +169,48 @@ global:
 	cxl_memdev_dimm_spd_read;
 	cxl_memdev_ddr_training_status;
     cxl_memdev_dimm_slot_info;
+    cxl_memdev_pmic_vtmon_info;
+    cxl_memdev_ddr_margin_run;
+    cxl_memdev_ddr_margin_status;
+    cxl_memdev_ddr_margin_get;
+    cxl_memdev_ddr_stats_run;
+    cxl_memdev_ddr_stats_status;
+    cxl_memdev_ddr_stats_get;
+    cxl_memdev_reboot_mode_set;
+    cxl_memdev_curr_cxl_boot_mode_get;
+    cxl_memdev_pcie_eye_run;
+    cxl_memdev_pcie_eye_status;
+    cxl_memdev_pcie_eye_get_sw;
+    cxl_memdev_pcie_eye_get_hw;
+    cxl_memdev_pcie_eye_get_sw_ber;
+    cxl_memdev_get_cxl_link_status;
+    cxl_memdev_get_device_info;
+    cxl_memdev_read_ddr_temp;
+    cxl_memdev_cxl_hpa_to_dpa;
+    cxl_memdev_get_cxl_membridge_errors;
+    cxl_memdev_get_ddr_bw;
+    cxl_memdev_get_ddr_latency;
+    cxl_memdev_i2c_read;
+    cxl_memdev_i2c_write;
+    cxl_memdev_get_ddr_ecc_err_info;
+    cxl_memdev_start_ddr_ecc_scrub;
+    cxl_memdev_ddr_ecc_scrub_status;
+    cxl_memdev_ddr_cont_scrub_status;
+    cxl_memdev_ddr_cont_scrub_set;
+    cxl_memdev_ddr_init_status;
+    cxl_memdev_get_cxl_membridge_stats;
+    cxl_memdev_trigger_coredump;
+    cxl_memdev_ddr_err_inj_en;
+    cxl_memdev_ddr_err_inj_en;
+    cxl_memdev_ddr_dimm_level_training_status;
+    cxl_memdev_ddr_param_set;
+    cxl_memdev_ddr_param_get;
+    cxl_memdev_core_volt_set;
+    cxl_memdev_core_volt_get;
+    cxl_memdev_oem_err_inj_viral;
+    cxl_memdev_err_inj_ll_poison;
+    cxl_memdev_pci_err_inj;
+    cxl_memdev_read_ltssm_states;
+    cxl_memdev_ddr_page_select_set;
+    cxl_memdev_ddr_page_select_get;
 } LIBCXL_3;
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
index 6583af5..4084daa 100644
--- a/cxl/libcxl.h
+++ b/cxl/libcxl.h
@@ -3,6 +3,7 @@
 #ifndef _LIBCXL_H_
 #define _LIBCXL_H_
 
+#include <stdbool.h>
 #include <stdarg.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -57,13 +58,13 @@ int cxl_memdev_set_lsa(struct cxl_memdev *memdev, void *buf, size_t length,
 		size_t offset);
 int cxl_memdev_cmd_identify(struct cxl_memdev *memdev);
 int cxl_memdev_device_info_get(struct cxl_memdev *memdev);
-int cxl_memdev_get_fw_info(struct cxl_memdev *memdev);
+int cxl_memdev_get_fw_info(struct cxl_memdev *memdev, bool is_os_img);
 int cxl_memdev_transfer_fw(struct cxl_memdev *memdev, u8 action,
 	u8 slot, u32 offset, int size, unsigned char *data, u32 transfer_fw_opcode);
 int cxl_memdev_activate_fw(struct cxl_memdev *memdev, u8 action,
 	u8 slot);
 int cxl_memdev_get_supported_logs(struct cxl_memdev *memdev);
-int cxl_memdev_get_cel_log(struct cxl_memdev *memdev, const char *uuid);
+int cxl_memdev_get_log(struct cxl_memdev *memdev, const char *uuid, const unsigned int data_size);
 int cxl_memdev_get_event_interrupt_policy(struct cxl_memdev *memdev);
 int cxl_memdev_set_event_interrupt_policy(struct cxl_memdev *memdev, u32 int_policy);
 int cxl_memdev_get_timestamp(struct cxl_memdev *memdev);
@@ -236,6 +237,51 @@ int cxl_memdev_dimm_spd_read(struct cxl_memdev *memdev, u32 spd_id,
 	u32 offset, u32 num_bytes);
 int cxl_memdev_ddr_training_status(struct cxl_memdev *memdev);
 int cxl_memdev_dimm_slot_info(struct cxl_memdev *memdev);
+int cxl_memdev_pmic_vtmon_info(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_margin_run(struct cxl_memdev *memdev, u8 slice_num, u8 rd_wr_margin, u8 ddr_id);
+int cxl_memdev_ddr_margin_status(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_margin_get(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_stats_run(struct cxl_memdev *memdev, u8 ddr_id,
+							u32 monitor_time, u32 loop_count);
+int cxl_memdev_ddr_stats_status(struct cxl_memdev *memdev, int* run_status, uint32_t* loop_count);
+int cxl_memdev_ddr_stats_get(struct cxl_memdev *memdev);
+int cxl_memdev_reboot_mode_set(struct cxl_memdev *memdev, u8 reboot_mode);
+int cxl_memdev_curr_cxl_boot_mode_get(struct cxl_memdev *memdev);
+int cxl_memdev_pcie_eye_run(struct cxl_memdev *memdev, u8 lane, u8 sw_scan, u8 ber);
+int cxl_memdev_pcie_eye_status(struct cxl_memdev *memdev);
+int cxl_memdev_pcie_eye_get_sw(struct cxl_memdev *memdev, uint offset);
+int cxl_memdev_pcie_eye_get_hw(struct cxl_memdev *memdev);
+int cxl_memdev_pcie_eye_get_sw_ber(struct cxl_memdev *memdev);
+int cxl_memdev_get_cxl_link_status(struct cxl_memdev *memdev);
+int cxl_memdev_get_device_info(struct cxl_memdev *memdev);
+int cxl_memdev_read_ddr_temp(struct cxl_memdev *memdev);
+int cxl_memdev_cxl_hpa_to_dpa(struct cxl_memdev *memdev, u64 hpa_address);
+int cxl_memdev_get_cxl_membridge_errors(struct cxl_memdev *memdev);
+int cxl_memdev_get_ddr_bw(struct cxl_memdev *memdev, u32 timeout, u32 iterations);
+int cxl_memdev_get_ddr_latency(struct cxl_memdev *memdev, u32 measure_time);
+int cxl_memdev_i2c_read(struct cxl_memdev *memdev, u16 slave_addr, u8 reg_addr, u8 num_bytes);
+int cxl_memdev_i2c_write(struct cxl_memdev *memdev, u16 slave_addr, u8 reg_addr, u8 data);
+int cxl_memdev_get_ddr_ecc_err_info(struct cxl_memdev *memdev);
+int cxl_memdev_start_ddr_ecc_scrub(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_ecc_scrub_status(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_cont_scrub_status(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_cont_scrub_set(struct cxl_memdev *memdev, u32 cont_scrub_status);
+int cxl_memdev_ddr_init_status(struct cxl_memdev *memdev);
+int cxl_memdev_get_cxl_membridge_stats(struct cxl_memdev *memdev);
+int cxl_memdev_trigger_coredump(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_err_inj_en(struct cxl_memdev *memdev, u32 ddr_id, u32 err_type, u64 ecc_fwc_mask);
+int cxl_memdev_ddr_dimm_level_training_status(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_param_set(struct cxl_memdev *memdev, u32 ddr_interleave_sz,
+	u32 ddr_interleave_ctrl_choice);
+int cxl_memdev_ddr_param_get(struct cxl_memdev *memdev);
+int cxl_memdev_core_volt_set(struct cxl_memdev *memdev, float core_volt);
+int cxl_memdev_core_volt_get(struct cxl_memdev *memdev);
+int cxl_memdev_oem_err_inj_viral(struct cxl_memdev *memdev, u32 viral_type);
+int cxl_memdev_err_inj_ll_poison(struct cxl_memdev *memdev, u32 en_dis, u32 ll_err_type);
+int cxl_memdev_pci_err_inj(struct cxl_memdev *memdev, u32 en_dis, u32 type, u32 err, u32 count, u32 opt1, u32 opt2);
+int cxl_memdev_read_ltssm_states(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_page_select_set(struct cxl_memdev *memdev, u32 page_select_option);
+int cxl_memdev_ddr_page_select_get(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 fba1f75..2ba16d4 100644
--- a/cxl/memdev.c
+++ b/cxl/memdev.c
@@ -54,6 +54,10 @@ OPT_UINTEGER('s', "size", &param.len, "number of label bytes to operate"), \
 OPT_UINTEGER('O', "offset", &param.offset, \
   "offset into the label area to start operation")
 
+u64 hpa_address;
+#define HPA_OPTIONS() \
+OPT_U64('h', "hpa", &hpa_address, "host physical address")
+
 static const struct option read_options[] = {
   BASE_OPTIONS(),
   LABEL_OPTIONS(),
@@ -92,9 +96,17 @@ static struct _log_uuid {
 OPT_STRING('l', "log_uuid", &log_uuid.uuid, "log-uuid", \
   "CEL Log UUID")
 
-static const struct option cmd_get_cel_log_options[] = {
+static struct _log_size {
+	u32 size;
+} log_size;
+
+#define LOG_SIZE_OPTIONS() \
+OPT_UINTEGER('s', "log_size", &log_size.size, "log-size")
+
+static const struct option cmd_get_log_options[] = {
   BASE_OPTIONS(),
   LOG_UUID_OPTIONS(),
+  LOG_SIZE_OPTIONS(),
   OPT_END(),
 };
 
@@ -146,6 +158,13 @@ static struct _update_fw_params {
   bool verbose;
 } update_fw_params;
 
+static struct _fw_img_params {
+	bool is_os;
+} fw_img_params;
+
+#define FW_IMG_OPTIONS() \
+OPT_BOOLEAN('z', "osimage", &fw_img_params.is_os, "select OS(a.k.a boot1) image")
+
 #define UPDATE_FW_OPTIONS() \
 OPT_FILENAME('f', "file", &update_fw_params.filepath, "rom-file", \
   "filepath to read ROM for firmware update"), \
@@ -156,6 +175,7 @@ OPT_BOOLEAN('m', "mock", &update_fw_params.mock, "For testing purposes. Mock tra
 static const struct option cmd_update_fw_options[] = {
   BASE_OPTIONS(),
   UPDATE_FW_OPTIONS(),
+  FW_IMG_OPTIONS(),
   OPT_END(),
 };
 
@@ -172,6 +192,7 @@ static const struct option cmd_device_info_get_options[] = {
 
 static const struct option cmd_get_fw_info_options[] = {
   BASE_OPTIONS(),
+  FW_IMG_OPTIONS(),
   OPT_END(),
 };
 
@@ -1909,6 +1930,403 @@ static const struct option cmd_dimm_slot_info_options[] = {
   OPT_END(),
 };
 
+static const struct option cmd_pmic_vtmon_info_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _ddr_margin_run_params {
+	u32 slice_num;
+	u32 rd_wr_margin;
+	u32 ddr_id;
+	bool verbose;
+} ddr_margin_run_params;
+
+#define DDR_MARGIN_RUN_OPTIONS() \
+OPT_UINTEGER('s', "slice_num", &ddr_margin_run_params.slice_num, "SLICE NUMBER"), \
+OPT_UINTEGER('m', "rd_wr_margin", &ddr_margin_run_params.rd_wr_margin, "RD/WR MARGIN"), \
+OPT_UINTEGER('i', "ddr_id", &ddr_margin_run_params.ddr_id, "DDR ID")
+
+static const struct option cmd_ddr_margin_run_options[] = {
+  BASE_OPTIONS(),
+  DDR_MARGIN_RUN_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_ddr_margin_status_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_ddr_margin_get_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _ddr_stats_run_params {
+	u32 ddr_id;
+	u32 monitor_time;
+	u32 loop_count;
+	bool verbose;
+} ddr_stats_run_params;
+
+#define DDR_STATS_RUN_OPTIONS() \
+OPT_UINTEGER('i', "ddr_id", &ddr_stats_run_params.ddr_id, "DDR ID"), \
+OPT_UINTEGER('m', "monitor_time", &ddr_stats_run_params.monitor_time, "MOINTOR TIME MSEC"), \
+OPT_UINTEGER('n', "loop_count", &ddr_stats_run_params.loop_count, "NUM ITERATION")
+
+static const struct option cmd_ddr_stats_run_options[] = {
+  BASE_OPTIONS(),
+  DDR_STATS_RUN_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_ddr_stats_get_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _reboot_mode_set_params {
+	u32 reboot_mode;
+	bool verbose;
+} reboot_mode_set_params;
+
+#define REBOOT_MODE_SET_OPTIONS() \
+OPT_UINTEGER('m', "reboot_mode", &reboot_mode_set_params.reboot_mode, "0:CXL-IO-MEM or 0xCE:CXL-IO")
+
+static const struct option cmd_reboot_mode_set_options[] = {
+  BASE_OPTIONS(),
+  REBOOT_MODE_SET_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_curr_cxl_boot_mode_get_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _pcie_eye_run_params {
+	u32 lane;
+	u32 sw_scan;
+	u32 ber;
+	bool verbose;
+} pcie_eye_run_params;
+
+#define PCIE_EYE_RUN_OPTIONS() \
+OPT_UINTEGER('l', "lane", &pcie_eye_run_params.lane, "LANE ID"), \
+OPT_UINTEGER('s', "sw_scan", &pcie_eye_run_params.sw_scan, "SW SCAN"), \
+OPT_UINTEGER('b', "ber", &pcie_eye_run_params.ber, "BER")
+
+static const struct option cmd_pcie_eye_run_options[] = {
+  BASE_OPTIONS(),
+  PCIE_EYE_RUN_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_pcie_eye_status_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _pcie_eye_get_params {
+	u32 sw_scan;
+	u32 ber;
+	bool verbose;
+} pcie_eye_get_params;
+
+#define PCIE_EYE_GET_OPTIONS() \
+OPT_UINTEGER('s', "sw_scan", &pcie_eye_get_params.sw_scan, "SW SCAN"), \
+OPT_UINTEGER('b', "ber", &pcie_eye_get_params.ber, "BER")
+
+static const struct option cmd_pcie_eye_get_options[] = {
+  BASE_OPTIONS(),
+  PCIE_EYE_GET_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_get_cxl_link_status_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_get_device_info_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_read_ddr_temp_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_cxl_hpa_to_dpa_options[] = {
+  BASE_OPTIONS(),
+  HPA_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_get_cxl_membridge_errors_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _get_ddr_bw_params {
+	u32 timeout;
+	u32 iterations;
+	bool verbose;
+} get_ddr_bw_params;
+
+#define GET_DDR_BW_OPTIONS() \
+OPT_UINTEGER('t', "temeout", &get_ddr_bw_params.timeout, "Timeout"), \
+OPT_UINTEGER('i', "iterations", &get_ddr_bw_params.iterations, "No Iterations")
+
+static const struct option cmd_get_ddr_bw_options[] = {
+  BASE_OPTIONS(),
+  GET_DDR_BW_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _get_ddr_latency_params {
+	u32 measure_time;
+	bool verbose;
+} get_ddr_latency_params;
+
+#define GET_DDR_LATENCY_OPTIONS() \
+OPT_UINTEGER('t', "measure time", &get_ddr_latency_params.measure_time, "Measure Time in msec")
+
+static const struct option cmd_get_ddr_latency_options[] = {
+  BASE_OPTIONS(),
+  GET_DDR_LATENCY_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _i2c_read_params {
+	u32 slave_addr;
+	u32 reg_addr;
+	u32 num_bytes;
+	bool verbose;
+} i2c_read_params;
+
+#define I2C_READ_OPTIONS() \
+OPT_UINTEGER('s', "slave_addr", &i2c_read_params.slave_addr, "Slave addr"), \
+OPT_UINTEGER('r', "reg_addr", &i2c_read_params.reg_addr, "Reg addr"), \
+OPT_UINTEGER('n', "num_bytes", &i2c_read_params.num_bytes, "Number of bytes")
+
+static const struct option cmd_i2c_read_options[] = {
+  BASE_OPTIONS(),
+  I2C_READ_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _i2c_write_params {
+	u32 slave_addr;
+	u32 reg_addr;
+	u32 data;
+	bool verbose;
+} i2c_write_params;
+
+#define I2C_WRITE_OPTIONS() \
+OPT_UINTEGER('s', "slave_addr", &i2c_write_params.slave_addr, "Slave addr"), \
+OPT_UINTEGER('r', "reg_addr", &i2c_write_params.reg_addr, "Reg addr"), \
+OPT_UINTEGER('d', "data", &i2c_write_params.data, "Data")
+
+static const struct option cmd_i2c_write_options[] = {
+  BASE_OPTIONS(),
+  I2C_WRITE_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_get_ddr_ecc_err_info_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_start_ddr_ecc_scrub_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_ddr_ecc_scrub_status_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_ddr_cont_scrub_status_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _ddr_cont_scrub_set_params {
+	u32 cont_scrub_status;
+} ddr_cont_scrub_set_params;
+
+#define DDR_CONT_SCRUB_SET_OPTIONS() \
+OPT_UINTEGER('i', "cont_scrub_status", &ddr_cont_scrub_set_params.cont_scrub_status, "Continuous Scrub ON:1 OFF: 0")
+
+static const struct option cmd_ddr_cont_scrub_set_options[] = {
+  BASE_OPTIONS(),
+  DDR_CONT_SCRUB_SET_OPTIONS(),
+  OPT_END(),
+};
+
+
+static const struct option cmd_ddr_init_status_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_get_cxl_membridge_stats_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_trigger_coredump_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _ddr_err_inj_en_params {
+	u32 ddr_id;
+	u32 err_type;
+	u64 ecc_fwc_mask;
+	bool verbose;
+} ddr_err_inj_en_params;
+
+#define DDR_ERR_INJ_EN_OPTIONS() \
+OPT_UINTEGER('d', "ddr_id", &ddr_err_inj_en_params.ddr_id, "ddr id <0-DDR_CTRL0,1-DDR_CTRL1>"), \
+OPT_UINTEGER('t', "err_type", &ddr_err_inj_en_params.err_type, "error type\n\t\t\t0: AXI bus parity READ ADDR\n\t\t\t1: AXI bus parity WRITE ADDR\n\t\t\t2: AXI bus parity WRITE DATA\n\t\t\t3: CA bus parity\n\t\t\t4: ECC correctable\n\t\t\t5: ECC uncorrectable\n\t\t\t6: ECC SCRUB"), \
+OPT_U64('m', "ecc_fwc_mask", &ddr_err_inj_en_params.ecc_fwc_mask, "ecc fwc mask <35bit value, upto two bit set for correctable ecc error\n\t\t\tAtleast 4bits for uncoorectable ecc errors\n>")
+
+static const struct option cmd_ddr_err_inj_en_options[] = {
+  BASE_OPTIONS(),
+  DDR_ERR_INJ_EN_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_ddr_dimm_level_training_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _ddr_set_params {
+        u32 ddr_interleave_sz;
+        u32 ddr_interleave_ctrl_choice;
+} ddr_set_params;
+
+#define DDR_PARAM_SET_OPTIONS() \
+	OPT_UINTEGER('m', "ddr_interleave_sz", &ddr_set_params.ddr_interleave_sz, "Intereleave SZ is: 2 pow m. Input the value of m as the Size"), \
+	OPT_UINTEGER('n', "ddr_interleave_ctrl_choice", &ddr_set_params.ddr_interleave_ctrl_choice, "CTRL Choice: 1=DDR0 2=DDR1 3= DDR0 and DDR1")
+
+static const struct option cmd_ddr_param_set_options[] = {
+  BASE_OPTIONS(),
+  DDR_PARAM_SET_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_ddr_param_get_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _ddr_core_volt_set_params {
+	u32 val1;
+	u32 val2;
+	u32 val3;
+} ddr_core_volt_set_params;
+
+#define CORE_VOLT_SET_OPTIONS() \
+OPT_UINTEGER('i', "core_volt_val1", &ddr_core_volt_set_params.val1, "CORE Voltage val1.val2 val3"), \
+OPT_UINTEGER('m', "core_volt_val2", &ddr_core_volt_set_params.val2, "CORE Voltage val1.val2 val3"), \
+OPT_UINTEGER('n', "core_volt_val3", &ddr_core_volt_set_params.val3, "CORE Voltage val1.val2 val3")
+
+static const struct option cmd_core_volt_set_options[] = {
+  BASE_OPTIONS(),
+  CORE_VOLT_SET_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_core_volt_get_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _oem_err_inj_viral_params {
+  u32 viral_type;
+  bool verbose;
+} oem_err_inj_viral_params;
+
+#define OEM_ERR_INJ_VIRAL_OPTIONS() \
+OPT_UINTEGER('l', "viral_type", &oem_err_inj_viral_params.viral_type, "viral_type")
+
+static const struct option cmd_oem_err_inj_viral_options[] = {
+  BASE_OPTIONS(),
+  OEM_ERR_INJ_VIRAL_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _err_inj_ll_poison_params {
+  u32 en_dis;
+  u32 ll_err_type;
+  bool verbose;
+} err_inj_ll_poison_params;
+
+#define ERR_INJ_LL_POISON_OPTIONS() \
+OPT_UINTEGER('e', "en_dis", &err_inj_ll_poison_params.en_dis, "enable_disable 0=dis,1=en"), \
+OPT_UINTEGER('l', "ll_err_type", &err_inj_ll_poison_params.ll_err_type, "link level err type 0=mem-poison")
+
+static const struct option cmd_err_inj_ll_poison_options[] = {
+  BASE_OPTIONS(),
+  ERR_INJ_LL_POISON_OPTIONS(),
+  OPT_END(),
+};
+
+static struct _pci_err_in_params {
+  u32 en_dis;
+  u32 err_type;
+  u32 err_subtype;
+  u32 count;
+  u32 opt_param1;
+  u32 opt_param2;
+  bool verbose;
+} pci_err_inj_params;
+
+#define PCI_ERR_INJ_OPTIONS() \
+OPT_UINTEGER('e', "en_dis", &pci_err_inj_params.en_dis, "enable_disable:\n\t0=disable inj\n\t1=enable inj"), \
+OPT_UINTEGER('l', "err_type", &pci_err_inj_params.err_type, "err inj type Group:\n\t0:CRC ERR\n\t1:SEQ NUM ERR\n\t2:DLLP ERR\n\t3:SYMBOL ERR\n\t4:FC CREDIT ERR\n\t5:Special TLP ERR\n"), \
+OPT_UINTEGER('s', "err_subtype", &pci_err_inj_params.err_subtype, "err inj sub-type:\n\tGroup-0:<CRC Error>\n\t\t0 = TX_TLP_LCRC_ERR\n\t\t1 = TX_16B_CRC_ERR_ACK_NAK_DLLP\n\t\t2 = TX_16B_CRC_ERR_UPD_FC\n\t\t3 = TX_TLP_ECRC_ERR\n\t\t4 = TX_FCRC_ERR_TLP\n\t\t5 = TX_PARITY_TSOS_ERR\n\t\t6 = TX_PARITY_SKPOS_ERR\n\t\t8 = RX_LCRC_ERR\n\t\t11= RX_ECRC_ERR\n\n\tGroup-1:<SEQ NUM Error>\n\t\t0 = TLP_ERR_SEQNUM\n\t\t1 = ACK_NAK_DLLP_ERR_SEQNUM\n\n\tGroup-2:<DLLP Error>\n\t\t0 = ACK_NACK_DLLP\n\t\t1 = UPD_FC_DLLP\n\t\t2 = NAK_DLLP\n\n\tGroup-3:<Symbol Error>\n\t\t0 = RSVD_OR_INVRT_SYNC_HDR\n\t\t1 = COM_PAD_TS1\n\t\t2 = COM_PAD_TS2\n\t\t3 = COM_FTS\n\t\t4 = COM_IDL\n\t\t5 = END_EDB\n\t\t6 = STP_SDP\n\t\t7 = COM_SKP\n\n\tGroup-4:<FC Credit Error>\n\t\t0 = POSTED_TLP_HDR\n\t\t1 = NON_POSTED_TLP_HDR\n\t\t2 = CMPL_TLP_HDR\n\t\t4 = POSTED_TLP_DATA\n\t\t5 = NON_POSTED_TLP_DATA\n\n\tGroup-5:<Special TLP Error>\n\t\t0 = DUPLICATE_DLLP\n\t\t1 = NULLIFIED_TLP\n"), \
+OPT_UINTEGER('c', "count", &pci_err_inj_params.count, "err inj count:\n\t1-255: count of err to inject\n\t0: continuous inj until disable\n"), \
+OPT_UINTEGER('x', "opt1", &pci_err_inj_params.opt_param1, "opt1: Optional Extra args1\n\tFor Group-1:Bad Sequence Number(2s compliment in hex): Min:0x1001, Max:0xfff\n\tFor Group-4:Bad update-FC credit val(2s compliment in hex): Min:0x1001, Max:0xfff\n\tFor other Groups: Pass value '0'\n"), \
+OPT_UINTEGER('y', "opt2", &pci_err_inj_params.opt_param2, "opt2: Optional Extra args2\n\tGroup-4:<FC Credit Error>:Target VC_NUMBER: Min:0, Max:7\n\tFor other Groups:Pass value '0'\n")
+
+static const struct option cmd_pci_err_inj_options[] = {
+  BASE_OPTIONS(),
+  PCI_ERR_INJ_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_read_ltssm_states_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
+static struct page_policy_selection {
+  int page_policy_reg_val;
+} page_policy_select;
+
+#define DDR_PAGE_SELECT_SET_OPTIONS() \
+	OPT_INTEGER('p', "page_policy_reg_val", &page_policy_select.page_policy_reg_val, "Value for page policy selection")
+
+static const struct option cmd_ddr_page_select_set_options[] = {
+  BASE_OPTIONS(),
+  DDR_PAGE_SELECT_SET_OPTIONS(),
+  OPT_END(),
+};
+
+static const struct option cmd_ddr_page_select_get_options[] = {
+  BASE_OPTIONS(),
+  OPT_END(),
+};
+
 static int action_cmd_clear_event_records(struct cxl_memdev *memdev, struct action_context *actx)
 {
   u16 record_handle;
@@ -2133,10 +2551,16 @@ static int action_cmd_update_fw(struct cxl_memdev *memdev, struct action_context
   }
 
   offset = 0;
-  if (update_fw_params.hbo) {
-    opcode = 0xCD01; // Pioneer vendor opcode for hbo-transfer-fw
+
+  if (fw_img_params.is_os) {
+    printf("firmware update selected for OS Image\n");
+    opcode = 0xCD04; // Vistara opcode for OS(boot1) image update
   } else {
-    opcode = 0x0201; // Spec defined transfer-fw
+    if (update_fw_params.hbo) {
+      opcode = 0xCD01; // Pioneer vendor opcode for hbo-transfer-fw
+    } else {
+      opcode = 0x0201; // Spec defined transfer-fw
+    }
   }
 
   for (int i = 0; i < num_blocks; i++)
@@ -2248,15 +2672,15 @@ static int action_cmd_set_event_interrupt_policy(struct cxl_memdev *memdev, stru
   return cxl_memdev_set_event_interrupt_policy(memdev, interrupt_policy_params.policy);
 }
 
-static int action_cmd_get_cel_log(struct cxl_memdev *memdev, struct action_context *actx)
+static int action_cmd_get_log(struct cxl_memdev *memdev, struct action_context *actx)
 {
   if (cxl_memdev_is_active(memdev)) {
-    fprintf(stderr, "%s: memdev active, get_cel_log\n",
+    fprintf(stderr, "%s: memdev active, get_log\n",
       cxl_memdev_get_devname(memdev));
     return -EBUSY;
   }
 
-  return cxl_memdev_get_cel_log(memdev, log_uuid.uuid);
+  return cxl_memdev_get_log(memdev, log_uuid.uuid, log_size.size);
 }
 
 static int action_cmd_get_supported_logs(struct cxl_memdev *memdev, struct action_context *actx)
@@ -2358,7 +2782,7 @@ static int action_cmd_get_fw_info(struct cxl_memdev *memdev, struct action_conte
     return -EBUSY;
   }
 
-  return cxl_memdev_get_fw_info(memdev);
+  return cxl_memdev_get_fw_info(memdev, fw_img_params.is_os);
 }
 
 static int action_cmd_activate_fw(struct cxl_memdev *memdev, struct action_context *actx)
@@ -3463,32 +3887,594 @@ static int action_cmd_dimm_slot_info(struct cxl_memdev *memdev, struct action_co
 	return cxl_memdev_dimm_slot_info(memdev);
 }
 
-static int action_write(struct cxl_memdev *memdev, struct action_context *actx)
+static int action_cmd_pmic_vtmon_info(struct cxl_memdev *memdev, struct action_context *actx)
 {
-  size_t size = param.len, read_len;
-  unsigned char *buf;
-  int rc;
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort pmic_vtmon_info\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
 
-  if (cxl_memdev_is_active(memdev)) {
-    fprintf(stderr, "%s is active, abort label write\n",
-      cxl_memdev_get_devname(memdev));
-    return -EBUSY;
-  }
+	return cxl_memdev_pmic_vtmon_info(memdev);
+}
 
-  if (!size) {
-    size_t lsa_size = cxl_memdev_get_lsa_size(memdev);
+static int action_cmd_ddr_margin_run(struct cxl_memdev *memdev,
+				   struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr_margin_run\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
 
-    fseek(actx->f_in, 0L, SEEK_END);
-    size = ftell(actx->f_in);
-    fseek(actx->f_in, 0L, SEEK_SET);
+	return cxl_memdev_ddr_margin_run(memdev, ddr_margin_run_params.slice_num,
+				       ddr_margin_run_params.rd_wr_margin,
+				       ddr_margin_run_params.ddr_id);
+}
 
-    if (size > lsa_size) {
-      fprintf(stderr,
-        "File size (%zu) greater than LSA size (%zu), aborting\n",
-        size, lsa_size);
-      return -EINVAL;
-    }
-  }
+static int action_cmd_ddr_margin_status(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr_margin_status\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_ddr_margin_status(memdev);
+}
+
+static int action_cmd_ddr_margin_get(struct cxl_memdev *memdev,
+				   struct action_context *actx)
+{
+	int rc = 0;
+
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr_margin_get\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	rc = cxl_memdev_ddr_margin_get(memdev);
+	if(rc)
+	{
+		fprintf(stderr,
+			"ddr_margin_get read failed");
+		goto abort;
+	}
+
+abort:
+  return rc;
+}
+
+static int action_cmd_ddr_stats_run(struct cxl_memdev *memdev,
+				   struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr_stats_run\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_ddr_stats_run(memdev, ddr_stats_run_params.ddr_id,
+									ddr_stats_run_params.monitor_time,
+									ddr_stats_run_params.loop_count);
+}
+
+static int action_cmd_ddr_stats_get(struct cxl_memdev *memdev,
+				   struct action_context *actx)
+{
+	int rc = 0;
+
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr_stats_get\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	rc = cxl_memdev_ddr_stats_get(memdev);
+	if(rc)
+	{
+		fprintf(stderr,
+			"ddr_stats_get read failed");
+		goto abort;
+	}
+
+abort:
+  return rc;
+}
+
+static int action_cmd_reboot_mode_set(struct cxl_memdev *memdev,
+                                   struct action_context *actx)
+{
+        if (cxl_memdev_is_active(memdev)) {
+                fprintf(stderr, "%s: memdev active, abort reboot mode set\n",
+                        cxl_memdev_get_devname(memdev));
+                return -EBUSY;
+        }
+
+        return cxl_memdev_reboot_mode_set(memdev, reboot_mode_set_params.reboot_mode);
+}
+
+static int action_cmd_curr_cxl_boot_mode_get(struct cxl_memdev *memdev,
+				   struct action_context *actx)
+{
+	int rc = 0;
+
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort curr cxl boot mode get\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	rc = cxl_memdev_curr_cxl_boot_mode_get(memdev);
+	if(rc)
+	{
+		fprintf(stderr,
+			"curr_cxl_boot_mode_get failed");
+		goto abort;
+	}
+
+abort:
+  return rc;
+}
+
+static int action_cmd_pcie_eye_run(struct cxl_memdev *memdev,
+				   struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort pcie_eye_run\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_pcie_eye_run(memdev, pcie_eye_run_params.lane,
+				       pcie_eye_run_params.sw_scan,
+				       pcie_eye_run_params.ber);
+}
+
+static int action_cmd_pcie_eye_status(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort pcie_eye_status\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_pcie_eye_status(memdev);
+}
+
+static int action_cmd_pcie_eye_get(struct cxl_memdev *memdev,
+				   struct action_context *actx)
+{
+	#define NUM_EYESCOPE_VERT_VALS 511
+	#define TOTAL_EYESCOPE_VERT_VALS ((NUM_EYESCOPE_VERT_VALS * 2) + 1)
+	#define VERT_SKIP 15
+
+	int rc = 0;
+
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort pcie_eye_get\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	if(pcie_eye_get_params.sw_scan) {
+		for (int i = 0; i < TOTAL_EYESCOPE_VERT_VALS; i += VERT_SKIP) {
+			rc  = cxl_memdev_pcie_eye_get_sw(memdev, i);
+			if (rc != 0)
+			{
+				fprintf(stderr,
+					"pcie_eye_get read failed or sw_scan not enabled\n");
+				goto abort;
+			}
+		}
+		if(pcie_eye_get_params.ber) {
+			rc  = cxl_memdev_pcie_eye_get_sw_ber(memdev);
+			if (rc != 0)
+			{
+				fprintf(stderr,
+					"pcie_eye_get read failed OR BER is not enabled\n");
+				goto abort;
+			}
+		}
+	} else {
+		rc = cxl_memdev_pcie_eye_get_hw(memdev);
+		if(rc)
+		{
+			fprintf(stderr,
+				"pcie_eye_get read failed hw scan not enabled");
+			goto abort;
+		}
+	}
+abort:
+  return rc;
+}
+
+static int action_cmd_get_cxl_link_status(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort get_cxl_link_status\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_get_cxl_link_status(memdev);
+}
+
+static int action_cmd_get_device_info(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort get_device_info\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_get_device_info(memdev);
+}
+
+static int action_cmd_read_ddr_temp(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort read_ddr_temp\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_read_ddr_temp(memdev);
+}
+
+static int action_cmd_cxl_hpa_to_dpa(struct cxl_memdev *memdev,
+                                     struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+        	fprintf(stderr, "%s: memdev active, abort hpa to dpa\n",
+				cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_cxl_hpa_to_dpa(memdev, hpa_address);
+}
+
+static int action_cmd_get_cxl_membridge_errors(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort cxl membridge errors\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_get_cxl_membridge_errors(memdev);
+}
+
+static int action_cmd_get_ddr_bw(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort get_ddr_bw\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_get_ddr_bw(memdev, get_ddr_bw_params.timeout, get_ddr_bw_params.iterations);
+}
+
+static int action_cmd_get_ddr_latency(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort get_ddr_latency\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_get_ddr_latency(memdev, get_ddr_latency_params.measure_time);
+}
+
+static int action_cmd_i2c_read(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort i2c_read\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_i2c_read(memdev, i2c_read_params.slave_addr, i2c_read_params.reg_addr, i2c_read_params.num_bytes);
+}
+
+static int action_cmd_i2c_write(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort i2c_write\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_i2c_write(memdev, i2c_write_params.slave_addr, i2c_write_params.reg_addr, i2c_write_params.data);
+}
+
+static int action_cmd_get_ddr_ecc_err_info(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort get-ddr-ecc-err-info\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_get_ddr_ecc_err_info(memdev);
+}
+
+static int action_cmd_start_ddr_ecc_scrub(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort start-ddr-ecc-scrub\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_start_ddr_ecc_scrub(memdev);
+}
+
+static int action_cmd_ddr_ecc_scrub_status(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr-ecc-scrub-status\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_ddr_ecc_scrub_status(memdev);
+}
+
+static int action_cmd_ddr_cont_scrub_status(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr-cont-scrub-status\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_ddr_cont_scrub_status(memdev);
+}
+
+static int action_cmd_ddr_cont_scrub_set(struct cxl_memdev *memdev,
+				   struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr-cont-scrub-set\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_ddr_cont_scrub_set(memdev,
+			ddr_cont_scrub_set_params.cont_scrub_status);
+}
+
+static int action_cmd_ddr_init_status(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr-init-status\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+	return cxl_memdev_ddr_init_status(memdev);
+}
+
+static int action_cmd_get_cxl_membridge_stats(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort cxl membridge stats\n",
+    			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+  return cxl_memdev_get_cxl_membridge_stats(memdev);
+}
+
+static int action_cmd_trigger_coredump(struct cxl_memdev *memdev,
+                                      struct action_context *actx)
+{
+        if (cxl_memdev_is_active(memdev)) {
+                fprintf(stderr, "%s: memdev active, abort ddr-ecc-scrub-status\n",
+                        cxl_memdev_get_devname(memdev));
+                return -EBUSY;
+        }
+
+        return cxl_memdev_trigger_coredump(memdev);
+}
+
+static int action_cmd_ddr_err_inj_en(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr-err-inj-en\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_ddr_err_inj_en(memdev, ddr_err_inj_en_params.ddr_id, ddr_err_inj_en_params.err_type, ddr_err_inj_en_params.ecc_fwc_mask);
+}
+
+static int action_cmd_ddr_dimm_level_training_status(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr-dimm-level-training-status\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_ddr_dimm_level_training_status(memdev);
+}
+
+static int action_cmd_ddr_param_set(struct cxl_memdev *memdev,
+				   struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr_param_set\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_ddr_param_set(memdev, ddr_set_params.ddr_interleave_sz,
+                                  ddr_set_params.ddr_interleave_ctrl_choice);
+}
+
+static int action_cmd_ddr_param_get(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr_param_get\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_ddr_param_get(memdev);
+}
+
+static int action_cmd_core_volt_set(struct cxl_memdev *memdev,
+				   struct action_context *actx)
+{
+  float volt;
+
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort core_volt_set\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+  volt = ddr_core_volt_set_params.val1 + (ddr_core_volt_set_params.val2 / 10.0) +
+         (ddr_core_volt_set_params.val3 / 100.0);
+
+	return cxl_memdev_core_volt_set(memdev, volt);
+}
+
+static int action_cmd_core_volt_get(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort core_volt_get\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_core_volt_get(memdev);
+}
+
+static int action_cmd_oem_err_inj_viral(struct cxl_memdev *memdev, struct action_context *actx)
+{
+  if (cxl_memdev_is_active(memdev)) {
+    fprintf(stderr, "%s: memdev active, abort oem_err_inj_viral\n",
+      cxl_memdev_get_devname(memdev));
+    return -EBUSY;
+  }
+
+  return cxl_memdev_oem_err_inj_viral(memdev, oem_err_inj_viral_params.viral_type);
+}
+
+static int action_cmd_err_inj_ll_poison(struct cxl_memdev *memdev, struct action_context *actx)
+{
+  if (cxl_memdev_is_active(memdev)) {
+    fprintf(stderr, "%s: memdev active, abort err_inj_ll_poison\n",
+      cxl_memdev_get_devname(memdev));
+    return -EBUSY;
+  }
+
+  return cxl_memdev_err_inj_ll_poison(memdev, err_inj_ll_poison_params.en_dis,
+				      err_inj_ll_poison_params.ll_err_type);
+}
+
+static int action_cmd_pci_err_inj(struct cxl_memdev *memdev, struct action_context *actx)
+{
+  if (cxl_memdev_is_active(memdev)) {
+    fprintf(stderr, "%s: memdev active, abort err_inj_ll_poison\n",
+      cxl_memdev_get_devname(memdev));
+    return -EBUSY;
+  }
+
+  return cxl_memdev_pci_err_inj(memdev, pci_err_inj_params.en_dis,
+				      pci_err_inj_params.err_type,
+				      pci_err_inj_params.err_subtype,
+				      pci_err_inj_params.count,
+				      pci_err_inj_params.opt_param1,
+				      pci_err_inj_params.opt_param2);
+}
+
+static int action_cmd_read_ltssm_states(struct cxl_memdev *memdev, struct action_context *actx)
+{
+  if (cxl_memdev_is_active(memdev)) {
+    fprintf(stderr, "%s: memdev active, abort read-ltssm-state-changes\n",
+      cxl_memdev_get_devname(memdev));
+    return -EBUSY;
+  }
+
+  return cxl_memdev_read_ltssm_states(memdev);
+}
+
+
+static int action_cmd_ddr_page_select_set(struct cxl_memdev *memdev,
+				   struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr_param_set\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_ddr_page_select_set(memdev, page_policy_select.page_policy_reg_val);
+}
+
+static int action_cmd_ddr_page_select_get(struct cxl_memdev *memdev,
+				      struct action_context *actx)
+{
+	if (cxl_memdev_is_active(memdev)) {
+		fprintf(stderr, "%s: memdev active, abort ddr_param_get\n",
+			cxl_memdev_get_devname(memdev));
+		return -EBUSY;
+	}
+
+	return cxl_memdev_ddr_page_select_get(memdev);
+}
+
+
+static int action_write(struct cxl_memdev *memdev, struct action_context *actx)
+{
+  size_t size = param.len, read_len;
+  unsigned char *buf;
+  int rc;
+
+  if (cxl_memdev_is_active(memdev)) {
+    fprintf(stderr, "%s is active, abort label write\n",
+      cxl_memdev_get_devname(memdev));
+    return -EBUSY;
+  }
+
+  if (!size) {
+    size_t lsa_size = cxl_memdev_get_lsa_size(memdev);
+
+    fseek(actx->f_in, 0L, SEEK_END);
+    size = ftell(actx->f_in);
+    fseek(actx->f_in, 0L, SEEK_SET);
+
+    if (size > lsa_size) {
+      fprintf(stderr,
+        "File size (%zu) greater than LSA size (%zu), aborting\n",
+        size, lsa_size);
+      return -EINVAL;
+    }
+  }
 
   buf = calloc(1, size);
   if (!buf)
@@ -3707,10 +4693,10 @@ int cmd_get_supported_logs(int argc, const char **argv, struct cxl_ctx *ctx)
   return rc >= 0 ? 0 : EXIT_FAILURE;
 }
 
-int cmd_get_cel_log(int argc, const char **argv, struct cxl_ctx *ctx)
+int cmd_get_log(int argc, const char **argv, struct cxl_ctx *ctx)
 {
-  int rc = memdev_action(argc, argv, ctx, action_cmd_get_cel_log, cmd_get_cel_log_options,
-      "cxl get-cel-log <mem0> [<mem1>..<memN>] [<options>]");
+  int rc = memdev_action(argc, argv, ctx, action_cmd_get_log, cmd_get_log_options,
+      "cxl get-log <mem0> [<mem1>..<memN>] [<options>]");
 
   return rc >= 0 ? 0 : EXIT_FAILURE;
 }
@@ -4528,3 +5514,321 @@ int cmd_dimm_slot_info(int argc, const char **argv, struct cxl_ctx *ctx)
 
   return rc >= 0 ? 0 : EXIT_FAILURE;
 }
+
+int cmd_pmic_vtmon_info(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_pmic_vtmon_info, cmd_pmic_vtmon_info_options,
+      "cxl pmic-vtmon-info <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_margin_run(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_margin_run, cmd_ddr_margin_run_options,
+      "cxl ddr-margin-run <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_margin_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_margin_status, cmd_ddr_margin_status_options,
+      "cxl ddr-margin-status <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_margin_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_margin_get, cmd_ddr_margin_get_options,
+      "cxl ddr-margin-get <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_stats_run(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_stats_run, cmd_ddr_stats_run_options,
+      "cxl ddr-stats-run <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_stats_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_stats_get, cmd_ddr_stats_get_options,
+      "cxl ddr-stats-get <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_curr_cxl_boot_mode_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_curr_cxl_boot_mode_get, cmd_curr_cxl_boot_mode_get_options,
+      "cxl curr-cxl-boot-mode-get  <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_reboot_mode_set(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_reboot_mode_set, cmd_reboot_mode_set_options,
+      "cxl reboot-mode-set <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_pcie_eye_run(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_pcie_eye_run, cmd_pcie_eye_run_options,
+      "cxl pcie-eye-run <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_pcie_eye_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_pcie_eye_status, cmd_pcie_eye_status_options,
+      "cxl pcie-eye-status <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_pcie_eye_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_pcie_eye_get, cmd_pcie_eye_get_options,
+      "cxl pcie-eye-get <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_cxl_link_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_get_cxl_link_status, cmd_get_cxl_link_status_options,
+      "cxl get_cxl_link_status <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_device_info(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_get_device_info, cmd_get_device_info_options,
+      "cxl get_device_info <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_read_ddr_temp(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_read_ddr_temp, cmd_read_ddr_temp_options,
+      "cxl read_ddr_temp <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_cxl_hpa_to_dpa(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_cxl_hpa_to_dpa, cmd_cxl_hpa_to_dpa_options,
+      "cxl hpa to dpa");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_cxl_membridge_errors(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_get_cxl_membridge_errors, cmd_get_cxl_membridge_errors_options,
+      "cxl get_cxl_membridge_errors");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_ddr_bw(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_get_ddr_bw, cmd_get_ddr_bw_options,
+      "cxl get-ddr-bw <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_ddr_latency(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_get_ddr_latency, cmd_get_ddr_latency_options,
+      "cxl get-ddr-latency <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_i2c_read(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_i2c_read, cmd_i2c_read_options,
+      "cxl i2c-read <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_i2c_write(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_i2c_write, cmd_i2c_write_options,
+      "cxl i2c-write <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_ddr_ecc_err_info(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_get_ddr_ecc_err_info, cmd_get_ddr_ecc_err_info_options,
+      "cxl get-ddr-ecc-err-info <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_start_ddr_ecc_scrub(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_start_ddr_ecc_scrub, cmd_start_ddr_ecc_scrub_options,
+      "cxl start-ddr-ecc-scrub <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_ecc_scrub_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_ecc_scrub_status, cmd_ddr_ecc_scrub_status_options,
+      "cxl ddr-ecc-scrub-status <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_cont_scrub_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_cont_scrub_status, cmd_ddr_cont_scrub_status_options,
+      "cxl ddr-cont-scrub-status <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_cont_scrub_set(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_cont_scrub_set, cmd_ddr_cont_scrub_set_options,
+      "cxl core_volt_set <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_init_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_init_status, cmd_ddr_init_status_options,
+      "cxl ddr-init-status <mem0> [<mem1>..<memN>] [<options>]");
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_cxl_membridge_stats(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_get_cxl_membridge_stats, cmd_get_cxl_membridge_stats_options,
+      "cxl get_cxl_membridge_errors");
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_trigger_coredump(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_trigger_coredump, cmd_trigger_coredump_options,
+      "cxl trigger-coredump <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_err_inj_en(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_err_inj_en, cmd_ddr_err_inj_en_options,
+      "cxl ddr-err-inj-en <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_dimm_level_training_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_dimm_level_training_status, cmd_ddr_dimm_level_training_options,
+      "cxl ddr-dimm-level-training-status <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_param_set(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_param_set, cmd_ddr_param_set_options,
+      "cxl ddr_param_set <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_param_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_param_get, cmd_ddr_param_get_options,
+      "cxl ddr_param_get  <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_core_volt_set(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_core_volt_set, cmd_core_volt_set_options,
+      "cxl core_volt_set <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_core_volt_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_core_volt_get, cmd_core_volt_get_options,
+      "cxl core_volt_get  <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_oem_err_inj_viral(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_oem_err_inj_viral, cmd_oem_err_inj_viral_options,
+      "cxl oem_err_inj_viral <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_err_inj_ll_poison(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_err_inj_ll_poison, cmd_err_inj_ll_poison_options,
+      "cxl err_inj_ll_poison <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_pci_err_inj(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_pci_err_inj, cmd_pci_err_inj_options,
+      "cxl pci_err_inj <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_read_ltssm_states(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_read_ltssm_states, cmd_read_ltssm_states_options,
+      "cxl read-ltssm-state-changes <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_page_select_set(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_page_select_set, cmd_ddr_page_select_set_options,
+      "cxl ddr-page-select-set <<mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_page_select_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+  int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_page_select_get, cmd_ddr_page_select_get_options,
+      "cxl ddr-page-select-get <mem0> [<mem1>..<memN>] [<options>]");
+
+  return rc >= 0 ? 0 : EXIT_FAILURE;
+}