@@ -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)
{
@@ -121,6 +217,88 @@ 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 opal_mpipl_ops ops,
+ u64 src, u64 dest, u64 size)
+{
+ int rc;
+
+ switch (ops) {
+ 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:
+ /* Clear MDRT table */
+ memset((void *)MDRT_TABLE_BASE, 0, MDRT_TABLE_SIZE);
+ /* Set MDRT count to max allocated count */
+ ntuple_mdrt->act_cnt = MDRT_TABLE_SIZE / sizeof(struct mdrt_table);
+ rc = OPAL_SUCCESS;
+ prlog(PR_NOTICE, "Payload Invalidated MPIPL\n");
+ break;
+ default:
+ prlog(PR_DEBUG, "Unsupported MPIPL update operation : 0x%x\n", ops);
+ rc = OPAL_PARAMETER;
+ break;
+ }
+
+ return rc;
+}
+
void opal_mpipl_init(void)
{
void *mdst_base = (void *)MDST_TABLE_BASE;
@@ -154,4 +332,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);
}
@@ -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,14 @@ enum {
OPAL_PCI_P2P_TARGET = 1,
};
+/* MPIPL update operations */
+enum opal_mpipl_ops {
+ OPAL_MPIPL_ADD_RANGE = 0,
+ OPAL_MPIPL_REMOVE_RANGE = 1,
+ OPAL_MPIPL_REMOVE_ALL = 2,
+ OPAL_MPIPL_FREE_PRESERVED_MEMORY= 3,
+};
+
#endif /* __ASSEMBLY__ */
#endif /* __OPAL_API_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
This patch add new API to register for dump region. u64 opal_mpipl_update(u8 ops, u64 src, u64 dest, u64 size) ops : 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@linux.vnet.ibm.com> --- core/opal-dump.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/opal-api.h | 11 +++- include/opal-dump.h | 1 + 3 files changed, 192 insertions(+), 1 deletion(-)