583 lines
16 KiB
C
583 lines
16 KiB
C
/* 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 <chip.h>
|
|
#include <cpu.h>
|
|
#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 <sbe-p9.h>
|
|
#include <skiboot.h>
|
|
|
|
#include <ccan/endian/endian.h>
|
|
|
|
#include "hdata/spira.h"
|
|
|
|
/* XXX Ideally we should use HDAT provided data (proc_dump_area->thread_size).
|
|
* But we are not getting this data durig boot. Hence lets reserve fixed
|
|
* memory for architected registers data collection.
|
|
*/
|
|
#define ARCH_REGS_DATA_SIZE_PER_CHIP (512 * 1024)
|
|
|
|
/* 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)
|
|
#define PROC_DUMP_AREA_BASE (SKIBOOT_BASE + PROC_DUMP_AREA_OFF)
|
|
|
|
static struct spira_ntuple *ntuple_mdst;
|
|
static struct spira_ntuple *ntuple_mddt;
|
|
static struct spira_ntuple *ntuple_mdrt;
|
|
|
|
static struct mpipl_metadata *mpipl_metadata;
|
|
|
|
/* Dump metadata area */
|
|
static struct opal_mpipl_fadump *opal_mpipl_data;
|
|
static struct opal_mpipl_fadump *opal_mpipl_cpu_data;
|
|
|
|
/*
|
|
* Number of tags passed by OPAL to kernel after MPIPL boot.
|
|
* Currently it supports below tags:
|
|
* - CPU register data area
|
|
* - OPAL metadata area address
|
|
* - Kernel passed tag during MPIPL registration
|
|
* - Post MPIPL boot memory size
|
|
*/
|
|
#define MAX_OPAL_MPIPL_TAGS 0x04
|
|
static u64 opal_mpipl_tags[MAX_OPAL_MPIPL_TAGS];
|
|
static int opal_mpipl_max_tags = MAX_OPAL_MPIPL_TAGS;
|
|
|
|
static u64 opal_dump_addr, opal_dump_size;
|
|
|
|
static bool mpipl_enabled;
|
|
|
|
static int opal_mpipl_add_entry(u8 region, u64 src, u64 dest, u64 size)
|
|
{
|
|
int i;
|
|
int mdst_cnt = be16_to_cpu(ntuple_mdst->act_cnt);
|
|
int mddt_cnt = be16_to_cpu(ntuple_mddt->act_cnt);
|
|
struct mdst_table *mdst;
|
|
struct mddt_table *mddt;
|
|
|
|
if (mdst_cnt >= MDST_TABLE_SIZE / sizeof(struct mdst_table)) {
|
|
prlog(PR_DEBUG, "MDST table is full\n");
|
|
return OPAL_RESOURCE;
|
|
}
|
|
|
|
if (mddt_cnt >= MDDT_TABLE_SIZE / sizeof(struct mddt_table)) {
|
|
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 < mdst_cnt; i++) {
|
|
if (be64_to_cpu(mdst->addr) == (src | HRMOR_BIT)) {
|
|
prlog(PR_DEBUG,
|
|
"Duplicate source address : 0x%llx", src);
|
|
return OPAL_PARAMETER;
|
|
}
|
|
mdst++;
|
|
}
|
|
for (i = 0; i < mddt_cnt; i++) {
|
|
if (be64_to_cpu(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 = cpu_to_be64(src | HRMOR_BIT);
|
|
mdst->data_region = region;
|
|
mdst->size = cpu_to_be32(size);
|
|
ntuple_mdst->act_cnt = cpu_to_be16(mdst_cnt + 1);
|
|
|
|
/* Add OPAL destination address to MDDT entry */
|
|
mddt->addr = cpu_to_be64(dest | HRMOR_BIT);
|
|
mddt->data_region = region;
|
|
mddt->size = cpu_to_be32(size);
|
|
ntuple_mddt->act_cnt = cpu_to_be16(mddt_cnt + 1);
|
|
|
|
prlog(PR_TRACE, "Added new entry. src : 0x%llx, dest : 0x%llx,"
|
|
" size : 0x%llx\n", src, dest, size);
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
/* Remove entry from source (MDST) table */
|
|
static int opal_mpipl_remove_entry_mdst(bool remove_all, u8 region, u64 src)
|
|
{
|
|
bool found = false;
|
|
int i, j;
|
|
int mdst_cnt = be16_to_cpu(ntuple_mdst->act_cnt);
|
|
struct mdst_table *tmp_mdst;
|
|
struct mdst_table *mdst = (void *)(MDST_TABLE_BASE);
|
|
|
|
for (i = 0; i < mdst_cnt;) {
|
|
if (mdst->data_region != region) {
|
|
mdst++;
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
if (remove_all != true &&
|
|
be64_to_cpu(mdst->addr) != (src | HRMOR_BIT)) {
|
|
mdst++;
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
tmp_mdst = mdst;
|
|
memset(tmp_mdst, 0, sizeof(struct mdst_table));
|
|
|
|
for (j = i; j < mdst_cnt - 1; j++) {
|
|
memcpy((void *)tmp_mdst,
|
|
(void *)(tmp_mdst + 1), sizeof(struct mdst_table));
|
|
tmp_mdst++;
|
|
memset(tmp_mdst, 0, sizeof(struct mdst_table));
|
|
}
|
|
|
|
mdst_cnt--;
|
|
|
|
if (remove_all == false) {
|
|
found = true;
|
|
break;
|
|
}
|
|
} /* end - for loop */
|
|
|
|
ntuple_mdst->act_cnt = cpu_to_be16((u16)mdst_cnt);
|
|
|
|
if (remove_all == false && found == false) {
|
|
prlog(PR_DEBUG,
|
|
"Source address [0x%llx] not found in MDST table\n", src);
|
|
return OPAL_PARAMETER;
|
|
}
|
|
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
/* Remove entry from destination (MDDT) table */
|
|
static int opal_mpipl_remove_entry_mddt(bool remove_all, u8 region, u64 dest)
|
|
{
|
|
bool found = false;
|
|
int i, j;
|
|
int mddt_cnt = be16_to_cpu(ntuple_mddt->act_cnt);
|
|
struct mddt_table *tmp_mddt;
|
|
struct mddt_table *mddt = (void *)(MDDT_TABLE_BASE);
|
|
|
|
for (i = 0; i < mddt_cnt;) {
|
|
if (mddt->data_region != region) {
|
|
mddt++;
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
if (remove_all != true &&
|
|
be64_to_cpu(mddt->addr) != (dest | HRMOR_BIT)) {
|
|
mddt++;
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
tmp_mddt = mddt;
|
|
memset(tmp_mddt, 0, sizeof(struct mddt_table));
|
|
|
|
for (j = i; j < mddt_cnt - 1; j++) {
|
|
memcpy((void *)tmp_mddt,
|
|
(void *)(tmp_mddt + 1), sizeof(struct mddt_table));
|
|
tmp_mddt++;
|
|
memset(tmp_mddt, 0, sizeof(struct mddt_table));
|
|
}
|
|
|
|
mddt_cnt--;
|
|
|
|
if (remove_all == false) {
|
|
found = true;
|
|
break;
|
|
}
|
|
} /* end - for loop */
|
|
|
|
ntuple_mddt->act_cnt = cpu_to_be16((u16)mddt_cnt);
|
|
|
|
if (remove_all == false && found == false) {
|
|
prlog(PR_DEBUG,
|
|
"Dest address [0x%llx] not found in MDDT table\n", dest);
|
|
return OPAL_PARAMETER;
|
|
}
|
|
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
/* Register for OPAL dump. */
|
|
static void opal_mpipl_register(void)
|
|
{
|
|
u64 arch_regs_dest, arch_regs_size;
|
|
struct proc_dump_area *proc_dump = (void *)(PROC_DUMP_AREA_BASE);
|
|
|
|
/* Add OPAL reservation detail to MDST/MDDT table */
|
|
opal_mpipl_add_entry(DUMP_REGION_OPAL_MEMORY,
|
|
SKIBOOT_BASE, opal_dump_addr, opal_dump_size);
|
|
|
|
/* Thread size check */
|
|
if (proc_dump->thread_size != 0) {
|
|
prlog(PR_INFO, "Thread register entry size is available, "
|
|
"but not supported.\n");
|
|
}
|
|
|
|
/* Reserve memory used to capture architected register state */
|
|
arch_regs_dest = opal_dump_addr + opal_dump_size;
|
|
arch_regs_size = nr_chips() * ARCH_REGS_DATA_SIZE_PER_CHIP;
|
|
proc_dump->alloc_addr = cpu_to_be64(arch_regs_dest | HRMOR_BIT);
|
|
proc_dump->alloc_size = cpu_to_be32(arch_regs_size);
|
|
prlog(PR_NOTICE, "Architected register dest addr : 0x%llx, "
|
|
"size : 0x%llx\n", arch_regs_dest, arch_regs_size);
|
|
}
|
|
|
|
static int payload_mpipl_register(u64 src, u64 dest, u64 size)
|
|
{
|
|
if (!opal_addr_valid((void *)src)) {
|
|
prlog(PR_DEBUG, "Invalid source address [0x%llx]\n", src);
|
|
return OPAL_PARAMETER;
|
|
}
|
|
|
|
if (!opal_addr_valid((void *)dest)) {
|
|
prlog(PR_DEBUG, "Invalid dest address [0x%llx]\n", dest);
|
|
return OPAL_PARAMETER;
|
|
}
|
|
|
|
if (size <= 0) {
|
|
prlog(PR_DEBUG, "Invalid size [0x%llx]\n", size);
|
|
return OPAL_PARAMETER;
|
|
}
|
|
|
|
return opal_mpipl_add_entry(DUMP_REGION_KERNEL, src, dest, size);
|
|
}
|
|
|
|
static int payload_mpipl_unregister(u64 src, u64 dest)
|
|
{
|
|
int rc;
|
|
|
|
/* Remove src from MDST table */
|
|
rc = opal_mpipl_remove_entry_mdst(false, DUMP_REGION_KERNEL, src);
|
|
if (rc)
|
|
return rc;
|
|
|
|
/* Remove dest from MDDT table */
|
|
rc = opal_mpipl_remove_entry_mddt(false, DUMP_REGION_KERNEL, dest);
|
|
return rc;
|
|
}
|
|
|
|
static int payload_mpipl_unregister_all(void)
|
|
{
|
|
opal_mpipl_remove_entry_mdst(true, DUMP_REGION_KERNEL, 0);
|
|
opal_mpipl_remove_entry_mddt(true, DUMP_REGION_KERNEL, 0);
|
|
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
static int64_t opal_mpipl_update(enum opal_mpipl_ops ops,
|
|
u64 src, u64 dest, u64 size)
|
|
{
|
|
int rc;
|
|
void *skiboot_constant_addr mdrt_table_base_addr = (void *) MDRT_TABLE_BASE;
|
|
|
|
switch (ops) {
|
|
case OPAL_MPIPL_ADD_RANGE:
|
|
rc = payload_mpipl_register(src, dest, size);
|
|
if (!rc)
|
|
prlog(PR_NOTICE, "Payload registered for MPIPL\n");
|
|
break;
|
|
case OPAL_MPIPL_REMOVE_RANGE:
|
|
rc = payload_mpipl_unregister(src, dest);
|
|
if (!rc) {
|
|
prlog(PR_NOTICE, "Payload removed entry from MPIPL."
|
|
"[src : 0x%llx, dest : 0x%llx]\n", src, dest);
|
|
}
|
|
break;
|
|
case OPAL_MPIPL_REMOVE_ALL:
|
|
rc = payload_mpipl_unregister_all();
|
|
if (!rc)
|
|
prlog(PR_NOTICE, "Payload unregistered for MPIPL\n");
|
|
break;
|
|
case OPAL_MPIPL_FREE_PRESERVED_MEMORY:
|
|
/* Clear tags */
|
|
memset(&opal_mpipl_tags, 0, (sizeof(u64) * MAX_OPAL_MPIPL_TAGS));
|
|
opal_mpipl_max_tags = 0;
|
|
/* Release memory */
|
|
free(opal_mpipl_data);
|
|
opal_mpipl_data = NULL;
|
|
free(opal_mpipl_cpu_data);
|
|
opal_mpipl_cpu_data = NULL;
|
|
/* Clear MDRT table */
|
|
memset(mdrt_table_base_addr, 0, MDRT_TABLE_SIZE);
|
|
/* Set MDRT count to max allocated count */
|
|
ntuple_mdrt->act_cnt = cpu_to_be16(MDRT_TABLE_SIZE / sizeof(struct mdrt_table));
|
|
rc = OPAL_SUCCESS;
|
|
prlog(PR_NOTICE, "Payload Invalidated MPIPL\n");
|
|
break;
|
|
default:
|
|
prlog(PR_DEBUG, "Unsupported MPIPL update operation : 0x%x\n", ops);
|
|
rc = OPAL_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int64_t opal_mpipl_register_tag(enum opal_mpipl_tags tag,
|
|
uint64_t tag_val)
|
|
{
|
|
int rc = OPAL_SUCCESS;
|
|
|
|
switch (tag) {
|
|
case OPAL_MPIPL_TAG_BOOT_MEM:
|
|
if (tag_val <= 0 || tag_val > top_of_ram) {
|
|
prlog(PR_DEBUG, "Payload sent invalid boot mem size"
|
|
" : 0x%llx\n", tag_val);
|
|
rc = OPAL_PARAMETER;
|
|
} else {
|
|
mpipl_metadata->boot_mem_size = tag_val;
|
|
prlog(PR_NOTICE, "Boot mem size : 0x%llx\n", tag_val);
|
|
}
|
|
break;
|
|
case OPAL_MPIPL_TAG_KERNEL:
|
|
mpipl_metadata->kernel_tag = tag_val;
|
|
prlog(PR_NOTICE, "Payload sent metadata tag : 0x%llx\n", tag_val);
|
|
break;
|
|
default:
|
|
prlog(PR_DEBUG, "Payload sent unsupported tag : 0x%x\n", tag);
|
|
rc = OPAL_PARAMETER;
|
|
break;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
static uint64_t opal_mpipl_query_tag(enum opal_mpipl_tags tag, __be64 *tag_val)
|
|
{
|
|
if (!opal_addr_valid(tag_val)) {
|
|
prlog(PR_DEBUG, "Invalid tag address\n");
|
|
return OPAL_PARAMETER;
|
|
}
|
|
|
|
if (tag >= opal_mpipl_max_tags)
|
|
return OPAL_PARAMETER;
|
|
|
|
*tag_val = cpu_to_be64(opal_mpipl_tags[tag]);
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
static inline void post_mpipl_get_preserved_tags(void)
|
|
{
|
|
if (mpipl_metadata->kernel_tag)
|
|
opal_mpipl_tags[OPAL_MPIPL_TAG_KERNEL] = mpipl_metadata->kernel_tag;
|
|
if (mpipl_metadata->boot_mem_size)
|
|
opal_mpipl_tags[OPAL_MPIPL_TAG_BOOT_MEM] = mpipl_metadata->boot_mem_size;
|
|
}
|
|
|
|
static void post_mpipl_arch_regs_data(void)
|
|
{
|
|
struct proc_dump_area *proc_dump = (void *)(PROC_DUMP_AREA_BASE);
|
|
|
|
if (proc_dump->dest_addr == 0) {
|
|
prlog(PR_DEBUG, "Invalid CPU registers destination address\n");
|
|
return;
|
|
}
|
|
|
|
if (proc_dump->act_size == 0) {
|
|
prlog(PR_DEBUG, "Invalid CPU registers destination size\n");
|
|
return;
|
|
}
|
|
|
|
opal_mpipl_cpu_data = zalloc(sizeof(struct opal_mpipl_fadump) +
|
|
sizeof(struct opal_mpipl_region));
|
|
if (!opal_mpipl_cpu_data) {
|
|
prlog(PR_ERR, "Failed to allocate memory\n");
|
|
return;
|
|
}
|
|
|
|
/* Fill CPU register details */
|
|
opal_mpipl_cpu_data->version = OPAL_MPIPL_VERSION;
|
|
opal_mpipl_cpu_data->cpu_data_version = cpu_to_be32((u32)proc_dump->version);
|
|
opal_mpipl_cpu_data->cpu_data_size = proc_dump->thread_size;
|
|
opal_mpipl_cpu_data->region_cnt = cpu_to_be32(1);
|
|
|
|
opal_mpipl_cpu_data->region[0].src = proc_dump->dest_addr & ~(cpu_to_be64(HRMOR_BIT));
|
|
opal_mpipl_cpu_data->region[0].dest = proc_dump->dest_addr & ~(cpu_to_be64(HRMOR_BIT));
|
|
opal_mpipl_cpu_data->region[0].size = cpu_to_be64(be32_to_cpu(proc_dump->act_size));
|
|
|
|
/* Update tag */
|
|
opal_mpipl_tags[OPAL_MPIPL_TAG_CPU] = (u64)opal_mpipl_cpu_data;
|
|
}
|
|
|
|
static void post_mpipl_get_opal_data(void)
|
|
{
|
|
struct mdrt_table *mdrt = (void *)(MDRT_TABLE_BASE);
|
|
int i, j = 0, count = 0;
|
|
int mdrt_cnt = be16_to_cpu(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 = cpu_to_be32(mpipl_metadata->crashing_pir);
|
|
opal_mpipl_data->region_cnt = cpu_to_be32(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 & ~(cpu_to_be64(HRMOR_BIT));
|
|
region[j].dest = mdrt->dest_addr & ~(cpu_to_be64(HRMOR_BIT));
|
|
region[j].size = cpu_to_be64(be32_to_cpu(mdrt->size));
|
|
|
|
prlog(PR_NOTICE, "OPAL reserved region %d - src : 0x%llx, "
|
|
"dest : 0x%llx, size : 0x%llx\n", j,
|
|
be64_to_cpu(region[j].src), be64_to_cpu(region[j].dest),
|
|
be64_to_cpu(region[j].size));
|
|
|
|
mdrt++;
|
|
j++;
|
|
if (j == count)
|
|
break;
|
|
}
|
|
|
|
opal_mpipl_tags[OPAL_MPIPL_TAG_OPAL] = (u64)opal_mpipl_data;
|
|
}
|
|
|
|
void opal_mpipl_save_crashing_pir(void)
|
|
{
|
|
if (!is_mpipl_enabled())
|
|
return;
|
|
|
|
mpipl_metadata->crashing_pir = this_cpu()->pir;
|
|
prlog(PR_NOTICE, "Crashing PIR = 0x%x\n", this_cpu()->pir);
|
|
}
|
|
|
|
void opal_mpipl_reserve_mem(void)
|
|
{
|
|
struct dt_node *opal_node, *dump_node;
|
|
u64 arch_regs_dest, arch_regs_size;
|
|
|
|
opal_node = dt_find_by_path(dt_root, "ibm,opal");
|
|
if (!opal_node)
|
|
return;
|
|
|
|
dump_node = dt_find_by_path(opal_node, "dump");
|
|
if (!dump_node)
|
|
return;
|
|
|
|
/* Calculcate and Reserve OPAL dump destination memory */
|
|
opal_dump_size = SKIBOOT_SIZE + (cpu_max_pir + 1) * STACK_SIZE;
|
|
opal_dump_addr = SKIBOOT_BASE + opal_dump_size;
|
|
mem_reserve_fw("ibm,firmware-dump",
|
|
opal_dump_addr, opal_dump_size);
|
|
|
|
/* Reserve memory to capture CPU register data */
|
|
arch_regs_dest = opal_dump_addr + opal_dump_size;
|
|
arch_regs_size = nr_chips() * ARCH_REGS_DATA_SIZE_PER_CHIP;
|
|
mem_reserve_fw("ibm,firmware-arch-registers",
|
|
arch_regs_dest, arch_regs_size);
|
|
}
|
|
|
|
bool is_mpipl_enabled(void)
|
|
{
|
|
return mpipl_enabled;
|
|
}
|
|
|
|
void opal_mpipl_init(void)
|
|
{
|
|
void *skiboot_constant_addr mdst_base = (void *)MDST_TABLE_BASE;
|
|
void *skiboot_constant_addr 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);
|
|
|
|
/* Get metadata area pointer */
|
|
mpipl_metadata = (void *)(DUMP_METADATA_AREA_BASE);
|
|
|
|
if (dt_find_property(dump_node, "mpipl-boot")) {
|
|
disable_fast_reboot("MPIPL Boot");
|
|
|
|
post_mpipl_get_preserved_tags();
|
|
post_mpipl_get_opal_data();
|
|
post_mpipl_arch_regs_data();
|
|
}
|
|
|
|
/* Clear OPAL metadata area */
|
|
if (sizeof(struct mpipl_metadata) > DUMP_METADATA_AREA_SIZE) {
|
|
prlog(PR_ERR, "INSUFFICIENT OPAL METADATA AREA\n");
|
|
prlog(PR_ERR, "INCREASE OPAL MEDTADATA AREA SIZE\n");
|
|
assert(false);
|
|
}
|
|
memset(mpipl_metadata, 0, sizeof(struct mpipl_metadata));
|
|
|
|
/* 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();
|
|
|
|
/* Send OPAL relocated base address to SBE */
|
|
p9_sbe_send_relocated_base(SKIBOOT_BASE);
|
|
|
|
/* OPAL API for MPIPL update */
|
|
opal_register(OPAL_MPIPL_UPDATE, opal_mpipl_update, 4);
|
|
opal_register(OPAL_MPIPL_REGISTER_TAG, opal_mpipl_register_tag, 2);
|
|
opal_register(OPAL_MPIPL_QUERY_TAG, opal_mpipl_query_tag, 2);
|
|
|
|
/* Enable MPIPL */
|
|
mpipl_enabled = true;
|
|
}
|