[Skiboot] [PATCH v8 10/24] MPIPL: Register for OPAL dump

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Fri Jun 28 20:36:21 AEST 2019


On 06/28/2019 07:03 AM, Nicholas Piggin wrote:
> Vasant Hegde's on June 17, 2019 3:10 am:
>> This patch adds support to register for OPAL dump.
>>    - Calculate memory required to capture OPAL dump
>>    - Reserve OPAL dump destination memory
>>    - Add OPAL dump details to MDST and MDDT table
>>
>> Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
>> ---
>>   core/Makefile.inc   |   2 +-
>>   core/init.c         |   6 ++-
>>   core/opal-dump.c    | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   include/opal-dump.h |   4 ++
>>   4 files changed, 153 insertions(+), 2 deletions(-)
>>   create mode 100644 core/opal-dump.c
>>
>> diff --git a/core/Makefile.inc b/core/Makefile.inc
>> index 21c12fb8d..c2c9731db 100644
>> --- a/core/Makefile.inc
>> +++ b/core/Makefile.inc
>> @@ -10,7 +10,7 @@ CORE_OBJS += console-log.o ipmi.o time-utils.o pel.o pool.o errorlog.o
>>   CORE_OBJS += timer.o i2c.o rtc.o flash.o sensor.o ipmi-opal.o
>>   CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o powercap.o psr.o
>>   CORE_OBJS += pci-dt-slot.o direct-controls.o cpufeatures.o
>> -CORE_OBJS += flash-firmware-versions.o
>> +CORE_OBJS += flash-firmware-versions.o opal-dump.o
>>   
>>   ifeq ($(SKIBOOT_GCOV),1)
>>   CORE_OBJS += gcov-profiling.o
>> diff --git a/core/init.c b/core/init.c
>> index 3db9df314..03776537e 100644
>> --- a/core/init.c
>> +++ b/core/init.c
>> @@ -1,4 +1,4 @@
>> -/* Copyright 2013-2016 IBM Corp.
>> +/* Copyright 2013-2019 IBM Corp.
>>    *
>>    * Licensed under the Apache License, Version 2.0 (the "License");
>>    * you may not use this file except in compliance with the License.
>> @@ -55,6 +55,7 @@
>>   #include <sbe-p9.h>
>>   #include <debug_descriptor.h>
>>   #include <occ.h>
>> +#include <opal-dump.h>
>>   
>>   enum proc_gen proc_gen;
>>   unsigned int pcie_max_link_speed;
>> @@ -1173,6 +1174,9 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
>>   	if (platform.init)
>>   		platform.init();
>>   
>> +	/* init opal dump */
>> +	opal_mpipl_init();
>> +
>>   	/* Read in NVRAM and set it up */
>>   	nvram_init();
>>   
> 
> So you're reserving memory and adding important OPAL memory to the MPIPL
> ranges just in case, even if the host won't be using it?

Yes.
   - This is to make sure each layer takes care of its reservation. OPAL should 
take care of
     memory reservation for OPAL/ kernel should take care of kernel memory 
reservation.
   - Also if future if we support early OPAL crashes then we can't really wait 
for kernel to
     reserve memory.

   - Kernel can always go and capture OPAL dump irrespective of dump method its 
using.


Probably I should call opal_mpipl_init() bit late in the init path.

> 
> It seems nicer if you would just advertise in the dt what the important
> OPAL address ranges are, and the host can preserve them if it wants to
> do OPAL dumps.

I don't think so.


