acpi: Move most of HEST ACPI table to common code
This moves most of the vendor and architecture independent code into common ACPI code. Change-Id: I7dca939612a5f3d8d6a148fa67bf0ce891952584 Signed-off-by: Maximilian Brune <maximilian.brune@9elements.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/88034 Reviewed-by: Anand Vaikar <a.vaikar2021@gmail.com> Reviewed-by: Jérémy Compostella <jeremy.compostella@intel.com> Reviewed-by: Shuo Liu <shuo.liu@intel.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
ce1ced7f6a
commit
4431848ee6
15 changed files with 113 additions and 167 deletions
|
|
@ -127,3 +127,16 @@ config ACPI_WDAT_WDT
|
|||
help
|
||||
Selected by platforms that support and fill ACPI Watchdog Action Table
|
||||
(WDAT).
|
||||
|
||||
config ACPI_HEST
|
||||
bool
|
||||
depends on HAVE_ACPI_TABLES
|
||||
help
|
||||
Selected by platforms that support and fill ACPI Hardware Error Source Table (HEST)
|
||||
|
||||
config ACPI_HEST_ERROR_LOG_BUFFER_SIZE
|
||||
hex
|
||||
default 0x4000
|
||||
depends on ACPI_HEST
|
||||
help
|
||||
Define the size of the HEST ACPI error log buffer
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
*/
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acpi_apei.h>
|
||||
#include <acpi/acpi_gnvs.h>
|
||||
#include <acpi/acpi_iort.h>
|
||||
#include <acpi/acpi_ivrs.h>
|
||||
#include <acpi/acpigen.h>
|
||||
|
|
@ -1062,20 +1064,32 @@ unsigned long acpi_create_hest_error_source(acpi_hest_t *hest,
|
|||
}
|
||||
|
||||
/* ACPI 4.0 */
|
||||
void acpi_write_hest(acpi_hest_t *hest,
|
||||
unsigned long (*acpi_fill_hest)(acpi_hest_t *hest))
|
||||
static void acpi_create_hest(acpi_header_t *header, void *unused)
|
||||
{
|
||||
acpi_header_t *header = &(hest->header);
|
||||
if (!CONFIG(ACPI_HEST))
|
||||
return;
|
||||
|
||||
/* Reserve memory for Enhanced error logging */
|
||||
void *log_mem = cbmem_add(CBMEM_ID_ACPI_HEST, CONFIG_ACPI_HEST_ERROR_LOG_BUFFER_SIZE);
|
||||
if (!log_mem) {
|
||||
printk(BIOS_ERR, "Unable to allocate HEST memory\n");
|
||||
return;
|
||||
}
|
||||
printk(BIOS_DEBUG, "HEST elog_addr: %p, size:%d\n", log_mem,
|
||||
CONFIG_ACPI_HEST_ERROR_LOG_BUFFER_SIZE);
|
||||
|
||||
acpi_hest_t *hest = (acpi_hest_t *)header;
|
||||
uintptr_t current = (uintptr_t)(hest + 1);
|
||||
|
||||
memset(hest, 0, sizeof(acpi_hest_t));
|
||||
|
||||
if (acpi_fill_header(header, "HEST", HEST, sizeof(acpi_hest_t)) != CB_SUCCESS)
|
||||
return;
|
||||
|
||||
acpi_fill_hest(hest);
|
||||
current = acpi_soc_fill_hest(hest, current, log_mem);
|
||||
|
||||
/* Calculate checksums. */
|
||||
header->checksum = acpi_checksum((void *)hest, header->length);
|
||||
/* (Re)calculate length. */
|
||||
header->length = current - (uintptr_t)hest;
|
||||
}
|
||||
|
||||
/* ACPI 3.0b */
|
||||
|
|
@ -1456,6 +1470,7 @@ unsigned long write_acpi_tables(const unsigned long start)
|
|||
{ acpi_create_tpm2, NULL, sizeof(acpi_tpm2_t) },
|
||||
{ acpi_create_lpit, NULL, sizeof(acpi_lpit_t) },
|
||||
{ acpi_create_madt, NULL, sizeof(acpi_header_t) },
|
||||
{ acpi_create_hest, NULL, sizeof(acpi_hest_t) },
|
||||
{ acpi_create_bert, NULL, sizeof(acpi_bert_t) },
|
||||
{ acpi_create_spcr, NULL, sizeof(acpi_spcr_t) },
|
||||
{ acpi_create_gtdt, NULL, sizeof(acpi_gtdt_t) },
|
||||
|
|
|
|||
|
|
@ -1879,11 +1879,9 @@ unsigned long acpi_create_dmar_ds_ioapic_from_hw(unsigned long current,
|
|||
unsigned long acpi_create_dmar_ds_msi_hpet(unsigned long current,
|
||||
u8 enumeration_id,
|
||||
u8 bus, u8 dev, u8 fn);
|
||||
void acpi_write_hest(acpi_hest_t *hest,
|
||||
unsigned long (*acpi_fill_hest)(acpi_hest_t *hest));
|
||||
|
||||
unsigned long acpi_create_hest_error_source(acpi_hest_t *hest,
|
||||
acpi_hest_esd_t *esd, u16 type, void *data, u16 len);
|
||||
unsigned long acpi_create_hest_error_source(acpi_hest_t *hest, acpi_hest_esd_t *esd, u16 type,
|
||||
void *data, u16 len);
|
||||
|
||||
unsigned long acpi_create_lpi_desc_ncst(acpi_lpi_desc_ncst_t *lpi_desc, uint16_t uid);
|
||||
|
||||
|
|
|
|||
36
src/include/acpi/acpi_apei.h
Normal file
36
src/include/acpi/acpi_apei.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
/*
|
||||
* Contains ACPI Platform Error Interfaces (APEI) definitions and declarations.
|
||||
* These are mostly used by:
|
||||
* - BERT (Boot Error Record Table) ACPI Table.
|
||||
* - HEST (Hardware Error Source Table) ACPI Table.
|
||||
*/
|
||||
|
||||
#ifndef _ACPI_APEI_H_
|
||||
#define _ACPI_APEI_H_
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
|
||||
/* Generic Hardware Error Source Descriptor */
|
||||
typedef struct acpi_ghes_esd {
|
||||
u16 type;
|
||||
u16 source_id;
|
||||
u16 related_src_id;
|
||||
u8 flags;
|
||||
u8 enabled;
|
||||
u32 prealloc_erecords;
|
||||
u32 max_section_per_record;
|
||||
} __packed acpi_ghes_esd_t;
|
||||
|
||||
typedef struct ghes_record {
|
||||
acpi_ghes_esd_t esd;
|
||||
u32 max_raw_data_length;
|
||||
acpi_addr64_t sts_addr;
|
||||
acpi_hest_hen_t notify;
|
||||
u32 err_sts_blk_len;
|
||||
} __packed ghes_record_t;
|
||||
|
||||
uintptr_t acpi_soc_fill_hest(acpi_hest_t *hest, uintptr_t current, void *log_mem);
|
||||
|
||||
#endif
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
config NORTHBRIDGE_AMD_PI_00730F01
|
||||
bool
|
||||
select DRAM_SUPPORT_DDR3
|
||||
select ACPI_HEST
|
||||
|
||||
if NORTHBRIDGE_AMD_PI_00730F01
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <acpi/acpi_apei.h>
|
||||
#include <commonlib/helpers.h>
|
||||
#include <console/console.h>
|
||||
#include <device/pci_ops.h>
|
||||
|
|
@ -91,22 +92,19 @@ static void northbridge_init(struct device *dev)
|
|||
register_new_ioapic(IO_APIC2_ADDR);
|
||||
}
|
||||
|
||||
static unsigned long acpi_fill_hest(acpi_hest_t *hest)
|
||||
uintptr_t acpi_soc_fill_hest(acpi_hest_t *hest, uintptr_t current, void *log_mem)
|
||||
{
|
||||
void *addr, *current;
|
||||
|
||||
/* Skip the HEST header. */
|
||||
current = (void *)(hest + 1);
|
||||
void *addr;
|
||||
|
||||
addr = agesawrapper_getlateinitptr(PICK_WHEA_MCE);
|
||||
if (addr != NULL)
|
||||
current += acpi_create_hest_error_source(hest, current, 0, (void *)((u32)addr + 2), *(UINT16 *)addr - 2);
|
||||
current += acpi_create_hest_error_source(hest, (acpi_hest_esd_t *)current, 0, (void *)((u32)addr + 2), *(UINT16 *)addr - 2);
|
||||
|
||||
addr = agesawrapper_getlateinitptr(PICK_WHEA_CMC);
|
||||
if (addr != NULL)
|
||||
current += acpi_create_hest_error_source(hest, current, 1, (void *)((u32)addr + 2), *(UINT16 *)addr - 2);
|
||||
current += acpi_create_hest_error_source(hest, (acpi_hest_esd_t *)current, 1, (void *)((u32)addr + 2), *(UINT16 *)addr - 2);
|
||||
|
||||
return (unsigned long)current;
|
||||
return current;
|
||||
}
|
||||
|
||||
static unsigned long acpi_fill_ivrs_ioapic(acpi_ivrs_t *ivrs, unsigned long current)
|
||||
|
|
@ -430,12 +428,6 @@ static unsigned long agesa_write_acpi_tables(const struct device *device,
|
|||
acpi_header_t *alib;
|
||||
acpi_ivrs_t *ivrs;
|
||||
|
||||
/* HEST */
|
||||
current = ALIGN_UP(current, 8);
|
||||
acpi_write_hest((void *)current, acpi_fill_hest);
|
||||
acpi_add_table(rsdp, (void *)current);
|
||||
current += ((acpi_header_t *)current)->length;
|
||||
|
||||
/* IVRS */
|
||||
if (is_dev_enabled(DEV_PTR(iommu))) {
|
||||
current = ALIGN_UP(current, 8);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
config SOC_AMD_STONEYRIDGE
|
||||
bool
|
||||
select ACPI_SOC_NVS
|
||||
select ACPI_HEST
|
||||
select ARCH_X86
|
||||
select BOOT_DEVICE_SUPPORTS_WRITES if BOOT_DEVICE_SPI_FLASH
|
||||
select COLLECT_TIMESTAMPS_NO_TSC
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <acpi/acpi_apei.h>
|
||||
#include <assert.h>
|
||||
#include <amdblocks/acpi.h>
|
||||
#include <amdblocks/biosram.h>
|
||||
|
|
@ -102,24 +103,21 @@ static void acpi_fill_root_complex_tom(const struct device *device)
|
|||
acpigen_pop_len();
|
||||
}
|
||||
|
||||
static unsigned long acpi_fill_hest(acpi_hest_t *hest)
|
||||
uintptr_t acpi_soc_fill_hest(acpi_hest_t *hest, uintptr_t current, void *log_mem)
|
||||
{
|
||||
void *addr, *current;
|
||||
|
||||
/* Skip the HEST header. */
|
||||
current = (void *)(hest + 1);
|
||||
void *addr;
|
||||
|
||||
addr = agesawrapper_getlateinitptr(PICK_WHEA_MCE);
|
||||
if (addr != NULL)
|
||||
current += acpi_create_hest_error_source(hest, current, 0,
|
||||
current += acpi_create_hest_error_source(hest, (acpi_hest_esd_t *)current, 0,
|
||||
(void *)((u32)addr + 2), *(uint16_t *)addr - 2);
|
||||
|
||||
addr = agesawrapper_getlateinitptr(PICK_WHEA_CMC);
|
||||
if (addr != NULL)
|
||||
current += acpi_create_hest_error_source(hest, current, 1,
|
||||
current += acpi_create_hest_error_source(hest, (acpi_hest_esd_t *)current, 1,
|
||||
(void *)((u32)addr + 2), *(uint16_t *)addr - 2);
|
||||
|
||||
return (unsigned long)current;
|
||||
return current;
|
||||
}
|
||||
|
||||
unsigned long soc_acpi_write_tables(const struct device *device, unsigned long current,
|
||||
|
|
@ -129,14 +127,6 @@ unsigned long soc_acpi_write_tables(const struct device *device, unsigned long c
|
|||
acpi_slit_t *slit;
|
||||
acpi_header_t *alib;
|
||||
acpi_header_t *ivrs;
|
||||
acpi_hest_t *hest;
|
||||
|
||||
/* HEST */
|
||||
current = acpi_align_current(current);
|
||||
hest = (acpi_hest_t *)current;
|
||||
acpi_write_hest(hest, acpi_fill_hest);
|
||||
acpi_add_table(rsdp, (void *)current);
|
||||
current += hest->header.length;
|
||||
|
||||
current = acpi_align_current(current);
|
||||
printk(BIOS_DEBUG, "ACPI: * IVRS at %lx\n", current);
|
||||
|
|
|
|||
|
|
@ -108,8 +108,7 @@ config HPET_MIN_TICKS
|
|||
|
||||
config SOC_INTEL_XEON_RAS
|
||||
bool
|
||||
select SOC_ACPI_HEST
|
||||
select SOC_RAS_ELOG
|
||||
select ACPI_HEST
|
||||
|
||||
config HAVE_IOAT_DOMAINS
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef _HEST_H_
|
||||
#define _HEST_H_
|
||||
#include <acpi/acpi.h>
|
||||
|
||||
#define MCE_ERR_POLL_MS_INTERVAL 1000
|
||||
#define HEST_PCIE_RP_AER_DESC_TYPE 6
|
||||
#define HEST_GHES_DESC_TYPE 9
|
||||
#define GHES_MAX_RAW_DATA_LENGTH (((CONFIG_ERROR_LOG_BUFFER_SIZE) >> 1) - 8)
|
||||
#define GHEST_ERROR_STATUS_BLOCK_LENGTH ((CONFIG_ERROR_LOG_BUFFER_SIZE) >> 1)
|
||||
#define GHEST_ASSIST (1 << 2)
|
||||
#define FIRMWARE_FIRST (1 << 0)
|
||||
#define MEM_VALID_BITS 0x66ff
|
||||
#define PCIE_VALID_BITS 0xef
|
||||
#define QWORD_ACCESS 4
|
||||
#define NOTIFY_TYPE_SCI 3
|
||||
|
||||
/* Generic Error Source Descriptor */
|
||||
typedef struct acpi_ghes_esd {
|
||||
u16 type;
|
||||
u16 source_id;
|
||||
u16 related_src_id;
|
||||
u8 flags;
|
||||
u8 enabled;
|
||||
u32 prealloc_erecords;
|
||||
u32 max_section_per_record;
|
||||
} __packed acpi_ghes_esd_t;
|
||||
|
||||
typedef struct ghes_record {
|
||||
acpi_ghes_esd_t esd;
|
||||
u32 max_raw_data_length;
|
||||
acpi_addr64_t sts_addr;
|
||||
acpi_hest_hen_t notify;
|
||||
u32 err_sts_blk_len;
|
||||
} __packed ghes_record_t;
|
||||
|
||||
unsigned long hest_create(unsigned long current, struct acpi_rsdp *rsdp);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
config SOC_ACPI_HEST
|
||||
def_bool n
|
||||
depends on HAVE_ACPI_TABLES
|
||||
help
|
||||
This variable provides control for ACPI hardware error source table (HEST)
|
||||
|
||||
config SOC_RAS_ELOG
|
||||
def_bool n
|
||||
depends on SOC_ACPI_HEST
|
||||
help
|
||||
This variable provides enhanced error logging support used with HEST
|
||||
|
||||
config ERROR_LOG_BUFFER_SIZE
|
||||
hex
|
||||
default 0x4000
|
||||
depends on SOC_RAS_ELOG
|
||||
help
|
||||
This variable allows a configurable error log based on system requirements
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
## SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
ramstage-$(CONFIG_SOC_ACPI_HEST) += hest.c
|
||||
ramstage-$(CONFIG_ACPI_HEST) += hest.c
|
||||
|
|
|
|||
|
|
@ -1,29 +1,25 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <soc/acpi.h>
|
||||
#include <acpi/acpi_apei.h>
|
||||
#include <acpi/acpi_gnvs.h>
|
||||
#include <cbmem.h>
|
||||
#include <console/console.h>
|
||||
#include <soc/hest.h>
|
||||
#include <intelblocks/nvs.h>
|
||||
#include <soc/acpi.h>
|
||||
|
||||
static u64 hest_get_elog_addr(void)
|
||||
{
|
||||
/* The elog address comes from reserved memory */
|
||||
struct global_nvs *gnvs;
|
||||
gnvs = acpi_get_gnvs();
|
||||
if (!gnvs) {
|
||||
printk(BIOS_ERR, "Unable to get gnvs\n");
|
||||
return 0;
|
||||
}
|
||||
#define MCE_ERR_POLL_MS_INTERVAL 1000
|
||||
#define HEST_PCIE_RP_AER_DESC_TYPE 6
|
||||
#define HEST_GHES_DESC_TYPE 9
|
||||
#define GHES_MAX_RAW_DATA_LENGTH (((CONFIG_ACPI_HEST_ERROR_LOG_BUFFER_SIZE) >> 1) - 8)
|
||||
#define GHEST_ERROR_STATUS_BLOCK_LENGTH ((CONFIG_ACPI_HEST_ERROR_LOG_BUFFER_SIZE) >> 1)
|
||||
#define GHEST_ASSIST (1 << 2)
|
||||
#define FIRMWARE_FIRST (1 << 0)
|
||||
#define MEM_VALID_BITS 0x66ff
|
||||
#define PCIE_VALID_BITS 0xef
|
||||
#define QWORD_ACCESS 4
|
||||
#define NOTIFY_TYPE_SCI 3
|
||||
|
||||
/* Runtime logging address */
|
||||
printk(BIOS_DEBUG, "\t status blk start addr = %llx\n", gnvs->hest_log_addr);
|
||||
printk(BIOS_DEBUG, "\t size = %x\n", CONFIG_ERROR_LOG_BUFFER_SIZE);
|
||||
return gnvs->hest_log_addr;
|
||||
}
|
||||
|
||||
static u32 acpi_hest_add_ghes(void *current)
|
||||
static u32 acpi_hest_add_ghes(uintptr_t current, uintptr_t log_mem)
|
||||
{
|
||||
ghes_record_t *rec = (ghes_record_t *)current;
|
||||
u32 size = sizeof(ghes_record_t);
|
||||
|
|
@ -50,51 +46,22 @@ static u32 acpi_hest_add_ghes(void *current)
|
|||
rec->err_sts_blk_len = GHEST_ERROR_STATUS_BLOCK_LENGTH;
|
||||
|
||||
/* error status block entries start address */
|
||||
if (CONFIG(SOC_ACPI_HEST))
|
||||
rec->sts_addr.addr = hest_get_elog_addr();
|
||||
rec->sts_addr.addr = log_mem;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static unsigned long acpi_fill_hest(acpi_hest_t *hest)
|
||||
uintptr_t acpi_soc_fill_hest(acpi_hest_t *hest, uintptr_t current, void *log_mem)
|
||||
{
|
||||
acpi_header_t *header = &(hest->header);
|
||||
void *current;
|
||||
current = (void *)(hest);
|
||||
void *next = current;
|
||||
next = hest + 1;
|
||||
next += acpi_hest_add_ghes(next);
|
||||
// fill ACPI global non volatile storage with hest elog addr
|
||||
struct global_nvs *gnvs = acpi_get_gnvs();
|
||||
if (gnvs)
|
||||
gnvs->hest_log_addr = (uintptr_t)log_mem;
|
||||
else
|
||||
printk(BIOS_ERR, "ACPI fill HEST: Unable to get gnvs\n");
|
||||
|
||||
current = acpi_hest_add_ghes(current, (uintptr_t)log_mem); // add first entry
|
||||
hest->error_source_count += 1;
|
||||
header->length = next - current;
|
||||
return header->length;
|
||||
}
|
||||
|
||||
unsigned long hest_create(unsigned long current, struct acpi_rsdp *rsdp)
|
||||
{
|
||||
struct global_nvs *gnvs;
|
||||
acpi_hest_t *hest;
|
||||
|
||||
/* Reserve memory for Enhanced error logging */
|
||||
void *mem = cbmem_add(CBMEM_ID_ACPI_HEST, CONFIG_ERROR_LOG_BUFFER_SIZE);
|
||||
if (!mem) {
|
||||
printk(BIOS_ERR, "Unable to allocate HEST memory\n");
|
||||
return current;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "HEST memory created: %p\n", mem);
|
||||
gnvs = acpi_get_gnvs();
|
||||
if (!gnvs) {
|
||||
printk(BIOS_ERR, "Unable to get gnvs\n");
|
||||
return current;
|
||||
}
|
||||
gnvs->hest_log_addr = (uintptr_t)mem;
|
||||
printk(BIOS_DEBUG, "elog_addr: %llx, size:%x\n", gnvs->hest_log_addr,
|
||||
CONFIG_ERROR_LOG_BUFFER_SIZE);
|
||||
|
||||
current = ALIGN_UP(current, 8);
|
||||
hest = (acpi_hest_t *)current;
|
||||
acpi_write_hest(hest, acpi_fill_hest);
|
||||
acpi_add_table(rsdp, (void *)current);
|
||||
current += hest->header.length;
|
||||
return current;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Scope (\_SB)
|
|||
#include "iiostack.asl"
|
||||
#undef SOCKET
|
||||
|
||||
#if CONFIG(SOC_ACPI_HEST)
|
||||
#if CONFIG(ACPI_HEST)
|
||||
Method (_OSC, 4, NotSerialized)
|
||||
{
|
||||
CreateDWordField (Arg3, 0x00, CDW1)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#include <device/pci_ops.h>
|
||||
#include <soc/acpi.h>
|
||||
#include <soc/chip_common.h>
|
||||
#include <soc/hest.h>
|
||||
#include <soc/iomap.h>
|
||||
#include <soc/numa.h>
|
||||
#include <soc/pci_devs.h>
|
||||
|
|
@ -633,10 +632,5 @@ unsigned long northbridge_write_acpi_tables(const struct device *device, unsigne
|
|||
}
|
||||
}
|
||||
|
||||
if (CONFIG(SOC_ACPI_HEST)) {
|
||||
printk(BIOS_DEBUG, "ACPI: * HEST at %lx\n", current);
|
||||
current = hest_create(current, rsdp);
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue