[Skiboot] [PATCH v7 12/22] hdata: Add result table property to "dump" node

Michael Neuling mikey at neuling.org
Thu May 9 11:16:54 AEST 2019


On Sat, 2019-04-13 at 14:45 +0530, Vasant Hegde wrote:
> During MPIPL hostboot updates MDRT table with details of memory movement
> (source, destination address, size, etc). Convert these details to fadump
> structure format and pass it to kernel via 'result-table' property.
> 
> Device tree property:
>   /ibm,opal/dump/result-table - follows fadump structure format
> 
> Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
> ---
>  hdata/spira.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hdata/spira.h |  4 +++
>  2 files changed, 97 insertions(+)
> 
> diff --git a/hdata/spira.c b/hdata/spira.c
> index 34e3034ce..fa6149322 100644
> --- a/hdata/spira.c
> +++ b/hdata/spira.c
> @@ -26,6 +26,8 @@
>  #include <fsp-attn.h>
>  #include <fsp-leds.h>
>  #include <skiboot.h>
> +#include <mem_region-malloc.h>
> +#include <opal-dump.h>
>  
>  #include "hdata.h"
>  #include "hostservices.h"
> @@ -1055,6 +1057,94 @@ static void dt_init_secureboot_node(const struct iplparams_sysparams *sysparams)
>  	dt_add_property_cells(node, "hw-key-hash-size", hw_key_hash_size);
>  }
>  
> +static void opal_dump_add_result_table(const struct iplparams_iplparams *p)
> +{
> +	int i, j = 0;
> +	u32 mdrt_cnt = spira.ntuples.mdump_res.act_cnt;
> +	u32 mdrt_max_cnt = MDRT_TABLE_SIZE / sizeof(struct mdrt_table);
> +	size_t prop_size;
> +	struct mdrt_table *mdrt = (void *)(MDRT_TABLE_BASE);
> +	struct fadump_section *fadump_section;
> +	struct fadump *result_table;
> +	struct dt_node *dump_node;
> +
> +	dump_node = dt_find_by_path(opal_node, "dump");
> +	if (!dump_node)
> +		return;
> +
> +	/* Check boot params to detect MPIPL boot or not */
> +	if (p->cec_ipl_maj_type != IPLPARAMS_MAJ_TYPE_REIPL)
> +		return;
> +	/*
> +	 * On FSP system we get minor type as post dump IPL and on BMC system
> +	 * we get platform reboot. Hence lets check for both values
> +	 */
> +	if (p->cec_ipl_min_type != IPLPARAMS_MIN_TYPE_POST_DUMP &&
> +	    p->cec_ipl_min_type != IPLPARAMS_MIN_TYPE_PLAT_REBOOT) {
> +		prlog(PR_DEBUG, "DUMP: Non MPIPL reboot "
> +		      "[minor type = 0x%x]\n", p->cec_ipl_min_type);
> +		return;
> +	}
> +	if (p->cec_ipl_attrib != IPLPARAMS_ATTRIB_MEM_PRESERVE) {
> +		prlog(PR_DEBUG, "DUMP: Memory not preserved\n");
> +		return;
> +	}
> +
> +	if (mdrt_cnt == 0 || mdrt_cnt >= mdrt_max_cnt) {
> +		prlog(PR_DEBUG, "DUMP: Invalid MDRT count : %x\n", mdrt_cnt);
> +		return;
> +	}
> +
> +	prlog(PR_NOTICE, "DUMP: Dump found, MDRT count = 0x%x\n", mdrt_cnt);
> +
> +	/* Calculcate property size */
> +	prop_size = sizeof(struct fadump) +
> +		(mdrt_cnt * sizeof(struct fadump_section));
> +	result_table = zalloc(prop_size);
> +	if (!result_table) {
> +		prlog(PR_ERR, "DUMP: Failed to allocate memory\n");
> +		return;
> +	}
> +
> +	/* Copy MDRT entries to result-table */
> +	result_table->fadump_section_size = sizeof(struct fadump_section);
> +	for (i = 0; i < mdrt_cnt; i++) {
> +		/* Skip garbage entry */
> +		if ((mdrt->dest_addr == 0) || (mdrt->size == 0)) {
> +			mdrt++;
> +			continue;
> +		}
> +
> +		if (mdrt->dump_type != DUMP_TYPE_FADUMP) {
> +			mdrt++;
> +			continue;
> +		}
> +
> +		fadump_section = &(result_table->section[j++]);
> +		fadump_section->source_type = mdrt->data_region;
> +		/* Clear top bit */
> +		fadump_section->source_addr =
> +			cpu_to_be64(mdrt->src_addr & ~(HRMOR_BIT));
> +		fadump_section->dest_addr =
> +			cpu_to_be64(mdrt->dest_addr & ~(HRMOR_BIT));
> +		fadump_section->source_size = cpu_to_be64(mdrt->size);
> +		fadump_section->dest_size = cpu_to_be64(mdrt->size);
> +		mdrt++;
> +	}
> +
> +	if (j == 0) {
> +		prlog(PR_DEBUG, "DUMP: MDRT table is empty\n");
> +		free(result_table);
> +		return;
> +	}
> +
> +	result_table->section_count = cpu_to_be16(j);
> +	/* Actual property size */
> +	prop_size = sizeof(struct fadump) + (j * sizeof(struct fadump_section));
> +	dt_add_property(dump_node, "result-table", result_table, prop_size);

This concerns me, especially since it's an API.

How is this structure communicated to the kernel? This seems to be a large flat
structure passed from opal to the kernel here. 

What happens if we need to make a change to this format in future?  How are we
going to communicate that to the kernel?  Do we need a compat or version
property here?

Why don't we represent the structure more in the device tree, rather than
flattening it here?

Mikey

> +	free(result_table);
> +}
> +
>  static void add_opal_dump_node(void)
>  {
>  	u64 fw_load_area[4];
> @@ -1218,6 +1308,9 @@ static void add_iplparams_ipl_params(const void *iplp, struct dt_node *node)
>  	else
>  		dt_add_property_strings(led_node, DT_PROPERTY_LED_MODE,
>  					LED_MODE_GUIDING_LIGHT);
> +
> +	/* Populate opal dump result table */
> +	opal_dump_add_result_table(p);
>  }
>  
>  static void add_iplparams_serials(const void *iplp, struct dt_node *node)
> diff --git a/hdata/spira.h b/hdata/spira.h
> index 80e75d220..a8b68327d 100644
> --- a/hdata/spira.h
> +++ b/hdata/spira.h
> @@ -401,8 +401,12 @@ struct iplparams_iplparams {
>  #define IPLPARAMS_FSP_FW_IPL_SIDE_TEMP	0x01
>  	uint8_t		ipl_speed;
>  	__be16		cec_ipl_attrib;
> +#define IPLPARAMS_ATTRIB_MEM_PRESERVE	PPC_BIT16(2)
>  	uint8_t		cec_ipl_maj_type;
> +#define IPLPARAMS_MAJ_TYPE_REIPL	0x1
>  	uint8_t		cec_ipl_min_type;
> +#define IPLPARAMS_MIN_TYPE_POST_DUMP	0xc
> +#define IPLPARAMS_MIN_TYPE_PLAT_REBOOT	0xd
>  	uint8_t		os_ipl_mode;
>  	uint8_t		keylock_pos;
>  	uint8_t		lmb_size;



More information about the Skiboot mailing list