[Skiboot] [PATCH v8 12/24] MPIPL: Add OPAL API to register for dump

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Mon Jun 17 03:10:12 AEST 2019


This patch add new API to register for dump.
  u64 opal_mpipl_update(u8 ops, u64 src, u64 dest, u64 size)

  ops :
    OPAL_MPIPL_REGISTER_TAG
      Kernel metadata pointer. Kernel will send this to OPAL during MPIPL
      registration. Post MPIPL, kernel will request for this tag via
      mpipl_query_tag API.
        src  = kernel metadata address
        dest = ignore
        size = ignore

    OPAL_MPIPL_ADD_RANGE
      Add new entry to MPIPL table. Kernel will send src, dest and size.
      During MPIPL content from source address is moved to destination address.
        src  = Source start address
        dest = Destination start address
        size = size

    OPAL_MPIPL_REMOVE_RANGE
      Remove kernel requested entry from MPIPL table.
        src  = Source start address
        dest = Destination start address
        size = ignore

    OPAL_MPIPL_REMOVE_ALL
      Remove all kernel passed entry from MPIPL table.
        src  = ignore
        dest = ignore
        size = ignore

    OPAL_MPIPL_FREE_PRESERVED_MEMORY
      Post MPIPL, kernel will indicate OPAL that it has processed dump and
      it can clear/release metadata area.
        src  = ignore
        dest = ignore
        size = ignore

Return values:
  OPAL_SUCCESS   : Operation success
  OPAL_PARAMETER : Payload passed invalid data
  OPAL_RESOURCE  : Ran out of MDST or MDDT table size
  OPAL_HARDWARE  : MPIPL not supported

Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
 core/opal-dump.c    | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/opal-api.h  |  12 +++-
 include/opal-dump.h |   1 +
 3 files changed, 197 insertions(+), 1 deletion(-)

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
-- 
2.14.3



More information about the Skiboot mailing list