diff --git a/core/opal-dump.c b/core/opal-dump.c
index ea9d00ead..bef54ebe1 100644
--- a/core/opal-dump.c
+++ b/core/opal-dump.c
@@ -96,6 +96,102 @@ static int opal_mpipl_add_entry(u8 region, u64 src, u64 dest, u64 size)
 	return OPAL_SUCCESS;
 }
 
+/* Remove entry from source (MDST) table */
+static int opal_mpipl_remove_entry_mdst(bool remove_all, u8 region, u64 src)
+{
+	bool found = false;
+	int i, j;
+	struct mdst_table *tmp_mdst;
+	struct mdst_table *mdst = (void *)(MDST_TABLE_BASE);
+
+	for (i = 0; i < ntuple_mdst->act_cnt;) {
+		if (mdst->data_region != region) {
+			mdst++;
+			i++;
+			continue;
+		}
+
+		if (remove_all != true && mdst->addr != (src | HRMOR_BIT)) {
+			mdst++;
+			i++;
+			continue;
+		}
+
+		tmp_mdst = mdst;
+		memset(tmp_mdst, 0, sizeof(struct mdst_table));
+
+		for (j = i; j < ntuple_mdst->act_cnt - 1; j++) {
+			memcpy((void *)tmp_mdst,
+			       (void *)(tmp_mdst + 1), sizeof(struct mdst_table));
+			tmp_mdst++;
+			memset(tmp_mdst, 0, sizeof(struct mdst_table));
+		}
+
+		ntuple_mdst->act_cnt--;
+
+		if (remove_all == false) {
+			found = true;
+			break;
+		}
+	}  /* end - for loop */
+
+	if (remove_all == false && found == false) {
+		prlog(PR_DEBUG,
+		      "Source address [0x%llx] not found in MDST table\n", src);
+		return OPAL_PARAMETER;
+	}
+
+	return OPAL_SUCCESS;
+}
+
+/* Remove entry from destination (MDDT) table */
+static int opal_mpipl_remove_entry_mddt(bool remove_all, u8 region, u64 dest)
+{
+	bool found = false;
+	int i, j;
+	struct mddt_table *tmp_mddt;
+	struct mddt_table *mddt = (void *)(MDDT_TABLE_BASE);
+
+	for (i = 0; i < ntuple_mddt->act_cnt;) {
+		if (mddt->data_region != region) {
+			mddt++;
+			i++;
+			continue;
+		}
+
+		if (remove_all != true && mddt->addr != (dest | HRMOR_BIT)) {
+			mddt++;
+			i++;
+			continue;
+		}
+
+		tmp_mddt = mddt;
+		memset(tmp_mddt, 0, sizeof(struct mddt_table));
+
+		for (j = i; j < ntuple_mddt->act_cnt - 1; j++) {
+			memcpy((void *)tmp_mddt,
+			       (void *)(tmp_mddt + 1), sizeof(struct mddt_table));
+			tmp_mddt++;
+			memset(tmp_mddt, 0, sizeof(struct mddt_table));
+		}
+
+		ntuple_mddt->act_cnt--;
+
+		if (remove_all == false) {
+			found = true;
+			break;
+		}
+	}  /* end - for loop */
+
+	if (remove_all == false && found == false) {
+		prlog(PR_DEBUG,
+		      "Dest address [0x%llx] not found in MDDT table\n", dest);
+		return OPAL_PARAMETER;
+	}
+
+	return OPAL_SUCCESS;
+}
+
 /* Register for OPAL dump.  */
 static void opal_mpipl_register(void)
 {
@@ -120,6 +216,92 @@ static void opal_mpipl_register(void)
 			     SKIBOOT_BASE, opal_dest, opal_size);
 }
 