> 
>> diff --git a/core/opal-dump.c b/core/opal-dump.c
>> new file mode 100644
>> index 000000000..dc364fab1
>> --- /dev/null
>> +++ b/core/opal-dump.c
>> @@ -0,0 +1,143 @@
>> +/* Copyright 2019 IBM Corp.
>> + *
>> + * Licensed under the Apache License, Version 2.0 (the "License");
>> + * you may not use this file except in compliance with the License.
>> + * You may obtain a copy of the License at
>> + *
>> + *	http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> + * implied.
>> + * See the License for the specific language governing permissions and
>> + * limitations under the License.
>> + */
>> +
>> +#define pr_fmt(fmt)	"DUMP: " fmt
>> +
>> +#include <device.h>
>> +#include <mem-map.h>
>> +#include <mem_region.h>
>> +#include <mem_region-malloc.h>
>> +#include <opal.h>
>> +#include <opal-dump.h>
>> +#include <opal-internal.h>
>> +#include <skiboot.h>
>> +
>> +#include <ccan/endian/endian.h>
>> +
>> +#include "hdata/spira.h"
>> +
>> +/* Actual address of MDST and MDDT table */
>> +#define MDST_TABLE_BASE		(SKIBOOT_BASE + MDST_TABLE_OFF)
>> +#define MDDT_TABLE_BASE		(SKIBOOT_BASE + MDDT_TABLE_OFF)
>> +
>> +static struct spira_ntuple *ntuple_mdst;
>> +static struct spira_ntuple *ntuple_mddt;
>> +static struct spira_ntuple *ntuple_mdrt;
>> +
>> +static int opal_mpipl_add_entry(u8 region, u64 src, u64 dest, u64 size)
>> +{
>> +	int i, max_cnt;
>> +	struct mdst_table *mdst;
>> +	struct mddt_table *mddt;
>> +
>> +	max_cnt = MDST_TABLE_SIZE / sizeof(struct mdst_table);
>> +	if (ntuple_mdst->act_cnt >= max_cnt) {
>> +		prlog(PR_DEBUG, "MDST table is full\n");
>> +		return OPAL_RESOURCE;
>> +	}
>> +
>> +	max_cnt = MDDT_TABLE_SIZE / sizeof(struct mddt_table);
>> +	if (ntuple_mdst->act_cnt >= max_cnt) {
>> +		prlog(PR_DEBUG, "MDDT table is full\n");
>> +		return OPAL_RESOURCE;
>> +	}
>> +
>> +	/* Use relocated memory address */
>> +	mdst = (void *)(MDST_TABLE_BASE);
>> +	mddt = (void *)(MDDT_TABLE_BASE);
>> +
>> +	/* Check for duplicate entry */
>> +	for (i = 0; i < ntuple_mdst->act_cnt; i++) {
>> +		if (mdst->addr == (src | HRMOR_BIT)) {
>> +			prlog(PR_DEBUG,
>> +			      "Duplicate source address : 0x%llx", src);
>> +			return OPAL_PARAMETER;
>> +		}
>> +		mdst++;
>> +	}
>> +	for (i = 0; i < ntuple_mddt->act_cnt; i++) {
>> +		if (mddt->addr == (dest | HRMOR_BIT)) {
>> +			prlog(PR_DEBUG,
>> +			      "Duplicate destination address : 0x%llx", dest);
>> +			return OPAL_PARAMETER;
>> +		}
>> +		mddt++;
>> +	}
>> +
>> +	/* Add OPAL source address to MDST entry */
>> +	mdst->addr = src | HRMOR_BIT;
>> +	mdst->data_region = region;
>> +	mdst->size = size;
>> +	ntuple_mdst->act_cnt++;
>> +
>> +	/* Add OPAL destination address to MDDT entry */
>> +	mddt->addr = dest | HRMOR_BIT;
>> +	mddt->data_region = region;
>> +	mddt->size = size;
>> +	ntuple_mddt->act_cnt++;
>> +
>> +	prlog(PR_TRACE, "Added new entry. src : 0x%llx, dest : 0x%llx,"
>> +	      " size : 0x%llx\n", src, dest, size);
>> +	return OPAL_SUCCESS;
>> +}
>> +
>> +/* Register for OPAL dump.  */
>> +static void opal_mpipl_register(void)
>> +{
>> +	u64 opal_dest, opal_size;
>> +
>> +	/* Get OPAL runtime size */
>> +	if (!dt_find_property(opal_node, "opal-runtime-size")) {
>> +		prlog(PR_DEBUG, "Could not get OPAL runtime size\n");
>> +		return;
>> +	}
> 
> As an aside, is it best practice to read your own device tree for this
> kind of thing? As opposed to just exporting it from the code which set
> the dt entry.

I think its fine to read from DT (we have been doing that) instead of creating
so many global variables.

-Vasant



More information about the Skiboot mailing list