aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/opal-dump.c61
-rw-r--r--include/opal-api.h20
2 files changed, 81 insertions, 0 deletions
diff --git a/core/opal-dump.c b/core/opal-dump.c
index bb90c45..15f8214 100644
--- a/core/opal-dump.c
+++ b/core/opal-dump.c
@@ -41,6 +41,10 @@ static struct spira_ntuple *ntuple_mdrt;
static struct mpipl_metadata *mpipl_metadata;
+/* Dump metadata area */
+static struct opal_mpipl_fadump *opal_mpipl_data;
+
+
static int opal_mpipl_add_entry(u8 region, u64 src, u64 dest, u64 size)
{
int i, max_cnt;
@@ -329,6 +333,60 @@ static int64_t opal_mpipl_register_tag(enum opal_mpipl_tags tag,
return rc;
}
+static void post_mpipl_get_opal_data(void)
+{
+ struct mdrt_table *mdrt = (void *)(MDRT_TABLE_BASE);
+ int i, j = 0, count = 0;
+ u32 mdrt_cnt = ntuple_mdrt->act_cnt;
+ struct opal_mpipl_region *region;
+
+ /* Count OPAL dump regions */
+ for (i = 0; i < mdrt_cnt; i++) {
+ if (mdrt->data_region == DUMP_REGION_OPAL_MEMORY)
+ count++;
+ mdrt++;
+ }
+
+ if (count == 0) {
+ prlog(PR_INFO, "OPAL dump is not available\n");
+ return;
+ }
+
+ opal_mpipl_data = zalloc(sizeof(struct opal_mpipl_fadump) +
+ count * sizeof(struct opal_mpipl_region));
+ if (!opal_mpipl_data) {
+ prlog(PR_ERR, "Failed to allocate memory\n");
+ return;
+ }
+
+ /* Fill OPAL dump details */
+ opal_mpipl_data->version = OPAL_MPIPL_VERSION;
+ opal_mpipl_data->crashing_pir = mpipl_metadata->crashing_pir;
+ opal_mpipl_data->region_cnt = count;
+ region = opal_mpipl_data->region;
+
+ mdrt = (void *)(MDRT_TABLE_BASE);
+ for (i = 0; i < mdrt_cnt; i++) {
+ if (mdrt->data_region != DUMP_REGION_OPAL_MEMORY) {
+ mdrt++;
+ continue;
+ }
+
+ region[j].src = mdrt->src_addr & ~(HRMOR_BIT);
+ region[j].dest = mdrt->dest_addr & ~(HRMOR_BIT);
+ region[j].size = mdrt->size;
+
+ prlog(PR_NOTICE, "OPAL reserved region %d - src : 0x%llx, "
+ "dest : 0x%llx, size : 0x%llx\n", j, region[j].src,
+ region[j].dest, region[j].size);
+
+ mdrt++;
+ j++;
+ if (j == count)
+ break;
+ }
+}
+
void opal_mpipl_save_crashing_pir(void)
{
mpipl_metadata->crashing_pir = this_cpu()->pir;
@@ -353,6 +411,9 @@ void opal_mpipl_init(void)
/* Get metadata area pointer */
mpipl_metadata = (void *)(DUMP_METADATA_AREA_BASE);
+ if (dt_find_property(dump_node, "mpipl-boot"))
+ post_mpipl_get_opal_data();
+
/* Clear OPAL metadata area */
if (sizeof(struct mpipl_metadata) > DUMP_METADATA_AREA_SIZE) {
prlog(PR_ERR, "INSUFFICIENT OPAL METADATA AREA\n");
diff --git a/include/opal-api.h b/include/opal-api.h
index 1a1f380..7d8e046 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -1223,6 +1223,26 @@ enum opal_mpipl_tags {
OPAL_MPIPL_TAG_BOOT_MEM = 3,
};
+/* Preserved memory details */
+struct opal_mpipl_region {
+ u64 src;
+ u64 dest;
+ u64 size;
+};
+
+/* Structure version */
+#define OPAL_MPIPL_VERSION 0x01
+
+struct opal_mpipl_fadump {
+ u8 version;
+ u8 reserved[7];
+ u32 crashing_pir; /* OPAL crashing CPU PIR */
+ u32 cpu_data_version;
+ u32 cpu_data_size;
+ u32 region_cnt;
+ struct opal_mpipl_region region[];
+} __packed;
+
#endif /* __ASSEMBLY__ */
#endif /* __OPAL_API_H */