[PATCH 075/109] drm/amd/ras: add rascore BERT record walker
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: Xiang Liu <[email protected]> Add a rascore BERT record walker that validates cached BERT generic status blocks and iterates their CPER section descriptors. The generic APEI BERT path may have already consumed the boot error region and cleared block_status before AMDGPU caches the payload, so do not use block_status to decide whether cached records should be parsed. Section-specific parsers can be added separately on top of this walker. Reviewed-by: Hawking Zhang <[email protected]> Signed-off-by: Xiang Liu <[email protected]> Signed-off-by: Alex Deucher <[email protected]> --- drivers/gpu/drm/amd/ras/core/Makefile | 1 + drivers/gpu/drm/amd/ras/core/ras.h | 3 + drivers/gpu/drm/amd/ras/core/ras_bert.c | 78 +++++++++++++++++++++++ drivers/gpu/drm/amd/ras/ras_mgr/ras_sys.h | 4 ++ 4 files changed, 86 insertions(+) create mode 100644 drivers/gpu/drm/amd/ras/core/ras_bert.c diff --git a/drivers/gpu/drm/amd/ras/core/Makefile b/drivers/gpu/drm/amd/ras/core/Makefile index def5fbb2a49e6..b2872affbf719 100644 --- a/drivers/gpu/drm/amd/ras/core/Makefile +++ b/drivers/gpu/drm/amd/ras/core/Makefile @@ -38,6 +38,7 @@ RAS_CORE_FILES = core.o \ ras_nbio.o \ ras_nbio_v7_9.o \ log_ring.o \ + ras_bert.o \ ras_cper.o \ ras_psp.o \ ras_psp_v13_0.o \ diff --git a/drivers/gpu/drm/amd/ras/core/ras.h b/drivers/gpu/drm/amd/ras/core/ras.h index 9c830b803e834..168766d449ce7 100644 --- a/drivers/gpu/drm/amd/ras/core/ras.h +++ b/drivers/gpu/drm/amd/ras/core/ras.h @@ -475,4 +475,7 @@ bool ras_core_poison_supported(struct ras_core_context *ras_core); bool ras_core_in_early_init(struct ras_core_context *ras_core); bool ras_core_early_init_service_enabled(struct ras_core_context *ras_core); int ras_core_eeprom_early_init_service(struct ras_core_context *ras_core); +#if defined(CONFIG_X86_MCE_AMD) && defined(CONFIG_ACPI_APEI) +int ras_bert_process_records(struct ras_core_context *ras_core, const void *bert, u32 bert_len); +#endif #endif diff --git a/drivers/gpu/drm/amd/ras/core/ras_bert.c b/drivers/gpu/drm/amd/ras/core/ras_bert.c new file mode 100644 index 0000000000000..5d11b7d0d0c08 --- /dev/null +++ b/drivers/gpu/drm/amd/ras/core/ras_bert.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "ras.h" + +#if defined(CONFIG_X86_MCE_AMD) && defined(CONFIG_ACPI_APEI) +int ras_bert_process_records(struct ras_core_context *ras_core, + const void *bert, u32 bert_len) +{ + struct acpi_hest_generic_status *estatus; + struct acpi_hest_generic_data *gdata; + u32 estatus_len; + int remain; + + if (!ras_core || !bert || bert_len < sizeof(struct acpi_hest_generic_status)) + return -EINVAL; + + estatus = (struct acpi_hest_generic_status *)bert; + remain = bert_len; + + while (remain >= sizeof(struct acpi_hest_generic_status)) { + estatus_len = estatus->raw_data_length ? + estatus->raw_data_offset + estatus->raw_data_length : + sizeof(*estatus) + estatus->data_length; + if (remain < estatus_len) { + RAS_DEV_ERR(ras_core->dev, "truncated status block (length: %u).\n", + estatus_len); + return -EINVAL; + } + if (!estatus_len) + return -EINVAL; + + /* + * The generic APEI BERT path may have already consumed the boot + * error region and cleared block_status. AMDGPU still needs to + * parse the cached BERT payload, so do not use block_status to + * decide whether this status block contains records. + */ + if (cper_estatus_check(estatus)) { + RAS_DEV_ERR(ras_core->dev, "invalid error record.\n"); + return -EINVAL; + } + + gdata = (struct acpi_hest_generic_data *)(estatus + 1); + while ((void *)gdata - (void *)(estatus + 1) < estatus->data_length) { + RAS_DEV_INFO(ras_core->dev, "unknown section: %pUl\n", + gdata->section_type); + + gdata = acpi_hest_get_next(gdata); + } + estatus = (struct acpi_hest_generic_status *)((u8 *)estatus + estatus_len); + remain -= estatus_len; + } + + return 0; +} +#endif diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/ras_sys.h b/drivers/gpu/drm/amd/ras/ras_mgr/ras_sys.h index 2775c7bf41b7e..351864a1dd40d 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/ras_sys.h +++ b/drivers/gpu/drm/amd/ras/ras_mgr/ras_sys.h @@ -28,6 +28,10 @@ #include <linux/printk.h> #include <linux/dev_printk.h> #include <linux/mempool.h> +#if defined(CONFIG_X86_MCE_AMD) && defined(CONFIG_ACPI_APEI) +#include <linux/cper.h> +#include <acpi/ghes.h> +#endif #include "amdgpu.h" /* inject address is 52 bits */ -- 2.55.0