Skip to content

Commit

Permalink
MPIPL: Register for OPAL dump
Browse files Browse the repository at this point in the history
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@linux.vnet.ibm.com>
[oliver: rebased]
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
  • Loading branch information
Vasant Hegde authored and oohal committed Aug 15, 2019
1 parent 0cadc98 commit 1ba3198
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 1 deletion.
2 changes: 1 addition & 1 deletion core/Makefile.inc
Expand Up @@ -12,7 +12,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
Expand Down
4 changes: 4 additions & 0 deletions core/init.c
Expand Up @@ -44,6 +44,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;
Expand Down Expand Up @@ -1255,6 +1256,9 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
/* Create the LPC bus interrupt-map on P9 */
lpc_finalize_interrupts();

/* init opal dump */
opal_mpipl_init();

/* Add the list of interrupts going to OPAL */
add_opal_interrupts();

Expand Down
144 changes: 144 additions & 0 deletions core/opal-dump.c
@@ -0,0 +1,144 @@
/* 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;
}
opal_size = dt_prop_get_u64(opal_node, "opal-runtime-size");
if (!opal_size) {
prlog(PR_DEBUG, "OPAL runtime size is zero\n");
return;
}

/* Calculate and reserve OPAL dump destination memory */
opal_dest = SKIBOOT_BASE + opal_size;
mem_reserve_fw("ibm,firmware-dump", opal_dest, opal_size);

/* Add OPAL reservation detail to MDST/MDDT table */
opal_mpipl_add_entry(DUMP_REGION_OPAL_MEMORY,
SKIBOOT_BASE, opal_dest, opal_size);
}

void opal_mpipl_init(void)
{
void *mdst_base = (void *)MDST_TABLE_BASE;
void *mddt_base = (void *)MDDT_TABLE_BASE;
struct dt_node *dump_node;

dump_node = dt_find_by_path(opal_node, "dump");
if (!dump_node)
return;

/* Get MDST and MDDT ntuple from SPIRAH */
ntuple_mdst = &(spirah.ntuples.mdump_src);
ntuple_mddt = &(spirah.ntuples.mdump_dst);
ntuple_mdrt = &(spirah.ntuples.mdump_res);

/* Clear MDST and MDDT table */
memset(mdst_base, 0, MDST_TABLE_SIZE);
ntuple_mdst->act_cnt = 0;
memset(mddt_base, 0, MDDT_TABLE_SIZE);
ntuple_mddt->act_cnt = 0;

opal_mpipl_register();
}
4 changes: 4 additions & 0 deletions include/opal-dump.h
Expand Up @@ -19,6 +19,7 @@

#define DUMP_REGION_CONSOLE 0x01
#define DUMP_REGION_HBRT_LOG 0x02
#define DUMP_REGION_OPAL_MEMORY 0x03

/* Mainstore memory to be captured by FSP SYSDUMP */
#define DUMP_TYPE_SYSDUMP 0xF5
Expand Down Expand Up @@ -106,4 +107,7 @@ struct proc_reg_data {
uint64_t reg_val;
} __packed;

/* init opal dump */
extern void opal_mpipl_init(void);

#endif /* __OPAL_DUMP_H */

0 comments on commit 1ba3198

Please sign in to comment.