From af98c56312b4521985f40223209d64e7715bb49a Mon Sep 17 00:00:00 2001 From: Vasant Hegde Date: Fri, 12 Jul 2019 16:47:39 +0530 Subject: FSP/MDST: Rename fsp-mdst-table.c -> fsp-sysdump.c MDST is a ntuple inside SPIRAH. Its just a interface to pass memory ranges to be captured as part of dump to FSP/Hostboot. Today OPAL is using MDST ntuple to pass list of memory region (mostly OPAL console and host dmesg) to be collected as part of SYSDUMP. Soon we are going to support OPAL MPIPL feature (aka Memory Preserving IPL). Even MPIPL uses MDST/MDDT table. Hence rename files based on feature instead of some table name: - fsp-mdst-table.c -> fsp-sysdump.c - fsp-mdst-table.h -> opal-dump.h (This will cater both SYSDUMP and MPIPL) - Rename structure -> dump_mdst_table -> mdst_table This patch does renaming and header file adjustment. No functionality changes. Signed-off-by: Vasant Hegde [oliver: rebased] Signed-off-by: Oliver O'Halloran --- hdata/spira.c | 6 +- hw/fsp/Makefile.inc | 2 +- hw/fsp/fsp-mdst-table.c | 426 ----------------------------------------------- hw/fsp/fsp-sysdump.c | 426 +++++++++++++++++++++++++++++++++++++++++++++++ include/fsp-mdst-table.h | 34 ---- include/opal-dump.h | 34 ++++ 6 files changed, 464 insertions(+), 464 deletions(-) delete mode 100644 hw/fsp/fsp-mdst-table.c create mode 100644 hw/fsp/fsp-sysdump.c delete mode 100644 include/fsp-mdst-table.h create mode 100644 include/opal-dump.h diff --git a/hdata/spira.c b/hdata/spira.c index f6003ea..1bcbb6c 100644 --- a/hdata/spira.c +++ b/hdata/spira.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include @@ -81,9 +81,9 @@ __section(".cpuctrl.data") struct cpu_ctl_init_data cpu_ctl_init_data = { * addresses, we set the top bit to 1 on physical addresses */ -extern struct dump_mdst_table init_mdst_table[]; +extern struct mdst_table init_mdst_table[]; -__section(".mdst.data") struct dump_mdst_table init_mdst_table[2] = { +__section(".mdst.data") struct mdst_table init_mdst_table[2] = { { .addr = CPU_TO_BE64(INMEM_CON_START | HRMOR_BIT), .type = CPU_TO_BE32(DUMP_REGION_CONSOLE), diff --git a/hw/fsp/Makefile.inc b/hw/fsp/Makefile.inc index b078a4d..21dc52a 100644 --- a/hw/fsp/Makefile.inc +++ b/hw/fsp/Makefile.inc @@ -4,7 +4,7 @@ FSP_OBJS = fsp.o fsp-console.o fsp-rtc.o fsp-nvram.o fsp-sysparam.o FSP_OBJS += fsp-surveillance.o fsp-codeupdate.o fsp-sensor.o FSP_OBJS += fsp-diag.o fsp-leds.o fsp-mem-err.o fsp-op-panel.o FSP_OBJS += fsp-elog-read.o fsp-elog-write.o fsp-epow.o fsp-dpo.o -FSP_OBJS += fsp-dump.o fsp-mdst-table.o fsp-chiptod.o fsp-ipmi.o +FSP_OBJS += fsp-dump.o fsp-sysdump.o fsp-chiptod.o fsp-ipmi.o FSP_OBJS += fsp-attn.o fsp-occ.o fsp-psi.o FSP = hw/fsp/built-in.a diff --git a/hw/fsp/fsp-mdst-table.c b/hw/fsp/fsp-mdst-table.c deleted file mode 100644 index 98f667f..0000000 --- a/hw/fsp/fsp-mdst-table.c +++ /dev/null @@ -1,426 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -/* - * Sapphire dump design: - * - During initialization we setup Memory Dump Source Table (MDST) table - * which contains address, size pair. - * - We send MDST table update notification to FSP via MBOX command. - * - During Sapphire checkstop: - * - FSP retrieves HWDUMP. - * - FSP retrieves CEC memory based on MDST table. - * - Once Sapphire reboot FSP sends new dump avialable notification via HDAT - * - * Copyright 2013-2016 IBM Corp. - */ - -#include -#include -#include -#include -#include -#include -#include - -/* - * Sapphire dump size - * This is the maximum memory that FSP can retrieve during checkstop. - * - * Note: - * Presently we are hardcoding this parameter. Eventually we need - * new System parameter so that we can get max size dynamically. - */ -#define MAX_SAPPHIRE_DUMP_SIZE 0x1000000 - -DEFINE_LOG_ENTRY(OPAL_RC_DUMP_MDST_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_DUMP, - OPAL_PLATFORM_FIRMWARE, OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT, - OPAL_NA); - -DEFINE_LOG_ENTRY(OPAL_RC_DUMP_MDST_UPDATE, OPAL_PLATFORM_ERR_EVT, OPAL_DUMP, - OPAL_PLATFORM_FIRMWARE, - OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT, - OPAL_NA); - -DEFINE_LOG_ENTRY(OPAL_RC_DUMP_MDST_ADD, OPAL_PLATFORM_ERR_EVT, OPAL_DUMP, - OPAL_PLATFORM_FIRMWARE, OPAL_INFO, OPAL_NA); - -DEFINE_LOG_ENTRY(OPAL_RC_DUMP_MDST_REMOVE, OPAL_PLATFORM_ERR_EVT, OPAL_DUMP, - OPAL_PLATFORM_FIRMWARE, OPAL_INFO, OPAL_NA); - - -static struct dump_mdst_table *mdst_table; -static struct dump_mdst_table *dump_mem_region; - -static int cur_mdst_entry; -static int max_mdst_entry; -static int cur_dump_size; -/* - * Presently both sizes are same.. But if someday FSP gives more space - * than our TCE mapping then we need this validation.. - * - * Also once FSP implements MAX_SAPPHIRE_DUMP_SIZE system param, we can - * move this validation to separate function. - */ -static int max_dump_size = MIN(MAX_SAPPHIRE_DUMP_SIZE, PSI_DMA_HYP_DUMP_SIZE); - -/* Protect MDST table entries */ -static struct lock mdst_lock = LOCK_UNLOCKED; - -/* Not supported on P7 */ -static inline bool fsp_mdst_supported(void) -{ - return proc_gen >= proc_gen_p8; -} - -static inline uint32_t get_dump_region_map_size(uint64_t addr, uint32_t size) -{ - uint64_t start, end; - - start = addr & ~TCE_MASK; - end = addr + size; - end = ALIGN_UP(end, TCE_PSIZE); - - return (end - start); -} - -static int dump_region_tce_map(void) -{ - int i; - uint32_t t_size = 0, size; - uint64_t addr; - - for (i = 0; i < cur_mdst_entry; i++) { - - addr = be64_to_cpu(dump_mem_region[i].addr) & ~TCE_MASK; - size = get_dump_region_map_size(be64_to_cpu(dump_mem_region[i].addr), - be32_to_cpu(dump_mem_region[i].size)); - - if (t_size + size > max_dump_size) - break; - - /* TCE mapping */ - fsp_tce_map(PSI_DMA_HYP_DUMP + t_size, (void *)addr, size); - - /* Add entry to MDST table */ - mdst_table[i].type = dump_mem_region[i].type; - mdst_table[i].size = dump_mem_region[i].size; - mdst_table[i].addr = cpu_to_be64(PSI_DMA_HYP_DUMP + t_size); - - /* TCE alignment adjustment */ - mdst_table[i].addr = cpu_to_be64(be64_to_cpu(mdst_table[i].addr) + - (be64_to_cpu(dump_mem_region[i].addr) & 0xfff)); - - t_size += size; - } - - return i; -} - -static inline void dump_region_tce_unmap(void) -{ - fsp_tce_unmap(PSI_DMA_HYP_DUMP, PSI_DMA_HYP_DUMP_SIZE); -} - -static void update_mdst_table_complete(struct fsp_msg *msg) -{ - uint8_t status = (msg->resp->word1 >> 8) & 0xff; - - if (status) - log_simple_error(&e_info(OPAL_RC_DUMP_MDST_UPDATE), - "MDST: Update table MBOX command failed: " - "0x%x\n", status); - else - printf("MDST: Table updated.\n"); - - fsp_freemsg(msg); -} - -/* Send MDST table to FSP */ -static int64_t fsp_update_mdst_table(void) -{ - struct fsp_msg *msg; - int count; - int rc = OPAL_SUCCESS; - - if (cur_mdst_entry <= 0) { - printf("MDST: Table is empty\n"); - return OPAL_INTERNAL_ERROR; - } - - lock(&mdst_lock); - - /* Unmap previous mapping */ - dump_region_tce_unmap(); - count = dump_region_tce_map(); - - msg = fsp_mkmsg(FSP_CMD_HYP_MDST_TABLE, 4, 0, - PSI_DMA_MDST_TABLE, - sizeof(*mdst_table) * count, - sizeof(*mdst_table)); - unlock(&mdst_lock); - - if (!msg) { - log_simple_error(&e_info(OPAL_RC_DUMP_MDST_UPDATE), - "MDST: Message allocation failed.!\n"); - rc = OPAL_INTERNAL_ERROR; - } else if (fsp_queue_msg(msg, update_mdst_table_complete)) { - log_simple_error(&e_info(OPAL_RC_DUMP_MDST_UPDATE), - "MDST: Failed to queue MDST table message.\n"); - fsp_freemsg(msg); - rc = OPAL_INTERNAL_ERROR; - } - return rc; -} - -static int dump_region_del_entry(uint32_t id) -{ - int i; - uint32_t size; - bool found = false; - int rc = OPAL_SUCCESS; - - lock(&mdst_lock); - - for (i = 0; i < cur_mdst_entry; i++) { - if (be32_to_cpu(dump_mem_region[i].type) != id) - continue; - - found = true; - break; - } - - if (!found) { - rc = OPAL_PARAMETER; - goto del_out; - } - - /* Adjust current dump size */ - size = get_dump_region_map_size(be64_to_cpu(dump_mem_region[i].addr), - be32_to_cpu(dump_mem_region[i].size)); - cur_dump_size -= size; - - for ( ; i < cur_mdst_entry - 1; i++) - dump_mem_region[i] = dump_mem_region[i + 1]; - - dump_mem_region[i].type = 0; - cur_mdst_entry--; - -del_out: - unlock(&mdst_lock); - return rc; -} - -/* Add entry to MDST table */ -static int __dump_region_add_entry(uint32_t id, uint64_t addr, uint32_t size) -{ - int rc = OPAL_INTERNAL_ERROR; - uint32_t act_size; - - /* Delete function takes lock before modifying table */ - dump_region_del_entry(id); - - lock(&mdst_lock); - - if (cur_mdst_entry >= max_mdst_entry) { - log_simple_error(&e_info(OPAL_RC_DUMP_MDST_ADD), - "MDST: Table is full.\n"); - goto out; - } - - /* TCE alignment adjustment */ - act_size = get_dump_region_map_size(addr, size); - - /* Make sure we don't cross dump size limit */ - if (cur_dump_size + act_size > max_dump_size) { - log_simple_error(&e_info(OPAL_RC_DUMP_MDST_ADD), - "MDST: 0x%x is crossing max dump size (0x%x) limit.\n", - cur_dump_size + act_size, max_dump_size); - goto out; - } - - /* Add entry to dump memory region table */ - dump_mem_region[cur_mdst_entry].type = cpu_to_be32(id); - dump_mem_region[cur_mdst_entry].addr = cpu_to_be64(addr); - dump_mem_region[cur_mdst_entry].size = cpu_to_be32(size); - - /* Update dump region count and dump size */ - cur_mdst_entry++; - cur_dump_size += act_size; - - printf("MDST: Addr = 0x%llx [size : 0x%x bytes] added to MDST table.\n", - (uint64_t)addr, size); - - rc = OPAL_SUCCESS; - -out: - unlock(&mdst_lock); - return rc; -} - -static int dump_region_add_entries(void) -{ - int rc; - - /* Add console buffer */ - rc = __dump_region_add_entry(DUMP_REGION_CONSOLE, - INMEM_CON_START, INMEM_CON_LEN); - if (rc) - return rc; - - /* Add HBRT buffer */ - rc = __dump_region_add_entry(DUMP_REGION_HBRT_LOG, - HBRT_CON_START, HBRT_CON_LEN); - - return rc; -} - -static int64_t fsp_opal_register_dump_region(uint32_t id, - uint64_t addr, uint64_t size) -{ - int rc = OPAL_SUCCESS; - - if (!fsp_present()) - return OPAL_UNSUPPORTED; - - if (!fsp_mdst_supported()) { - printf("MDST: Not supported\n"); - return OPAL_UNSUPPORTED; - } - - /* Validate memory region id */ - if (id < DUMP_REGION_HOST_START || id > DUMP_REGION_HOST_END) { - log_simple_error(&e_info(OPAL_RC_DUMP_MDST_ADD), - "MDST: Invalid dump region id : 0x%x\n", id); - return OPAL_PARAMETER; - } - - if (size <= 0) { - log_simple_error(&e_info(OPAL_RC_DUMP_MDST_ADD), - "MDST: Invalid size : 0x%llx\n", size); - return OPAL_PARAMETER; - } - - rc = __dump_region_add_entry(id, addr, size); - if (rc) - return rc; - - /* Send updated MDST to FSP */ - rc = fsp_update_mdst_table(); - - return rc; -} - -static int64_t fsp_opal_unregister_dump_region(uint32_t id) -{ - int rc = OPAL_SUCCESS; - - if (!fsp_present()) - return OPAL_UNSUPPORTED; - - if (!fsp_mdst_supported()) { - printf("MDST: Not supported\n"); - return OPAL_UNSUPPORTED; - } - - /* Validate memory region id */ - if (id < DUMP_REGION_HOST_START || id > DUMP_REGION_HOST_END) { - log_simple_error(&e_info(OPAL_RC_DUMP_MDST_REMOVE), - "MDST: Invalid dump region id : 0x%x\n", id); - return OPAL_PARAMETER; - } - - rc = dump_region_del_entry(id); - if (rc) { - log_simple_error(&e_info(OPAL_RC_DUMP_MDST_REMOVE), - "MDST: dump region id : 0x%x not found\n", id); - return OPAL_PARAMETER; - } - - /* Send updated MDST to FSP */ - rc = fsp_update_mdst_table(); - - return rc; -} - -/* TCE mapping */ -static inline void mdst_table_tce_map(void) -{ - fsp_tce_map(PSI_DMA_MDST_TABLE, mdst_table, PSI_DMA_MDST_TABLE_SIZE); -} - -/* Initialize MDST table */ -static int mdst_table_init(void) -{ - dump_mem_region = memalign(TCE_PSIZE, PSI_DMA_MDST_TABLE_SIZE); - if (!dump_mem_region) { - log_simple_error(&e_info(OPAL_RC_DUMP_MDST_INIT), - "MDST: Failed to allocate memory for dump " - "memory region table.\n"); - return -ENOMEM; - } - - memset(dump_mem_region, 0, PSI_DMA_MDST_TABLE_SIZE); - - mdst_table = memalign(TCE_PSIZE, PSI_DMA_MDST_TABLE_SIZE); - if (!mdst_table) { - log_simple_error(&e_info(OPAL_RC_DUMP_MDST_INIT), - "MDST: Failed to allocate memory for MDST table.\n"); - return -ENOMEM; - } - - memset(mdst_table, 0, PSI_DMA_MDST_TABLE_SIZE); - mdst_table_tce_map(); - - max_mdst_entry = PSI_DMA_MDST_TABLE_SIZE / sizeof(*mdst_table); - printf("MDST: Max entries in MDST table : %d\n", max_mdst_entry); - - return OPAL_SUCCESS; -} - -/* - * Handle FSP R/R event. - */ -static bool fsp_mdst_update_rr(uint32_t cmd_sub_mod, - struct fsp_msg *msg __unused) -{ - switch (cmd_sub_mod) { - case FSP_RESET_START: - return true; - case FSP_RELOAD_COMPLETE: /* Send MDST to FSP */ - fsp_update_mdst_table(); - return true; - } - return false; -} - -static struct fsp_client fsp_mdst_client_rr = { - .message = fsp_mdst_update_rr, -}; - -/* Initialize MDST table and send notification to FSP */ -void fsp_mdst_table_init(void) -{ - if (!fsp_present()) - return; - - /* OPAL interface */ - opal_register(OPAL_REGISTER_DUMP_REGION, - fsp_opal_register_dump_region, 3); - opal_register(OPAL_UNREGISTER_DUMP_REGION, - fsp_opal_unregister_dump_region, 1); - - if (!fsp_mdst_supported()) - return; - - /* Initiate MDST */ - if (mdst_table_init() != OPAL_SUCCESS) - return; - - /* - * Ignore return code from mdst_table_add_entries so that - * we can atleast capture partial dump. - */ - dump_region_add_entries(); - fsp_update_mdst_table(); - - /* Register for Class AA (FSP R/R) */ - fsp_register_client(&fsp_mdst_client_rr, FSP_MCLASS_RR_EVENT); -} diff --git a/hw/fsp/fsp-sysdump.c b/hw/fsp/fsp-sysdump.c new file mode 100644 index 0000000..869e059 --- /dev/null +++ b/hw/fsp/fsp-sysdump.c @@ -0,0 +1,426 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Sapphire dump design: + * - During initialization we setup Memory Dump Source Table (MDST) table + * which contains address, size pair. + * - We send MDST table update notification to FSP via MBOX command. + * - During Sapphire checkstop: + * - FSP retrieves HWDUMP. + * - FSP retrieves CEC memory based on MDST table. + * - Once Sapphire reboot FSP sends new dump avialable notification via HDAT + * + * Copyright 2013-2016 IBM Corp. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Sapphire dump size + * This is the maximum memory that FSP can retrieve during checkstop. + * + * Note: + * Presently we are hardcoding this parameter. Eventually we need + * new System parameter so that we can get max size dynamically. + */ +#define MAX_SAPPHIRE_DUMP_SIZE 0x1000000 + +DEFINE_LOG_ENTRY(OPAL_RC_DUMP_MDST_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_DUMP, + OPAL_PLATFORM_FIRMWARE, OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT, + OPAL_NA); + +DEFINE_LOG_ENTRY(OPAL_RC_DUMP_MDST_UPDATE, OPAL_PLATFORM_ERR_EVT, OPAL_DUMP, + OPAL_PLATFORM_FIRMWARE, + OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT, + OPAL_NA); + +DEFINE_LOG_ENTRY(OPAL_RC_DUMP_MDST_ADD, OPAL_PLATFORM_ERR_EVT, OPAL_DUMP, + OPAL_PLATFORM_FIRMWARE, OPAL_INFO, OPAL_NA); + +DEFINE_LOG_ENTRY(OPAL_RC_DUMP_MDST_REMOVE, OPAL_PLATFORM_ERR_EVT, OPAL_DUMP, + OPAL_PLATFORM_FIRMWARE, OPAL_INFO, OPAL_NA); + + +static struct mdst_table *mdst_table; +static struct mdst_table *dump_mem_region; + +static int cur_mdst_entry; +static int max_mdst_entry; +static int cur_dump_size; +/* + * Presently both sizes are same.. But if someday FSP gives more space + * than our TCE mapping then we need this validation.. + * + * Also once FSP implements MAX_SAPPHIRE_DUMP_SIZE system param, we can + * move this validation to separate function. + */ +static int max_dump_size = MIN(MAX_SAPPHIRE_DUMP_SIZE, PSI_DMA_HYP_DUMP_SIZE); + +/* Protect MDST table entries */ +static struct lock mdst_lock = LOCK_UNLOCKED; + +/* Not supported on P7 */ +static inline bool fsp_mdst_supported(void) +{ + return proc_gen >= proc_gen_p8; +} + +static inline uint32_t get_dump_region_map_size(uint64_t addr, uint32_t size) +{ + uint64_t start, end; + + start = addr & ~TCE_MASK; + end = addr + size; + end = ALIGN_UP(end, TCE_PSIZE); + + return (end - start); +} + +static int dump_region_tce_map(void) +{ + int i; + uint32_t t_size = 0, size; + uint64_t addr; + + for (i = 0; i < cur_mdst_entry; i++) { + + addr = be64_to_cpu(dump_mem_region[i].addr) & ~TCE_MASK; + size = get_dump_region_map_size(be64_to_cpu(dump_mem_region[i].addr), + be32_to_cpu(dump_mem_region[i].size)); + + if (t_size + size > max_dump_size) + break; + + /* TCE mapping */ + fsp_tce_map(PSI_DMA_HYP_DUMP + t_size, (void *)addr, size); + + /* Add entry to MDST table */ + mdst_table[i].type = dump_mem_region[i].type; + mdst_table[i].size = dump_mem_region[i].size; + mdst_table[i].addr = cpu_to_be64(PSI_DMA_HYP_DUMP + t_size); + + /* TCE alignment adjustment */ + mdst_table[i].addr = cpu_to_be64(be64_to_cpu(mdst_table[i].addr) + + (be64_to_cpu(dump_mem_region[i].addr) & 0xfff)); + + t_size += size; + } + + return i; +} + +static inline void dump_region_tce_unmap(void) +{ + fsp_tce_unmap(PSI_DMA_HYP_DUMP, PSI_DMA_HYP_DUMP_SIZE); +} + +static void update_mdst_table_complete(struct fsp_msg *msg) +{ + uint8_t status = (msg->resp->word1 >> 8) & 0xff; + + if (status) + log_simple_error(&e_info(OPAL_RC_DUMP_MDST_UPDATE), + "MDST: Update table MBOX command failed: " + "0x%x\n", status); + else + printf("MDST: Table updated.\n"); + + fsp_freemsg(msg); +} + +/* Send MDST table to FSP */ +static int64_t fsp_update_mdst_table(void) +{ + struct fsp_msg *msg; + int count; + int rc = OPAL_SUCCESS; + + if (cur_mdst_entry <= 0) { + printf("MDST: Table is empty\n"); + return OPAL_INTERNAL_ERROR; + } + + lock(&mdst_lock); + + /* Unmap previous mapping */ + dump_region_tce_unmap(); + count = dump_region_tce_map(); + + msg = fsp_mkmsg(FSP_CMD_HYP_MDST_TABLE, 4, 0, + PSI_DMA_MDST_TABLE, + sizeof(*mdst_table) * count, + sizeof(*mdst_table)); + unlock(&mdst_lock); + + if (!msg) { + log_simple_error(&e_info(OPAL_RC_DUMP_MDST_UPDATE), + "MDST: Message allocation failed.!\n"); + rc = OPAL_INTERNAL_ERROR; + } else if (fsp_queue_msg(msg, update_mdst_table_complete)) { + log_simple_error(&e_info(OPAL_RC_DUMP_MDST_UPDATE), + "MDST: Failed to queue MDST table message.\n"); + fsp_freemsg(msg); + rc = OPAL_INTERNAL_ERROR; + } + return rc; +} + +static int dump_region_del_entry(uint32_t id) +{ + int i; + uint32_t size; + bool found = false; + int rc = OPAL_SUCCESS; + + lock(&mdst_lock); + + for (i = 0; i < cur_mdst_entry; i++) { + if (be32_to_cpu(dump_mem_region[i].type) != id) + continue; + + found = true; + break; + } + + if (!found) { + rc = OPAL_PARAMETER; + goto del_out; + } + + /* Adjust current dump size */ + size = get_dump_region_map_size(be64_to_cpu(dump_mem_region[i].addr), + be32_to_cpu(dump_mem_region[i].size)); + cur_dump_size -= size; + + for ( ; i < cur_mdst_entry - 1; i++) + dump_mem_region[i] = dump_mem_region[i + 1]; + + dump_mem_region[i].type = 0; + cur_mdst_entry--; + +del_out: + unlock(&mdst_lock); + return rc; +} + +/* Add entry to MDST table */ +static int __dump_region_add_entry(uint32_t id, uint64_t addr, uint32_t size) +{ + int rc = OPAL_INTERNAL_ERROR; + uint32_t act_size; + + /* Delete function takes lock before modifying table */ + dump_region_del_entry(id); + + lock(&mdst_lock); + + if (cur_mdst_entry >= max_mdst_entry) { + log_simple_error(&e_info(OPAL_RC_DUMP_MDST_ADD), + "MDST: Table is full.\n"); + goto out; + } + + /* TCE alignment adjustment */ + act_size = get_dump_region_map_size(addr, size); + + /* Make sure we don't cross dump size limit */ + if (cur_dump_size + act_size > max_dump_size) { + log_simple_error(&e_info(OPAL_RC_DUMP_MDST_ADD), + "MDST: 0x%x is crossing max dump size (0x%x) limit.\n", + cur_dump_size + act_size, max_dump_size); + goto out; + } + + /* Add entry to dump memory region table */ + dump_mem_region[cur_mdst_entry].type = cpu_to_be32(id); + dump_mem_region[cur_mdst_entry].addr = cpu_to_be64(addr); + dump_mem_region[cur_mdst_entry].size = cpu_to_be32(size); + + /* Update dump region count and dump size */ + cur_mdst_entry++; + cur_dump_size += act_size; + + printf("MDST: Addr = 0x%llx [size : 0x%x bytes] added to MDST table.\n", + (uint64_t)addr, size); + + rc = OPAL_SUCCESS; + +out: + unlock(&mdst_lock); + return rc; +} + +static int dump_region_add_entries(void) +{ + int rc; + + /* Add console buffer */ + rc = __dump_region_add_entry(DUMP_REGION_CONSOLE, + INMEM_CON_START, INMEM_CON_LEN); + if (rc) + return rc; + + /* Add HBRT buffer */ + rc = __dump_region_add_entry(DUMP_REGION_HBRT_LOG, + HBRT_CON_START, HBRT_CON_LEN); + + return rc; +} + +static int64_t fsp_opal_register_dump_region(uint32_t id, + uint64_t addr, uint64_t size) +{ + int rc = OPAL_SUCCESS; + + if (!fsp_present()) + return OPAL_UNSUPPORTED; + + if (!fsp_mdst_supported()) { + printf("MDST: Not supported\n"); + return OPAL_UNSUPPORTED; + } + + /* Validate memory region id */ + if (id < DUMP_REGION_HOST_START || id > DUMP_REGION_HOST_END) { + log_simple_error(&e_info(OPAL_RC_DUMP_MDST_ADD), + "MDST: Invalid dump region id : 0x%x\n", id); + return OPAL_PARAMETER; + } + + if (size <= 0) { + log_simple_error(&e_info(OPAL_RC_DUMP_MDST_ADD), + "MDST: Invalid size : 0x%llx\n", size); + return OPAL_PARAMETER; + } + + rc = __dump_region_add_entry(id, addr, size); + if (rc) + return rc; + + /* Send updated MDST to FSP */ + rc = fsp_update_mdst_table(); + + return rc; +} + +static int64_t fsp_opal_unregister_dump_region(uint32_t id) +{ + int rc = OPAL_SUCCESS; + + if (!fsp_present()) + return OPAL_UNSUPPORTED; + + if (!fsp_mdst_supported()) { + printf("MDST: Not supported\n"); + return OPAL_UNSUPPORTED; + } + + /* Validate memory region id */ + if (id < DUMP_REGION_HOST_START || id > DUMP_REGION_HOST_END) { + log_simple_error(&e_info(OPAL_RC_DUMP_MDST_REMOVE), + "MDST: Invalid dump region id : 0x%x\n", id); + return OPAL_PARAMETER; + } + + rc = dump_region_del_entry(id); + if (rc) { + log_simple_error(&e_info(OPAL_RC_DUMP_MDST_REMOVE), + "MDST: dump region id : 0x%x not found\n", id); + return OPAL_PARAMETER; + } + + /* Send updated MDST to FSP */ + rc = fsp_update_mdst_table(); + + return rc; +} + +/* TCE mapping */ +static inline void mdst_table_tce_map(void) +{ + fsp_tce_map(PSI_DMA_MDST_TABLE, mdst_table, PSI_DMA_MDST_TABLE_SIZE); +} + +/* Initialize MDST table */ +static int mdst_table_init(void) +{ + dump_mem_region = memalign(TCE_PSIZE, PSI_DMA_MDST_TABLE_SIZE); + if (!dump_mem_region) { + log_simple_error(&e_info(OPAL_RC_DUMP_MDST_INIT), + "MDST: Failed to allocate memory for dump " + "memory region table.\n"); + return -ENOMEM; + } + + memset(dump_mem_region, 0, PSI_DMA_MDST_TABLE_SIZE); + + mdst_table = memalign(TCE_PSIZE, PSI_DMA_MDST_TABLE_SIZE); + if (!mdst_table) { + log_simple_error(&e_info(OPAL_RC_DUMP_MDST_INIT), + "MDST: Failed to allocate memory for MDST table.\n"); + return -ENOMEM; + } + + memset(mdst_table, 0, PSI_DMA_MDST_TABLE_SIZE); + mdst_table_tce_map(); + + max_mdst_entry = PSI_DMA_MDST_TABLE_SIZE / sizeof(*mdst_table); + printf("MDST: Max entries in MDST table : %d\n", max_mdst_entry); + + return OPAL_SUCCESS; +} + +/* + * Handle FSP R/R event. + */ +static bool fsp_mdst_update_rr(uint32_t cmd_sub_mod, + struct fsp_msg *msg __unused) +{ + switch (cmd_sub_mod) { + case FSP_RESET_START: + return true; + case FSP_RELOAD_COMPLETE: /* Send MDST to FSP */ + fsp_update_mdst_table(); + return true; + } + return false; +} + +static struct fsp_client fsp_mdst_client_rr = { + .message = fsp_mdst_update_rr, +}; + +/* Initialize MDST table and send notification to FSP */ +void fsp_mdst_table_init(void) +{ + if (!fsp_present()) + return; + + /* OPAL interface */ + opal_register(OPAL_REGISTER_DUMP_REGION, + fsp_opal_register_dump_region, 3); + opal_register(OPAL_UNREGISTER_DUMP_REGION, + fsp_opal_unregister_dump_region, 1); + + if (!fsp_mdst_supported()) + return; + + /* Initiate MDST */ + if (mdst_table_init() != OPAL_SUCCESS) + return; + + /* + * Ignore return code from mdst_table_add_entries so that + * we can atleast capture partial dump. + */ + dump_region_add_entries(); + fsp_update_mdst_table(); + + /* Register for Class AA (FSP R/R) */ + fsp_register_client(&fsp_mdst_client_rr, FSP_MCLASS_RR_EVENT); +} diff --git a/include/fsp-mdst-table.h b/include/fsp-mdst-table.h deleted file mode 100644 index 7f0ce14..0000000 --- a/include/fsp-mdst-table.h +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -/* Copyright 2013-2015 IBM Corp. */ - -#ifndef __FSPMDST_H -#define __FSPMDST_H - -/* - * Dump region ids - * - * 0x01 - 0x7F : OPAL - * 0x80 - 0xFF : Kernel - * - */ -#define DUMP_REGION_OPAL_START 0x01 -#define DUMP_REGION_OPAL_END 0x7F -#define DUMP_REGION_HOST_START OPAL_DUMP_REGION_HOST_START -#define DUMP_REGION_HOST_END OPAL_DUMP_REGION_HOST_END - -#define DUMP_REGION_CONSOLE 0x01 -#define DUMP_REGION_HBRT_LOG 0x02 - -/* - * Sapphire Memory Dump Source Table - * - * Format of this table is same as Memory Dump Source Table (MDST) - * defined in HDAT spec. - */ -struct dump_mdst_table { - __be64 addr; - __be32 type; /* DUMP_SECTION_* */ - __be32 size; -}; - -#endif /* __FSPMDST_H */ diff --git a/include/opal-dump.h b/include/opal-dump.h new file mode 100644 index 0000000..631aa20 --- /dev/null +++ b/include/opal-dump.h @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 +/* Copyright 2013-2015 IBM Corp. */ + +#ifndef __OPAL_DUMP_H +#define __OPAL_DUMP_H + +/* + * Dump region ids + * + * 0x01 - 0x7F : OPAL + * 0x80 - 0xFF : Kernel + * + */ +#define DUMP_REGION_OPAL_START 0x01 +#define DUMP_REGION_OPAL_END 0x7F +#define DUMP_REGION_HOST_START OPAL_DUMP_REGION_HOST_START +#define DUMP_REGION_HOST_END OPAL_DUMP_REGION_HOST_END + +#define DUMP_REGION_CONSOLE 0x01 +#define DUMP_REGION_HBRT_LOG 0x02 + +/* + * Sapphire Memory Dump Source Table + * + * Format of this table is same as Memory Dump Source Table (MDST) + * defined in HDAT spec. + */ +struct mdst_table { + __be64 addr; + __be32 type; /* DUMP_REGION_* */ + __be32 size; +}; + +#endif /* __OPAL_DUMP_H */ -- cgit v1.1