[v2,12/17] hdata: Add architected register support

Message ID 20180504102817.11059-13-hegdevasant@linux.vnet.ibm.com
State New
Headers show
Series
  • MPIPL support
Related show

Commit Message

Vasant Hegde May 4, 2018, 10:28 a.m.
Post MPIPL FSP/hostboot passes architected register data via HDAT. Add support
get architected register data from HDAT and pass it to kernel. Kernel will
use this data to generate vmcore and opalcore.

This patch moves 'proc_dump_area' ntuple from SPIRAH to SPIRAS..as HDAT provides
'proc_dump_area' under SPIRAS.

Device tree properties under /ibm,dump node:
  cpu-data-version - Architected register data format version
  cpu-data-size    - Each CPU register data size
  result-table     - Add entry for architected register
                     Based on cpu-data-size and result-table, kernel will be
		     able to get data for indivisual CPU/register.

Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
---
 hdata/spira.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 hdata/spira.h | 20 +++++++++++++++-----
 2 files changed, 65 insertions(+), 7 deletions(-)

Patch

diff --git a/hdata/spira.c b/hdata/spira.c
index 00bfa87a5..aa2733762 100644
--- a/hdata/spira.c
+++ b/hdata/spira.c
@@ -1121,6 +1121,47 @@  static void add_iplparams_sys_params(const void *iplp, struct dt_node *node)
 		dt_init_secureboot_node(p);
 }
 