+static int payload_mpipl_register(u64 src, u64 dest, u64 size)
+{
+	if (!opal_addr_valid((void *)src)) {
+		prlog(PR_DEBUG, "Invalid source address [0x%llx]\n", src);
+		return OPAL_PARAMETER;
+	}
+
+	if (!opal_addr_valid((void *)dest)) {
+		prlog(PR_DEBUG, "Invalid dest address [0x%llx]\n", dest);
+		return OPAL_PARAMETER;
+	}
+
+	if (size <= 0) {
+		prlog(PR_DEBUG, "Invalid size [0x%llx]\n", size);
+		return OPAL_PARAMETER;
+	}
+
+	return opal_mpipl_add_entry(DUMP_REGION_KERNEL, src, dest, size);
+}
+
+static int payload_mpipl_unregister(u64 src, u64 dest)
+{
+	int rc;
+
+	/* Remove src from MDST table */
+	rc = opal_mpipl_remove_entry_mdst(false, DUMP_REGION_KERNEL, src);
+	if (rc)
+		return rc;
+
+	/* Remove dest from MDDT table */
+	rc = opal_mpipl_remove_entry_mddt(false, DUMP_REGION_KERNEL, dest);
+	return rc;
+}
+
+static int payload_mpipl_unregister_all(void)
+{
+	opal_mpipl_remove_entry_mdst(true, DUMP_REGION_KERNEL, 0);
+	opal_mpipl_remove_entry_mddt(true, DUMP_REGION_KERNEL, 0);
+
+	return OPAL_SUCCESS;
+}
+
+static int64_t opal_mpipl_update(enum mpipl_ops ops,
+				 u64 src, u64 dest, u64 size)
+{
+	int rc;
+
+	if (ops > OPAL_MPIPL_FREE_PRESERVED_MEMORY) {
+		prlog(PR_DEBUG, "Unsupported operation : 0x%x\n", ops);
+		return OPAL_PARAMETER;
+	}
+
+	switch (ops) {
+	case OPAL_MPIPL_REGISTER_TAG:
+		mpipl_metadata->kernel_tag = src;
+		prlog(PR_NOTICE, "Payload sent metadata tag : 0x%llx\n", src);
+		rc = OPAL_SUCCESS;
+		break;
+	case OPAL_MPIPL_ADD_RANGE:
+		rc = payload_mpipl_register(src, dest, size);
+		if (!rc)
+			prlog(PR_NOTICE, "Payload registered for MPIPL\n");
+		break;
+	case OPAL_MPIPL_REMOVE_RANGE:
+		rc = payload_mpipl_unregister(src, dest);
+		if (!rc) {
+			prlog(PR_NOTICE, "Payload removed entry from MPIPL."
+			      "[src : 0x%llx, dest : 0x%llx]\n", src, dest);
+		}
+		break;
+	case OPAL_MPIPL_REMOVE_ALL:
+		rc = payload_mpipl_unregister_all();
+		if (!rc)
+			prlog(PR_NOTICE, "Payload unregistered for MPIPL\n");
+		break;
+	case OPAL_MPIPL_FREE_PRESERVED_MEMORY:
+		rc = OPAL_SUCCESS;
+		break;
+	default:
+		rc = OPAL_PARAMETER;
+		break;
+	}
+
+	return rc;
+}
+
 void opal_mpipl_init(void)
 {
 	void *mdst_base = (void *)MDST_TABLE_BASE;
@@ -153,4 +335,7 @@ void opal_mpipl_init(void)
 	ntuple_mddt->act_cnt = 0;
 
 	opal_mpipl_register();
+
+	/* OPAL API for MPIPL update */
+	opal_register(OPAL_MPIPL_UPDATE, opal_mpipl_update, 4);
 }
diff --git a/include/opal-api.h b/include/opal-api.h
index 0b0ae1969..bc6af2014 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -232,7 +232,8 @@
 #define OPAL_XIVE_GET_VP_STATE			170 /* Get NVT state */
 #define OPAL_NPU_MEM_ALLOC			171
 #define OPAL_NPU_MEM_RELEASE			172
-#define OPAL_LAST				172
+#define OPAL_MPIPL_UPDATE			173
+#define OPAL_LAST				173
 
 #define QUIESCE_HOLD			1 /* Spin all calls at entry */
 #define QUIESCE_REJECT			2 /* Fail all calls with OPAL_BUSY */
@@ -1215,6 +1216,15 @@ enum {
 	OPAL_PCI_P2P_TARGET	= 1,
 };
 
+/* MPIPL update operations */
+enum mpipl_ops {
+	OPAL_MPIPL_REGISTER_TAG		= 0,
+	OPAL_MPIPL_ADD_RANGE		= 1,
+	OPAL_MPIPL_REMOVE_RANGE		= 2,
+	OPAL_MPIPL_REMOVE_ALL		= 3,
+	OPAL_MPIPL_FREE_PRESERVED_MEMORY= 4,
+};
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __OPAL_API_H */
diff --git a/include/opal-dump.h b/include/opal-dump.h
index 0838ee124..9f5f102be 100644
--- a/include/opal-dump.h
+++ b/include/opal-dump.h
@@ -34,6 +34,7 @@
 #define DUMP_REGION_CONSOLE	0x01
 #define DUMP_REGION_HBRT_LOG	0x02
 #define DUMP_REGION_OPAL_MEMORY	0x03
+#define DUMP_REGION_KERNEL	0x80
 
 /* Mainstore memory to be captured by FSP SYSDUMP */
 #define DUMP_TYPE_SYSDUMP		0xF5
