soc/intel/tigerlake: Add CrashLog implementation for intel TGL
CrashLog is a diagnostic feature for Intel TGL based platforms. It is meant to capture the state of the platform before a crash. The state of relevant registers is preserved across a warm reset. BUG=None TEST=CrashLog data generated, extracted, processed, decoded sucessfully on delbin. Signed-off-by: Francois Toguo <francois.toguo.fotso@intel.com> Change-Id: Ie3763cebcd1178709cc8597710bf062a30901809 Reviewed-on: https://review.coreboot.org/c/coreboot/+/49943 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
This commit is contained in:
parent
619c60f94c
commit
15cbc3b599
|
@ -10,7 +10,13 @@ config SOC_INTEL_COMMON_BLOCK_ACPI_LPIT
|
|||
depends on HAVE_ACPI_TABLES
|
||||
select ACPI_LPIT
|
||||
help
|
||||
Generate LPIT table with LPI state entries.
|
||||
Generate LPIT table with LPI state entries
|
||||
|
||||
config SOC_INTEL_COMMON_BLOCK_CRASHLOG
|
||||
bool
|
||||
depends on SOC_INTEL_CRASHLOG
|
||||
help
|
||||
Generate crash data for BERT table
|
||||
|
||||
if SOC_INTEL_COMMON_BLOCK_ACPI
|
||||
|
||||
|
@ -19,4 +25,5 @@ config SOC_INTEL_COMMON_BLOCK_ACPI_CPPC
|
|||
help
|
||||
Generate CPPC entries for Intel SpeedShift
|
||||
|
||||
|
||||
endif
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ACPI) += acpi.c
|
||||
ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ACPI_LPIT) += lpit.c
|
||||
ramstage-$(CONFIG_ACPI_BERT) += acpi_bert.c
|
||||
ramstage-$(CONFIG_SOC_INTEL_COMMON_ACPI_WAKE_SOURCE) += acpi_wake_source.c
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acpigen.h>
|
||||
#include <arch/bert_storage.h>
|
||||
#include <console/console.h>
|
||||
#include <intelblocks/acpi.h>
|
||||
#include <intelblocks/crashlog.h>
|
||||
|
||||
|
||||
void acpi_soc_fill_bert(acpi_bert_t *bert,
|
||||
void **region,
|
||||
size_t *length)
|
||||
{
|
||||
acpi_generic_error_status_t *status = NULL;
|
||||
size_t cpu_record_size, pmc_record_size;
|
||||
void *cl_data = NULL;
|
||||
|
||||
if (!cl_get_total_data_size()) {
|
||||
printk(BIOS_ERR, "Error: No crashlog record present\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = bert_new_event(&CPER_SEC_FW_ERR_REC_REF_GUID);
|
||||
if (!status) {
|
||||
printk(BIOS_ERR, "Error: unable to allocate GSB\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cl_get_total_data_size() > bert_storage_remaining()) {
|
||||
printk(BIOS_ERR, "Error: Crashlog entry would exceed "
|
||||
"available region\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_record_size = cl_get_cpu_record_size();
|
||||
if (cpu_record_size) {
|
||||
cl_data = new_cper_fw_error_crashlog(status, cpu_record_size);
|
||||
if (!cl_data) {
|
||||
printk(BIOS_ERR, "Error: Crashlog CPU entry(size %lu) "
|
||||
"would exceed available region\n",
|
||||
cpu_record_size);
|
||||
return;
|
||||
}
|
||||
printk(BIOS_DEBUG, "cl_data %p, cpu_record_size %lu\n",
|
||||
cl_data, cpu_record_size);
|
||||
cl_fill_cpu_records(cl_data);
|
||||
}
|
||||
|
||||
pmc_record_size = cl_get_pmc_record_size();
|
||||
if (pmc_record_size) {
|
||||
/* Allocate new FW ERR structure in case CPU crashlog is present */
|
||||
if (cpu_record_size && !bert_append_fw_err(status)) {
|
||||
printk(BIOS_ERR, "Error: Crashlog PMC entry would "
|
||||
"exceed available region\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cl_data = new_cper_fw_error_crashlog(status, pmc_record_size);
|
||||
if (!cl_data) {
|
||||
printk(BIOS_ERR, "Error: Crashlog PMC entry(size %lu) "
|
||||
"would exceed available region\n",
|
||||
pmc_record_size);
|
||||
return;
|
||||
}
|
||||
printk(BIOS_DEBUG, "cl_data %p, pmc_record_size %lu\n",
|
||||
cl_data, pmc_record_size);
|
||||
cl_fill_pmc_records(cl_data);
|
||||
}
|
||||
|
||||
*length = status->raw_data_length;
|
||||
*region = (void *)status;
|
||||
|
||||
}
|
||||
|
||||
bool acpi_is_boot_error_src_present(void)
|
||||
{
|
||||
|
||||
if (!CONFIG(SOC_INTEL_CRASHLOG)) {
|
||||
printk(BIOS_DEBUG, "Crashlog disabled.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!discover_crashlog()) {
|
||||
printk(BIOS_SPEW, "Crashlog discovery result: crashlog not found\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
collect_pmc_and_cpu_crashlog_from_srams();
|
||||
|
||||
/* Discovery tables sizes can be larger than the actual valid collected data */
|
||||
u32 crashlog_size = cl_get_total_data_size();
|
||||
|
||||
return (crashlog_size > 0);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CRASHLOG) += crashlog.c
|
|
@ -0,0 +1,536 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <console/console.h>
|
||||
#include <cbmem.h>
|
||||
#include <delay.h>
|
||||
#include <intelblocks/crashlog.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
int __weak cl_get_cpu_record_size(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int __weak cl_get_pmc_record_size(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u32 __weak cl_get_cpu_bar_addr(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u32 __weak cl_get_cpu_tmp_bar(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u32 __weak cl_get_cpu_mb_int_addr(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int __weak cl_get_total_data_size(void)
|
||||
{
|
||||
return cl_get_cpu_record_size() + cl_get_pmc_record_size();
|
||||
}
|
||||
|
||||
|
||||
bool __weak cl_pmc_sram_has_mmio_access(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool __weak cpu_crashlog_support(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool __weak pmc_crashlog_support(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool __weak cl_cpu_data_present(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool __weak cl_pmc_data_present(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
__weak void reset_discovery_buffers(void) {}
|
||||
|
||||
|
||||
__weak void update_new_pmc_crashlog_size(u32 *pmc_crash_size) {}
|
||||
|
||||
|
||||
__weak void update_new_cpu_crashlog_size(u32 *cpu_crash_size) {}
|
||||
|
||||
|
||||
pmc_ipc_discovery_buf_t __weak cl_get_pmc_discovery_buf(void)
|
||||
{
|
||||
pmc_ipc_discovery_buf_t discov_buf;
|
||||
memset(&discov_buf, 0, sizeof(pmc_ipc_discovery_buf_t));
|
||||
return discov_buf;
|
||||
}
|
||||
|
||||
|
||||
pmc_crashlog_desc_table_t __weak cl_get_pmc_descriptor_table(void)
|
||||
{
|
||||
pmc_crashlog_desc_table_t desc_tab;
|
||||
memset(&desc_tab, 0, sizeof(pmc_crashlog_desc_table_t));
|
||||
return desc_tab;
|
||||
}
|
||||
|
||||
|
||||
cpu_crashlog_discovery_table_t __weak cl_get_cpu_discovery_table(void)
|
||||
{
|
||||
cpu_crashlog_discovery_table_t cpu_disc_tab;
|
||||
memset(&cpu_disc_tab, 0, sizeof(cpu_crashlog_discovery_table_t));
|
||||
return cpu_disc_tab;
|
||||
}
|
||||
|
||||
|
||||
int cpu_cl_poll_mailbox_ready(u32 cl_mailbox_addr)
|
||||
{
|
||||
cpu_crashlog_mailbox_t cl_mailbox_interface;
|
||||
u16 stall_cnt = 0;
|
||||
|
||||
do {
|
||||
cl_mailbox_interface.data = read32((u32 *)cl_mailbox_addr);
|
||||
udelay(CPU_CRASHLOG_MAILBOX_WAIT_STALL);
|
||||
stall_cnt++;
|
||||
} while ((cl_mailbox_interface.fields.busy == 1)
|
||||
&& stall_cnt < CPU_CRASHLOG_MAILBOX_WAIT_TIMEOUT);
|
||||
|
||||
if ((cl_mailbox_interface.fields.busy == 1)
|
||||
&& (stall_cnt >= CPU_CRASHLOG_MAILBOX_WAIT_TIMEOUT)) {
|
||||
printk(BIOS_ERR, "CPU crashlog mailbox timed out.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int cpu_cl_mailbox_cmd(u8 cmd, u8 param)
|
||||
{
|
||||
cpu_crashlog_mailbox_t cl_mailbox_intf;
|
||||
u32 cl_base_addr;
|
||||
|
||||
memset(&cl_mailbox_intf, 0, sizeof(cpu_crashlog_mailbox_t));
|
||||
|
||||
cl_base_addr = cl_get_cpu_bar_addr();
|
||||
|
||||
cl_mailbox_intf.fields.command = cmd;
|
||||
cl_mailbox_intf.fields.param = param;
|
||||
cl_mailbox_intf.fields.busy = 1;
|
||||
|
||||
write32((u32 *)(cl_base_addr + cl_get_cpu_mb_int_addr()),
|
||||
cl_mailbox_intf.data);
|
||||
|
||||
cpu_cl_poll_mailbox_ready(cl_base_addr + cl_get_cpu_mb_int_addr());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int cpu_cl_clear_data(void)
|
||||
{
|
||||
return cpu_cl_mailbox_cmd(CPU_CRASHLOG_CMD_CLEAR, 0);
|
||||
}
|
||||
|
||||
|
||||
int pmc_cl_gen_descriptor_table(u32 desc_table_addr,
|
||||
pmc_crashlog_desc_table_t *descriptor_table)
|
||||
{
|
||||
int total_data_size = 0;
|
||||
descriptor_table->numb_regions = read32((u32 *)desc_table_addr);
|
||||
printk(BIOS_DEBUG, "CL PMC desc table: numb of regions is 0x%x at addr 0x%x\n",
|
||||
descriptor_table->numb_regions, desc_table_addr);
|
||||
for (int i = 0; i < descriptor_table->numb_regions; i++) {
|
||||
desc_table_addr += 4;
|
||||
descriptor_table->regions[i].data = read32((u32 *)(desc_table_addr));
|
||||
total_data_size += descriptor_table->regions[i].bits.size * sizeof(u32);
|
||||
printk(BIOS_DEBUG, "CL PMC desc table: region 0x%x has size 0x%x at offset 0x%x\n",
|
||||
i, descriptor_table->regions[i].bits.size,
|
||||
descriptor_table->regions[i].bits.offset);
|
||||
if (i > 255) {
|
||||
printk(BIOS_ERR, "More than 255 regions in PMC crashLog descriptor table");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return total_data_size;
|
||||
}
|
||||
|
||||
|
||||
bool __weak pmc_cl_discovery(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool __weak cpu_cl_discovery(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int cl_pmc_re_arm_after_reset(void)
|
||||
{
|
||||
|
||||
const struct pmc_ipc_buffer *req = { 0 };
|
||||
struct pmc_ipc_buffer *res = NULL;
|
||||
uint32_t cmd_reg;
|
||||
int r;
|
||||
|
||||
cmd_reg = pmc_make_ipc_cmd(PMC_IPC_CMD_CRASHLOG,
|
||||
PMC_IPC_CMD_ID_CRASHLOG_RE_ARM_ON_RESET,
|
||||
PMC_IPC_CMD_SIZE_SHIFT);
|
||||
|
||||
r = pmc_send_ipc_cmd(cmd_reg, req, res);
|
||||
|
||||
if (r < 0) {
|
||||
printk(BIOS_ERR, "pmc_send_ipc_cmd failed in %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* Sends PMC IPC to clear CrashLog from PMC SSRAM area */
|
||||
int cl_pmc_clear(void)
|
||||
{
|
||||
const struct pmc_ipc_buffer *req = { 0 };
|
||||
struct pmc_ipc_buffer *res = NULL;
|
||||
uint32_t cmd_reg;
|
||||
int r;
|
||||
|
||||
cmd_reg = pmc_make_ipc_cmd(PMC_IPC_CMD_CRASHLOG,
|
||||
PMC_IPC_CMD_ID_CRASHLOG_ERASE,
|
||||
PMC_IPC_CMD_SIZE_SHIFT);
|
||||
|
||||
r = pmc_send_ipc_cmd(cmd_reg, req, res);
|
||||
|
||||
if (r < 0) {
|
||||
printk(BIOS_ERR, "pmc_send_ipc_cmd failed in %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sends PMC IPC to populate CrashLog on all reboot.
|
||||
* The SSRAM area will be cleared on G3 by PMC automatically
|
||||
*/
|
||||
|
||||
int cl_pmc_en_gen_on_all_reboot(void)
|
||||
{
|
||||
const struct pmc_ipc_buffer *req = { 0 };
|
||||
struct pmc_ipc_buffer *res = NULL;
|
||||
uint32_t cmd_reg;
|
||||
int r;
|
||||
|
||||
cmd_reg = pmc_make_ipc_cmd(PMC_IPC_CMD_CRASHLOG,
|
||||
PMC_IPC_CMD_ID_CRASHLOG_ON_RESET,
|
||||
PMC_IPC_CMD_SIZE_SHIFT);
|
||||
|
||||
r = pmc_send_ipc_cmd(cmd_reg, req, res);
|
||||
|
||||
if (r < 0) {
|
||||
printk(BIOS_ERR, "pmc_send_ipc_cmd failed in %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
bool discover_crashlog(void)
|
||||
{
|
||||
bool cpu_cl_discovered = false, pmc_cl_discovered = false;
|
||||
|
||||
reset_discovery_buffers();
|
||||
|
||||
/* PCH crashLog discovery */
|
||||
pmc_cl_discovered = pmc_cl_discovery();
|
||||
|
||||
/* CPU crashLog discovery */
|
||||
cpu_cl_discovered = cpu_cl_discovery();
|
||||
|
||||
return (cpu_cl_discovered || pmc_cl_discovered);
|
||||
}
|
||||
|
||||
|
||||
bool cl_copy_data_from_sram(u32 src_bar,
|
||||
u32 offset,
|
||||
u32 size,
|
||||
u32 *dest_addr,
|
||||
u32 buffer_index,
|
||||
bool pmc_sram)
|
||||
{
|
||||
if (src_bar == 0) {
|
||||
printk(BIOS_ERR, "Invalid bar 0x%x and offset 0x%x for %s\n",
|
||||
src_bar, offset, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 src_addr = src_bar + offset;
|
||||
|
||||
u32 data = read32((u32 *)src_addr);
|
||||
/* PMC: copy if 1st DWORD in buffer is not zero and its 31st bit is not set */
|
||||
if (pmc_sram && !(data && !(data & BIT(31)))) {
|
||||
printk(BIOS_DEBUG, "Invalid data 0x%x at offset 0x%x from addr 0x%x"
|
||||
" of PMC SRAM.\n", data, offset, src_bar);
|
||||
return false;
|
||||
}
|
||||
/*CPU: don't copy if 1st DWORD in first buffer is zero */
|
||||
if (!pmc_sram && !data && (buffer_index == 0)) {
|
||||
printk(BIOS_DEBUG, "Invalid data 0x%x at offset 0x%x from addr 0x%x"
|
||||
" of telemetry SRAM.\n", data, offset, src_bar);
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 copied = 0;
|
||||
while (copied < size) {
|
||||
/* DW by DW copy: byte access to PMC SRAM not allowed */
|
||||
*dest_addr = read32((u32 *)src_addr);
|
||||
dest_addr++;
|
||||
src_addr += 4;
|
||||
copied++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void cl_get_pmc_sram_data(void)
|
||||
{
|
||||
u32 *dest = NULL;
|
||||
u32 tmp_bar_addr = cl_get_cpu_tmp_bar();
|
||||
u32 pmc_crashLog_size = cl_get_pmc_record_size();
|
||||
|
||||
if (!cl_pmc_sram_has_mmio_access())
|
||||
return;
|
||||
|
||||
pmc_ipc_discovery_buf_t discovery_buf = cl_get_pmc_discovery_buf();
|
||||
|
||||
if (discovery_buf.bits.supported != 1) {
|
||||
printk(BIOS_DEBUG, "PCH crashlog feature not supported.\n");
|
||||
goto pmc_send_re_arm_after_reset;
|
||||
}
|
||||
|
||||
/* Get the size of data to copy */
|
||||
if (discovery_buf.bits.discov_mechanism == 1) {
|
||||
if (discovery_buf.bits.base_offset & BIT(31)) {
|
||||
printk(BIOS_DEBUG, "PCH discovery to be used is disabled.\n");
|
||||
goto pmc_send_re_arm_after_reset;
|
||||
}
|
||||
printk(BIOS_DEBUG, "PMC crashLog size in discovery mode : 0x%X\n",
|
||||
pmc_crashLog_size);
|
||||
} else {
|
||||
if (discovery_buf.bits.dis) {
|
||||
printk(BIOS_DEBUG, "PCH crashlog is disabled in legacy mode.\n");
|
||||
return;
|
||||
}
|
||||
pmc_crashLog_size = (discovery_buf.bits.size != 0) ?
|
||||
discovery_buf.bits.size : 0xC00;
|
||||
printk(BIOS_DEBUG, "PMC crashLog size in legacy mode : 0x%X\n",
|
||||
pmc_crashLog_size);
|
||||
}
|
||||
|
||||
/* allocate mem for the record to be copied */
|
||||
unsigned long pmc_cl_cbmem_addr;
|
||||
|
||||
pmc_cl_cbmem_addr = (unsigned long) cbmem_add(CBMEM_ID_PMC_CRASHLOG,
|
||||
pmc_crashLog_size);
|
||||
if (!pmc_cl_cbmem_addr) {
|
||||
printk(BIOS_ERR, "Unable to allocate CBMEM PMC crashLog entry.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset((void *)pmc_cl_cbmem_addr, 0, pmc_crashLog_size);
|
||||
dest = (u32 *)(uintptr_t) pmc_cl_cbmem_addr;
|
||||
bool pmc_sram = true;
|
||||
pmc_crashlog_desc_table_t descriptor_table = cl_get_pmc_descriptor_table();
|
||||
if (discovery_buf.bits.discov_mechanism == 1) {
|
||||
for (int i = 0; i < descriptor_table.numb_regions; i++) {
|
||||
if (cl_copy_data_from_sram(tmp_bar_addr,
|
||||
descriptor_table.regions[i].bits.offset,
|
||||
descriptor_table.regions[i].bits.size,
|
||||
dest,
|
||||
i,
|
||||
pmc_sram)) {
|
||||
dest = (u32 *)((u32)dest +
|
||||
(descriptor_table.regions[i].bits.size
|
||||
* sizeof(u32)));
|
||||
} else {
|
||||
pmc_crashLog_size -= descriptor_table.regions[i].bits.size *
|
||||
sizeof(u32);
|
||||
printk(BIOS_DEBUG, "discover mode PMC crashlog size adjusted"
|
||||
" to: 0x%x\n", pmc_crashLog_size);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!cl_copy_data_from_sram(tmp_bar_addr,
|
||||
discovery_buf.bits.base_offset,
|
||||
discovery_buf.bits.size,
|
||||
dest,
|
||||
0,
|
||||
pmc_sram)) {
|
||||
pmc_crashLog_size -= discovery_buf.bits.size * sizeof(u32);
|
||||
printk(BIOS_DEBUG, "legacy mode PMC crashlog size adjusted to: 0x%x\n",
|
||||
pmc_crashLog_size);
|
||||
}
|
||||
}
|
||||
|
||||
update_new_pmc_crashlog_size(&pmc_crashLog_size);
|
||||
|
||||
pmc_send_re_arm_after_reset:
|
||||
/* when bit 7 of discov cmd resp is set -> bit 2 of size field */
|
||||
if (discovery_buf.bits.size & BIT(2))
|
||||
cl_pmc_re_arm_after_reset();
|
||||
|
||||
/* Clear the SSRAM region after copying the error log */
|
||||
cl_pmc_clear();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cl_get_cpu_sram_data(void)
|
||||
{
|
||||
u32 tmp_bar_addr = 0;
|
||||
u32 *dest = NULL;
|
||||
u32 m_cpu_crashLog_size = cl_get_cpu_record_size();
|
||||
cpu_crashlog_discovery_table_t cpu_cl_disc_tab = cl_get_cpu_discovery_table();
|
||||
|
||||
if (m_cpu_crashLog_size < 1) {
|
||||
printk(BIOS_DEBUG, "%s: no data to collect.\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "CPU crash data size: 0x%X bytes in 0x%X region(s).\n",
|
||||
m_cpu_crashLog_size, cpu_cl_disc_tab.header.fields.count);
|
||||
|
||||
/* allocate memory buffers for CPU crashog data to be copied */
|
||||
unsigned long cpu_crashlog_cbmem_addr;
|
||||
cpu_crashlog_cbmem_addr = (unsigned long) cbmem_add(CBMEM_ID_CPU_CRASHLOG,
|
||||
m_cpu_crashLog_size);
|
||||
if (!cpu_crashlog_cbmem_addr) {
|
||||
printk(BIOS_ERR, "Failed to add CPU main crashLog entries to CBMEM.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset((void *) cpu_crashlog_cbmem_addr, 0, m_cpu_crashLog_size);
|
||||
tmp_bar_addr = cl_get_cpu_bar_addr();
|
||||
dest = (u32 *)(uintptr_t) cpu_crashlog_cbmem_addr;
|
||||
bool pmc_sram = false;
|
||||
cpu_crashlog_buffer_info_t buff_info;
|
||||
|
||||
for (int i = 0 ; i < cpu_cl_disc_tab.header.fields.count ; i++) {
|
||||
buff_info = cpu_cl_disc_tab.buffers[i];
|
||||
|
||||
if (cl_copy_data_from_sram(tmp_bar_addr,
|
||||
cpu_cl_disc_tab.buffers[i].fields.offset,
|
||||
cpu_cl_disc_tab.buffers[i].fields.size,
|
||||
dest,
|
||||
i,
|
||||
pmc_sram)) {
|
||||
dest = (u32 *)((u32)dest +
|
||||
(cpu_cl_disc_tab.buffers[i].fields.size * sizeof(u32)));
|
||||
} else {
|
||||
m_cpu_crashLog_size -= cpu_cl_disc_tab.buffers[i].fields.size
|
||||
* sizeof(u32);
|
||||
|
||||
/* for CPU skip all buffers if the 1st one is not valid */
|
||||
if (i == 0) {
|
||||
m_cpu_crashLog_size = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_new_cpu_crashlog_size(&m_cpu_crashLog_size);
|
||||
|
||||
/* clear telemetry SRAM region */
|
||||
cpu_cl_clear_data();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void collect_pmc_and_cpu_crashlog_from_srams(void)
|
||||
{
|
||||
if (pmc_crashlog_support() && cl_pmc_data_present()
|
||||
&& (cl_get_pmc_record_size() > 0)) {
|
||||
cl_pmc_en_gen_on_all_reboot();
|
||||
printk(BIOS_DEBUG, "Crashlog collection enabled on every reboot.\n");
|
||||
cl_get_pmc_sram_data();
|
||||
} else {
|
||||
printk(BIOS_DEBUG, "Skipping PMC crashLog collection. Data not present.\n");
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "m_cpu_crashLog_size : 0x%X bytes\n", cl_get_cpu_record_size());
|
||||
|
||||
if (cpu_crashlog_support() && cl_cpu_data_present()
|
||||
&& (cl_get_cpu_record_size() > 0)) {
|
||||
printk(BIOS_DEBUG, "CPU crashLog present.\n");
|
||||
cl_get_cpu_sram_data();
|
||||
} else {
|
||||
printk(BIOS_DEBUG, "Skipping CPU crashLog collection. Data not present.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool cl_fill_cpu_records(void *cl_record)
|
||||
{
|
||||
void *cl_src_addr = NULL;
|
||||
|
||||
u32 m_cpu_crashLog_size = cl_get_cpu_record_size();
|
||||
|
||||
if (!cl_cpu_data_present() || m_cpu_crashLog_size == 0) {
|
||||
printk(BIOS_DEBUG, "CPU crashLog not present, skipping.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "CPU crash data collection.\n");
|
||||
cl_src_addr = cbmem_find(CBMEM_ID_CPU_CRASHLOG);
|
||||
memcpy(cl_record, cl_src_addr, m_cpu_crashLog_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool cl_fill_pmc_records(void *cl_record)
|
||||
{
|
||||
void *cl_src_addr = NULL;
|
||||
|
||||
u32 m_pmc_crashLog_size = cl_get_pmc_record_size();
|
||||
|
||||
if (!cl_pmc_data_present() || m_pmc_crashLog_size == 0) {
|
||||
printk(BIOS_DEBUG, "PMC crashLog not present, skipping.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "PMC crash data collection.\n");
|
||||
cl_src_addr = cbmem_find(CBMEM_ID_PMC_CRASHLOG);
|
||||
memcpy(cl_record, cl_src_addr, m_pmc_crashLog_size);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef SOC_INTEL_COMMON_BLOCK_CRASHLOG_H
|
||||
#define SOC_INTEL_COMMON_BLOCK_CRASHLOG_H
|
||||
|
||||
#include <console/console.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <device/pci_def.h>
|
||||
#include <device/mmio.h>
|
||||
#include <fsp/util.h>
|
||||
#include <intelblocks/pmc_ipc.h>
|
||||
#include <types.h>
|
||||
#include <arch/io.h>
|
||||
|
||||
/* PMC CrashLog Command */
|
||||
#define PMC_IPC_CMD_CRASHLOG 0xA6
|
||||
#define PMC_IPC_CMD_ID_CRASHLOG_DISCOVERY 0x01
|
||||
#define PMC_IPC_CMD_ID_CRASHLOG_DISABLE 0x02
|
||||
#define PMC_IPC_CMD_ID_CRASHLOG_ERASE 0x04
|
||||
#define PMC_IPC_CMD_ID_CRASHLOG_ON_RESET 0x05
|
||||
#define PMC_IPC_CMD_ID_CRASHLOG_RE_ARM_ON_RESET 0x06
|
||||
|
||||
/* CPU CrashLog Mailbox commands */
|
||||
#define CPU_CRASHLOG_CMD_DISABLE 0
|
||||
#define CPU_CRASHLOG_CMD_CLEAR 2
|
||||
#define CPU_CRASHLOG_MAILBOX_WAIT_STALL 1
|
||||
#define CPU_CRASHLOG_MAILBOX_WAIT_TIMEOUT 1000
|
||||
#define CPU_CRASHLOG_DISC_TAB_GUID_VALID 0x1600
|
||||
|
||||
#define CRASHLOG_SIZE_DEBUG_PURPOSE 0x640
|
||||
|
||||
/* PMC crashlog discovery structs */
|
||||
typedef union {
|
||||
struct {
|
||||
u16 offset;
|
||||
u16 size;
|
||||
} bits;
|
||||
u32 data;
|
||||
} __packed pmc_crashlog_discov_region_t;
|
||||
|
||||
typedef struct {
|
||||
u32 numb_regions;
|
||||
pmc_crashlog_discov_region_t regions[256];
|
||||
} __packed pmc_crashlog_desc_table_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
u32 supported :1;
|
||||
u32 dis :1;
|
||||
u32 discov_mechanism :2;
|
||||
u32 size :12;
|
||||
u32 base_offset :16; /* Start offset of CrashLog in PMC SSRAM */
|
||||
u32 rsv :16;
|
||||
u32 desc_tabl_offset :16; /* start offset of descriptor table */
|
||||
} bits;
|
||||
u64 val_64_bits;
|
||||
} __packed pmc_ipc_discovery_buf_t;
|
||||
|
||||
|
||||
/* CPU/TELEMETRY crashlog discovery structs */
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
u32 pcie_cap_id :16;
|
||||
u32 cap_ver :4;
|
||||
u32 next_cap_offset :12;
|
||||
} fields;
|
||||
u32 data;
|
||||
} __packed cap_data_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
u64 devsc_ven_id :16;
|
||||
u64 devsc_ver :4;
|
||||
u64 devsc_len :12;
|
||||
u64 devsc_id :16;
|
||||
u64 num_entries :8; /*Numb of telemetry aggregators in lookup table. */
|
||||
u64 entries_size :8; /* Entry Size in DWORDS */
|
||||
} fields;
|
||||
u64 data_64;
|
||||
u32 data_32[2];
|
||||
} __packed devsc_data_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
u32 t_bir_q :3; /* tBIR, The BAR to be used */
|
||||
u32 discovery_table_offset :29;
|
||||
} fields;
|
||||
u32 data;
|
||||
} __packed discovery_data_t;
|
||||
|
||||
typedef struct {
|
||||
cap_data_t cap_data;
|
||||
devsc_data_t devsc_data;
|
||||
discovery_data_t discovery_data;
|
||||
} __packed tel_crashlog_devsc_cap_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
u64 access_type :4;
|
||||
u64 crash_type :4;
|
||||
u64 count :8;
|
||||
u64 reserved :16;
|
||||
u64 guid :32;
|
||||
} fields;
|
||||
u64 data;
|
||||
} __packed cpu_crashlog_header_t;
|
||||
|
||||
|
||||
/* Structures for CPU CrashLog mailbox interface */
|
||||
typedef union {
|
||||
struct {
|
||||
u32 command :8;
|
||||
u32 param :8;
|
||||
u32 reserved :15;
|
||||
u32 busy :1;
|
||||
} fields;
|
||||
u32 data;
|
||||
} __packed cpu_crashlog_mailbox_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
u32 offset :32;
|
||||
u32 size :16;
|
||||
u32 reserved :16;
|
||||
} fields;
|
||||
u64 data;
|
||||
} __packed cpu_crashlog_buffer_info_t;
|
||||
|
||||
typedef struct {
|
||||
cpu_crashlog_header_t header;
|
||||
cpu_crashlog_mailbox_t cmd_mailbox;
|
||||
u32 mailbox_data;
|
||||
cpu_crashlog_buffer_info_t buffers[256];
|
||||
} __packed cpu_crashlog_discovery_table_t;
|
||||
|
||||
int cl_get_cpu_record_size(void);
|
||||
int cl_get_pmc_record_size(void);
|
||||
u32 cl_get_cpu_bar_addr(void);
|
||||
u32 cl_get_cpu_tmp_bar(void);
|
||||
u32 cl_get_cpu_mb_int_addr(void);
|
||||
int cl_get_total_data_size(void);
|
||||
bool cl_pmc_sram_has_mmio_access(void);
|
||||
bool cpu_crashlog_support(void);
|
||||
bool pmc_crashlog_support(void);
|
||||
bool cl_cpu_data_present(void);
|
||||
bool cl_pmc_data_present(void);
|
||||
void cl_get_cpu_sram_data(void);
|
||||
void cl_get_pmc_sram_data(void);
|
||||
void reset_discovery_buffers(void);
|
||||
void update_new_pmc_crashlog_size(u32 *pmc_crash_size);
|
||||
void update_new_cpu_crashlog_size(u32 *cpu_crash_size);
|
||||
pmc_ipc_discovery_buf_t cl_get_pmc_discovery_buf(void);
|
||||
pmc_crashlog_desc_table_t cl_get_pmc_descriptor_table(void);
|
||||
cpu_crashlog_discovery_table_t cl_get_cpu_discovery_table(void);
|
||||
u32 cl_gen_cpu_bar_addr(void);
|
||||
int cpu_cl_poll_mailbox_ready(u32 cl_mailbox_addr);
|
||||
int cpu_cl_mailbox_cmd(u8 cmd, u8 param);
|
||||
int cpu_cl_clear_data(void);
|
||||
int pmc_cl_gen_descriptor_table(u32 desc_table_addr,
|
||||
pmc_crashlog_desc_table_t *descriptor_table);
|
||||
bool pmc_cl_discovery(void);
|
||||
bool cpu_cl_discovery(void);
|
||||
int cl_pmc_re_arm_after_reset(void);
|
||||
int cl_pmc_clear(void);
|
||||
int cl_pmc_en_gen_on_all_reboot(void);
|
||||
bool discover_crashlog(void);
|
||||
bool cl_copy_data_from_sram(u32 src_bar,
|
||||
u32 offset,
|
||||
u32 size,
|
||||
u32 *dest_addr,
|
||||
u32 buffer_index,
|
||||
bool pmc_sram);
|
||||
void collect_pmc_and_cpu_crashlog_from_srams(void);
|
||||
bool cl_fill_cpu_records(void *cl_record);
|
||||
bool cl_fill_pmc_records(void *cl_record);
|
||||
|
||||
static const EFI_GUID FW_ERR_SECTION_GUID = {
|
||||
0x81212a96, 0x09ed, 0x4996,
|
||||
{ 0x94, 0x71, 0x8d, 0x72, 0x9c, 0x8e, 0x69, 0xed }
|
||||
};
|
||||
|
||||
#endif /* SOC_INTEL_COMMON_BLOCK_CRASHLOG */
|
|
@ -17,7 +17,7 @@
|
|||
#define PMC_IPC_CMD_SIZE_MASK 0xff
|
||||
|
||||
#define PMC_IPC_CMD_FIELD(name, val) \
|
||||
(((val) & PMC_IPC_CMD_##name##_MASK << PMC_IPC_CMD_##name##_SHIFT))
|
||||
((((val) & PMC_IPC_CMD_##name##_MASK) << PMC_IPC_CMD_##name##_SHIFT))
|
||||
|
||||
#define PMC_IPC_CMD_NO_MSI 0
|
||||
|
||||
|
|
|
@ -255,4 +255,11 @@ config MRC_CHANNEL_WIDTH
|
|||
int
|
||||
default 16
|
||||
|
||||
config SOC_INTEL_CRASHLOG
|
||||
def_bool n
|
||||
select SOC_INTEL_COMMON_BLOCK_CRASHLOG
|
||||
select ACPI_BERT
|
||||
help
|
||||
Enables CrashLog.
|
||||
|
||||
endif
|
||||
|
|
|
@ -46,6 +46,7 @@ ramstage-y += soundwire.c
|
|||
ramstage-y += systemagent.c
|
||||
ramstage-y += me.c
|
||||
ramstage-y += xhci.c
|
||||
ramstage-$(CONFIG_SOC_INTEL_CRASHLOG) += crashlog_lib.c
|
||||
|
||||
smm-y += gpio.c
|
||||
smm-y += p2sb.c
|
||||
|
|
|
@ -0,0 +1,320 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <console/console.h>
|
||||
#include <cbmem.h>
|
||||
#include <delay.h>
|
||||
#include <intelblocks/crashlog.h>
|
||||
#include <string.h>
|
||||
#include <soc/crashlog.h>
|
||||
#include <arch/bert_storage.h>
|
||||
#include <soc/iomap.h>
|
||||
#include <soc/pci_devs.h>
|
||||
|
||||
/* global crashLog info */
|
||||
static bool m_pmc_crashLog_support;
|
||||
static bool m_pmc_crashLog_present;
|
||||
static bool m_cpu_crashLog_support;
|
||||
static bool m_cpu_crashLog_present;
|
||||
static u32 m_pmc_crashLog_size;
|
||||
static u32 m_cpu_crashLog_size;
|
||||
static u32 cpu_crash_version;
|
||||
static pmc_ipc_discovery_buf_t discovery_buf;
|
||||
static pmc_crashlog_desc_table_t descriptor_table;
|
||||
static tel_crashlog_devsc_cap_t cpu_cl_devsc_cap;
|
||||
static cpu_crashlog_discovery_table_t cpu_cl_disc_tab;
|
||||
|
||||
u32 __weak cl_get_cpu_mb_int_addr(void)
|
||||
{
|
||||
return CRASHLOG_MAILBOX_INTF_ADDRESS;
|
||||
}
|
||||
|
||||
bool pmc_cl_discovery(void)
|
||||
{
|
||||
u32 tmp_bar_addr = 0, desc_table_addr = 0;
|
||||
|
||||
const struct pmc_ipc_buffer *req = { 0 };
|
||||
struct pmc_ipc_buffer *res = NULL;
|
||||
uint32_t cmd_reg;
|
||||
int r;
|
||||
|
||||
cmd_reg = pmc_make_ipc_cmd(PMC_IPC_CMD_CRASHLOG,
|
||||
PMC_IPC_CMD_ID_CRASHLOG_DISCOVERY,
|
||||
PMC_IPC_CMD_SIZE_SHIFT);
|
||||
printk(BIOS_DEBUG, "cmd_reg from pmc_make_ipc_cmd %d\n", cmd_reg);
|
||||
|
||||
r = pmc_send_ipc_cmd(cmd_reg, req, res);
|
||||
|
||||
if (r < 0) {
|
||||
printk(BIOS_ERR, "pmc_send_ipc_cmd failed in %s\n", __func__);
|
||||
return false;
|
||||
}
|
||||
discovery_buf.val_64_bits = ((u64)res->buf[1] << 32) | res->buf[0];
|
||||
|
||||
|
||||
if (discovery_buf.bits.supported != 1) {
|
||||
printk(BIOS_DEBUG, "PCH crashlog feature not supported.\n");
|
||||
m_pmc_crashLog_support = false;
|
||||
return false;
|
||||
}
|
||||
m_pmc_crashLog_support = true;
|
||||
|
||||
/* Program BAR 0 and enable command register memory space decoding */
|
||||
tmp_bar_addr = SPI_BASE_ADDRESS;
|
||||
pci_write_config32(PCH_DEV_SRAM, PCI_BASE_ADDRESS_0, tmp_bar_addr);
|
||||
pci_or_config16(PCH_DEV_SRAM, PCI_COMMAND, PCI_COMMAND_MEMORY);
|
||||
|
||||
if (discovery_buf.bits.discov_mechanism == 1) {
|
||||
/* discovery mode */
|
||||
if (discovery_buf.bits.base_offset & BIT(31)) {
|
||||
printk(BIOS_DEBUG, "PCH discovery to be used is disabled.\n");
|
||||
m_pmc_crashLog_present = false;
|
||||
m_pmc_crashLog_size = 0;
|
||||
return false;
|
||||
}
|
||||
desc_table_addr = tmp_bar_addr + discovery_buf.bits.desc_tabl_offset;
|
||||
m_pmc_crashLog_size = pmc_cl_gen_descriptor_table(desc_table_addr,
|
||||
&descriptor_table);
|
||||
printk(BIOS_DEBUG, "PMC crashLog size in discovery mode : 0x%X\n",
|
||||
m_pmc_crashLog_size);
|
||||
} else {
|
||||
/* legacy mode */
|
||||
if (discovery_buf.bits.dis) {
|
||||
printk(BIOS_DEBUG, "PCH crashlog is disabled in legacy mode.\n");
|
||||
m_pmc_crashLog_present = false;
|
||||
return false;
|
||||
}
|
||||
m_pmc_crashLog_size = (discovery_buf.bits.size != 0) ?
|
||||
(discovery_buf.bits.size * sizeof(u32)) : 0xC00;
|
||||
printk(BIOS_DEBUG, "PMC crashlog size in legacy mode = 0x%x\n",
|
||||
m_pmc_crashLog_size);
|
||||
}
|
||||
m_pmc_crashLog_present = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 cl_get_cpu_bar_addr(void)
|
||||
{
|
||||
u32 base_addr = 0;
|
||||
if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR0) {
|
||||
base_addr = pci_read_config32(SA_DEV_TMT, PCI_BASE_ADDRESS_0) &
|
||||
~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
|
||||
} else if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR1) {
|
||||
base_addr = pci_read_config32(SA_DEV_TMT, PCI_BASE_ADDRESS_1) &
|
||||
~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
|
||||
} else {
|
||||
printk(BIOS_ERR, "Invalid TEL_CFG_BAR value %d:\n",
|
||||
cpu_cl_devsc_cap.discovery_data.fields.t_bir_q);
|
||||
}
|
||||
|
||||
return base_addr;
|
||||
}
|
||||
|
||||
|
||||
u32 cl_get_cpu_tmp_bar(void)
|
||||
{
|
||||
return SPI_BASE_ADDRESS;
|
||||
}
|
||||
|
||||
bool cl_pmc_sram_has_mmio_access(void)
|
||||
{
|
||||
|
||||
if (pci_read_config16(PCH_DEV_SRAM, PCI_VENDOR_ID) == 0xFFFF) {
|
||||
printk(BIOS_ERR, "PMC SSRAM PCI device is disabled.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cpu_cl_get_capability(tel_crashlog_devsc_cap_t *cl_devsc_cap)
|
||||
{
|
||||
cl_devsc_cap->cap_data.data = pci_read_config32(SA_DEV_TMT,
|
||||
TEL_DVSEC_OFFSET + TEL_DVSEC_PCIE_CAP_ID);
|
||||
if (cl_devsc_cap->cap_data.fields.pcie_cap_id != TELEMETRY_EXTENDED_CAP_ID) {
|
||||
printk(BIOS_DEBUG, "Read ID for Telemetry: 0x%x differs from expected: 0x%x\n",
|
||||
cl_devsc_cap->cap_data.fields.pcie_cap_id, TELEMETRY_EXTENDED_CAP_ID);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* walk through the entries until crashLog entry */
|
||||
cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(SA_DEV_TMT, TEL_DVSEV_ID);
|
||||
int new_offset = 0;
|
||||
while (cl_devsc_cap->devsc_data.fields.devsc_id != CRASHLOG_DVSEC_ID) {
|
||||
if (cl_devsc_cap->cap_data.fields.next_cap_offset == 0
|
||||
|| cl_devsc_cap->cap_data.fields.next_cap_offset == 0xFFFF) {
|
||||
printk(BIOS_DEBUG, "Read invalid pcie_cap_id value: : 0x%x\n",
|
||||
cl_devsc_cap->cap_data.fields.pcie_cap_id);
|
||||
return false;
|
||||
}
|
||||
new_offset = cl_devsc_cap->cap_data.fields.next_cap_offset;
|
||||
cl_devsc_cap->cap_data.data = pci_read_config32(SA_DEV_TMT,
|
||||
new_offset + TEL_DVSEC_PCIE_CAP_ID);
|
||||
cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(SA_DEV_TMT,
|
||||
new_offset + TEL_DVSEV_ID);
|
||||
}
|
||||
cpu_crash_version = cl_devsc_cap->devsc_data.fields.devsc_ver;
|
||||
|
||||
cl_devsc_cap->discovery_data.data = pci_read_config32(SA_DEV_TMT, new_offset
|
||||
+ TEL_DVSEV_DISCOVERY_TABLE_OFFSET);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool cpu_cl_gen_discovery_table(void)
|
||||
{
|
||||
u32 bar_addr = 0, disc_tab_addr = 0;
|
||||
bar_addr = cl_get_cpu_bar_addr();
|
||||
disc_tab_addr = bar_addr +
|
||||
cpu_cl_devsc_cap.discovery_data.fields.discovery_table_offset;
|
||||
memset(&cpu_cl_disc_tab, 0, sizeof(cpu_crashlog_discovery_table_t));
|
||||
|
||||
cpu_cl_disc_tab.header.data = ((u64)read32((u32 *)disc_tab_addr) +
|
||||
((u64)read32((u32 *)(disc_tab_addr + 4)) << 32));
|
||||
|
||||
cpu_cl_disc_tab.cmd_mailbox.data = read32((u32 *)(disc_tab_addr + 8));
|
||||
cpu_cl_disc_tab.mailbox_data = read32((u32 *)(disc_tab_addr + 12));
|
||||
|
||||
printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer count: 0x%x\n",
|
||||
cpu_cl_disc_tab.header.fields.count);
|
||||
|
||||
if (cpu_cl_disc_tab.header.fields.guid != CPU_CRASHLOG_DISC_TAB_GUID_VALID) {
|
||||
printk(BIOS_ERR, "Invalid CPU crashlog discovery table GUID, expected = 0x%X ,"
|
||||
"actual = 0x%X\n", CPU_CRASHLOG_DISC_TAB_GUID_VALID,
|
||||
cpu_cl_disc_tab.header.fields.guid);
|
||||
return false;
|
||||
}
|
||||
|
||||
int cur_offset = 0;
|
||||
for (int i = 0; i < cpu_cl_disc_tab.header.fields.count ; i++) {
|
||||
cur_offset = 16 + 8*i;
|
||||
cpu_cl_disc_tab.buffers[i].data = ((u64)read32((u32 *)(disc_tab_addr +
|
||||
cur_offset)) + ((u64)read32((u32 *)
|
||||
(disc_tab_addr + cur_offset + 4)) << 32));
|
||||
printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer: 0x%x size:"
|
||||
"0x%x offset: 0x%x\n", i, cpu_cl_disc_tab.buffers[i].fields.size,
|
||||
cpu_cl_disc_tab.buffers[i].fields.offset);
|
||||
m_cpu_crashLog_size += cpu_cl_disc_tab.buffers[i].fields.size * sizeof(u32);
|
||||
}
|
||||
|
||||
m_cpu_crashLog_present = m_cpu_crashLog_size > 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cpu_cl_discovery(void)
|
||||
{
|
||||
memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
|
||||
|
||||
if (!cpu_cl_get_capability(&cpu_cl_devsc_cap)) {
|
||||
printk(BIOS_ERR, "CPU crashlog capability not found.\n");
|
||||
m_cpu_crashLog_support = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_cpu_crashLog_support = true;
|
||||
|
||||
/* Program BAR address and enable command register memory space decoding */
|
||||
u32 tmp_bar_addr = PCH_PWRM_BASE_ADDRESS;
|
||||
printk(BIOS_DEBUG, "tmp_bar_addr: 0x%X\n", tmp_bar_addr);
|
||||
|
||||
if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR0) {
|
||||
pci_write_config32(SA_DEV_TMT, TEL_CFG_BAR0, tmp_bar_addr);
|
||||
} else if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR1) {
|
||||
pci_write_config32(SA_DEV_TMT, TEL_CFG_BAR1, tmp_bar_addr);
|
||||
} else {
|
||||
printk(BIOS_DEBUG, "invalid discovery data t_bir_q: 0x%x\n",
|
||||
cpu_cl_devsc_cap.discovery_data.fields.t_bir_q);
|
||||
return false;
|
||||
}
|
||||
pci_or_config16(SA_DEV_TMT, PCI_COMMAND, PCI_COMMAND_MEMORY);
|
||||
|
||||
if (!cpu_cl_gen_discovery_table()) {
|
||||
printk(BIOS_ERR, "CPU crashlog discovery table not valid.\n");
|
||||
m_cpu_crashLog_present = false;
|
||||
return false;
|
||||
}
|
||||
m_cpu_crashLog_present = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void reset_discovery_buffers(void)
|
||||
{
|
||||
memset(&discovery_buf, 0, sizeof(pmc_ipc_discovery_buf_t));
|
||||
memset(&descriptor_table, 0, sizeof(pmc_crashlog_desc_table_t));
|
||||
memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
|
||||
}
|
||||
|
||||
|
||||
int cl_get_total_data_size(void)
|
||||
{
|
||||
return m_pmc_crashLog_size + m_cpu_crashLog_size;
|
||||
}
|
||||
|
||||
|
||||
pmc_ipc_discovery_buf_t cl_get_pmc_discovery_buf(void)
|
||||
{
|
||||
return discovery_buf;
|
||||
}
|
||||
|
||||
|
||||
pmc_crashlog_desc_table_t cl_get_pmc_descriptor_table(void)
|
||||
{
|
||||
return descriptor_table;
|
||||
}
|
||||
|
||||
|
||||
int cl_get_pmc_record_size(void)
|
||||
{
|
||||
return m_pmc_crashLog_size;
|
||||
}
|
||||
|
||||
|
||||
int cl_get_cpu_record_size(void)
|
||||
{
|
||||
return m_cpu_crashLog_size;
|
||||
}
|
||||
|
||||
|
||||
bool cl_cpu_data_present(void)
|
||||
{
|
||||
return m_cpu_crashLog_present;
|
||||
}
|
||||
|
||||
|
||||
bool cl_pmc_data_present(void)
|
||||
{
|
||||
return m_pmc_crashLog_present;
|
||||
}
|
||||
|
||||
|
||||
bool cpu_crashlog_support(void)
|
||||
{
|
||||
return m_cpu_crashLog_support;
|
||||
}
|
||||
|
||||
|
||||
bool pmc_crashlog_support(void)
|
||||
{
|
||||
return m_pmc_crashLog_support;
|
||||
}
|
||||
|
||||
|
||||
void update_new_pmc_crashlog_size(u32 *pmc_crash_size)
|
||||
{
|
||||
m_pmc_crashLog_size = *pmc_crash_size;
|
||||
}
|
||||
|
||||
|
||||
cpu_crashlog_discovery_table_t cl_get_cpu_discovery_table(void)
|
||||
{
|
||||
return cpu_cl_disc_tab;
|
||||
}
|
||||
|
||||
|
||||
void update_new_cpu_crashlog_size(u32 *cpu_crash_size)
|
||||
{
|
||||
m_cpu_crashLog_size = *cpu_crash_size;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _SOC_COMMON_BLOCK_CRASHLOG_LIB_H_
|
||||
#define _SOC_COMMON_BLOCK_CRASHLIB_LIB_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
|
||||
/* DVSEC capability Registers */
|
||||
#define TEL_DVSEC_OFFSET 0x100
|
||||
#define TEL_DVSEC_PCIE_CAP_ID 0x0
|
||||
#define TEL_DVSEC_NEXT_CAP 0x2
|
||||
#define TEL_DVSEV_ID 0x8
|
||||
#define TEL_DVSEV_DISCOVERY_TABLE_OFFSET 0xC
|
||||
#define TELEMETRY_EXTENDED_CAP_ID 0x23
|
||||
#define CRASHLOG_DVSEC_ID 0x04
|
||||
#define TEL_DVSEC_TBIR_BAR0 0
|
||||
#define TEL_DVSEC_TBIR_BAR1 1
|
||||
|
||||
/* CPU CrashLog MMIO Registers */
|
||||
#define CRASHLOG_MAILBOX_INTF_ADDRESS 0x6038
|
||||
#define CRASHLOG_POINTER_SIZE_FIELD_OFFSET 0x04
|
||||
|
||||
#endif /* _SOC_COMMON_BLOCK_CRASHLOG_LIB_H_ */
|
|
@ -5,12 +5,15 @@
|
|||
|
||||
#include <device/pci_def.h>
|
||||
|
||||
#define _SA_DEVFN(slot) PCI_DEVFN(SA_DEV_SLOT_ ## slot, 0)
|
||||
#define _PCH_DEVFN(slot, func) PCI_DEVFN(PCH_DEV_SLOT_ ## slot, func)
|
||||
|
||||
#if !defined(__SIMPLE_DEVICE__)
|
||||
#include <device/device.h>
|
||||
#define _SA_DEV(slot) pcidev_path_on_root(_SA_DEVFN(slot))
|
||||
#define _PCH_DEV(slot, func) pcidev_path_on_root_debug(_PCH_DEVFN(slot, func), __func__)
|
||||
#else
|
||||
#define _SA_DEV(slot) PCI_DEV(0, SA_DEV_SLOT_ ## slot, 0)
|
||||
#define _PCH_DEV(slot, func) PCI_DEV(0, PCH_DEV_SLOT_ ## slot, func)
|
||||
#endif
|
||||
|
||||
|
@ -49,6 +52,10 @@
|
|||
#define SA_DEV_TBT2 PCI_DEV(0, SA_DEV_SLOT_TBT, 2)
|
||||
#define SA_DEV_TBT3 PCI_DEV(0, SA_DEV_SLOT_TBT, 3)
|
||||
|
||||
#define SA_DEV_SLOT_TMT 0x0A
|
||||
#define SA_DEVFN_TMT _SA_DEVFN(TMT)
|
||||
#define SA_DEV_TMT _SA_DEV(TMT)
|
||||
|
||||
#define SA_DEV_SLOT_TCSS 0x0d
|
||||
#define NUM_TCSS_DMA_FUNCTIONS 2
|
||||
#define SA_DEVFN_TCSS_DMA(x) PCI_DEVFN(SA_DEV_SLOT_TCSS, ((x) + 2))
|
||||
|
|
|
@ -215,6 +215,12 @@ static void soc_memory_init_params(FSP_M_CONFIG *m_cfg,
|
|||
|
||||
/* Change TmeEnable UPD value according to INTEL_TME Kconfig */
|
||||
m_cfg->TmeEnable = CONFIG(INTEL_TME);
|
||||
|
||||
/* crashLog config */
|
||||
if (CONFIG(SOC_INTEL_CRASHLOG)) {
|
||||
m_cfg->CpuCrashLogDevice = 1;
|
||||
m_cfg->CpuCrashLogEnable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)
|
||||
|
|
|
@ -72,9 +72,11 @@ typedef struct {
|
|||
**/
|
||||
UINT8 EnableAbove4GBMmio;
|
||||
|
||||
/** Offset 0x004B - Reserved
|
||||
/** Offset 0x004B - Enable/Disable CrashLog Device 10
|
||||
Enable(Default): Enable CPU CrashLog Device 10, Disable: Disable CPU CrashLog
|
||||
$EN_DIS
|
||||
**/
|
||||
UINT8 Reserved0;
|
||||
UINT8 CpuCrashLogDevice;
|
||||
|
||||
/** Offset 0x004C - MemorySpdPtr00
|
||||
**/
|
||||
|
|
Loading…
Reference in New Issue