+/* Map architected register data from HDAT memory to result-table */
+static int fadump_add_arch_regs(struct dt_node *node,
+				struct fadump *result_table, int *res_cnt)
+{
+	u64 size, *addr;
+	const struct HDIF_common_hdr *reg_hdif;
+	const struct HDIF_array_hdr *reg_data;
+	struct fadump_section *fadump_section;
+
+	reg_hdif = get_hdif(&spira.ntuples.proc_dump_area, PROC_DUMP_HDIF_SIG);
+	if (!reg_hdif) {
+		prlog(PR_ERR, "FADUMP: Architected register is missing\n");
+		return OPAL_HARDWARE;
+	}
+
+	reg_data = HDIF_get_idata(reg_hdif, PROC_DUMP_ARCH_REG_DATA, NULL);
+	if (!CHECK_SPPTR(reg_data)) {
+		prlog(PR_ERR, "FADUMP: Invalid architected register data\n");
+		return OPAL_HARDWARE;
+	}
+
+	/* Add each thread size */
+	dt_add_property_cells(node, "cpu-data-size",
+			      be32_to_cpu(reg_data->eactsz));
+	prlog(PR_TRACE, "FADUMP: Architected regs : thread count = %x, "
+	      "size of each thread = %x\n",
+	      be32_to_cpu(reg_data->ecnt), be32_to_cpu(reg_data->eactsz));
+
+	size = be32_to_cpu(reg_data->ecnt) * be32_to_cpu(reg_data->eactsz);
+	addr = (void *)reg_data + be32_to_cpu(reg_data->offset);
+
+	fadump_section = &(result_table->section[*res_cnt]);
+	fadump_section->source_type = DUMP_REGION_CPU_DATA;
+	fadump_section->source_addr = (u64)addr;
+	fadump_section->dest_addr = (u64)addr;
+	fadump_section->source_size = size;
+	fadump_section->dest_size = size;
+	(*res_cnt)++;
+	return OPAL_SUCCESS;
+}
+
 static void fadump_add_result_table(struct dt_node *node,
 				    const struct iplparams_iplparams *p)
 {
@@ -1148,9 +1189,9 @@  static void fadump_add_result_table(struct dt_node *node,
 
 	prlog(PR_DEBUG, "FADUMP: Dump found, MDRT count = 0x%x\n", mdrt_cnt);
 
-	/* Number of entries in MDRT table */
+	/* Number of entries in MDRT table + 1 for arch register data */
 	prop_size = sizeof(struct fadump) +
-		(mdrt_cnt * sizeof(struct fadump_section));
+		((mdrt_cnt + 1) * sizeof(struct fadump_section));
 	result_table = zalloc(prop_size);
 	if (!result_table) {
 		prlog(PR_ERR, "FADUMP: Failed to allocate memory\n");
@@ -1187,6 +1228,9 @@  static void fadump_add_result_table(struct dt_node *node,
 		return;
 	}
 
+	/* Add architected register data to result-table */
+	fadump_add_arch_regs(node, result_table, &j);
+
 	result_table->section_count = j;
 	/* Actual property size */
 	prop_size = sizeof(struct fadump) + (j * sizeof(struct fadump_section));
@@ -1212,6 +1256,9 @@  static void fadump_add_node(const struct iplparams_iplparams *p)
 	fw_load_area[3] = INITRAMFS_LOAD_SIZE;
 	dt_add_property(node, "fw-load-area", fw_load_area, sizeof(fw_load_area));
 
+	/* Architected register data format version */
+	dt_add_property_cells(node, "cpu-data-version", PROC_DUMP_ARCH_REG_VER);
+
 	fadump_add_result_table(node, p);
 }
 
@@ -1801,6 +1848,7 @@  static void fixup_spira(void)
 	spira.ntuples.hs_data = spiras->ntuples.hs_data;
 	spira.ntuples.ipmi_sensor = spiras->ntuples.ipmi_sensor;
 	spira.ntuples.node_stb_data = spiras->ntuples.node_stb_data;
+	spira.ntuples.proc_dump_area = spiras->ntuples.proc_dump_area;
 }
 
 /*
diff --git a/hdata/spira.h b/hdata/spira.h
index 46d7c70c8..e0766fd49 100644
--- a/hdata/spira.h
+++ b/hdata/spira.h
@@ -76,6 +76,7 @@  struct spira_ntuples {
 	struct spira_ntuple	hs_data;		/* 0x320 */
 	struct spira_ntuple	ipmi_sensor;		/* 0x360 */
 	struct spira_ntuple	node_stb_data;		/* 0x380 */
+	struct spira_ntuple	proc_dump_area;		/* 0x3a0 */
 };
 
 struct spira {
@@ -89,7 +90,7 @@  struct spira {
 	 *
 	 * According to FSP engineers, this is an okay thing to do.
 	 */
-	u8			reserved[0x80];
+	u8			reserved[0x40];
 } __packed __align(0x100);
 
 extern struct spira spira;
@@ -111,7 +112,6 @@  struct spirah_ntuples {
 	struct spira_ntuple	mdump_src;	/* 0x0a0 */
 	struct spira_ntuple	mdump_dst;	/* 0x0c0 */
 	struct spira_ntuple	mdump_res;	/* 0x0e0 */
-	struct spira_ntuple	proc_dump_area;	/* 0x100 */
 };
 
 struct spirah {
@@ -119,7 +119,7 @@  struct spirah {
 	struct HDIF_idata_ptr	ntuples_ptr;
 	__be64			pad;
 	struct spirah_ntuples	ntuples;
-	u8			reserved[0xE0];
+	u8			reserved[0x100];
 } __packed __align(0x100);
 
 extern struct spirah spirah;
@@ -132,7 +132,7 @@  extern struct spirah spirah;
 #define SPIRAS_VERSION_P9	0x50
 
 /* N-tuples in SPIRAS */
-#define SPIRAS_NTUPLES_COUNT	0x10
+#define SPIRAS_NTUPLES_COUNT	0x13
 
 struct spiras_ntuples {
 	struct HDIF_array_hdr	array_hdr;		/* 0x030 */
@@ -154,6 +154,7 @@  struct spiras_ntuples {
 	struct spira_ntuple	hbrt_data;		/* 0x220 */
 	struct spira_ntuple	ipmi_sensor;		/* 0x240 */
 	struct spira_ntuple	node_stb_data;		/* 0x260 */
+	struct spira_ntuple	proc_dump_area;		/* 0x280 */
 };
 
 struct spiras {
@@ -161,7 +162,7 @@  struct spiras {
 	struct HDIF_idata_ptr	ntuples_ptr;
 	__be64			pad;
 	struct spiras_ntuples	ntuples;
-	u8			reserved[0x180];
+	u8			reserved[0x160];
 } __packed __align(0x100);
 
 extern struct spiras *spiras;
@@ -1291,6 +1292,15 @@  struct hash_and_verification {
 	__be32 offset;
 } __packed;
 
+
+/* Processor dump area. Used by MPIPL boot to get architected register data */
+#define PROC_DUMP_HDIF_SIG	"ARCREG"
+
+/* Idata index 0 : Architected register data area */
+#define PROC_DUMP_ARCH_REG_DATA		0
+
+#define PROC_DUMP_ARCH_REG_VER		0x10	/* P9 format */
+
 static inline const char *cpu_state(u32 flags)
 {
 	switch ((flags & CPU_ID_VERIFY_MASK) >> CPU_ID_VERIFY_SHIFT) {