1*aa16508fSDongjiu Geng /* 2*aa16508fSDongjiu Geng * Support for generating APEI tables and recording CPER for Guests 3*aa16508fSDongjiu Geng * 4*aa16508fSDongjiu Geng * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD. 5*aa16508fSDongjiu Geng * 6*aa16508fSDongjiu Geng * Author: Dongjiu Geng <gengdongjiu@huawei.com> 7*aa16508fSDongjiu Geng * 8*aa16508fSDongjiu Geng * This program is free software; you can redistribute it and/or modify 9*aa16508fSDongjiu Geng * it under the terms of the GNU General Public License as published by 10*aa16508fSDongjiu Geng * the Free Software Foundation; either version 2 of the License, or 11*aa16508fSDongjiu Geng * (at your option) any later version. 12*aa16508fSDongjiu Geng 13*aa16508fSDongjiu Geng * This program is distributed in the hope that it will be useful, 14*aa16508fSDongjiu Geng * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*aa16508fSDongjiu Geng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*aa16508fSDongjiu Geng * GNU General Public License for more details. 17*aa16508fSDongjiu Geng 18*aa16508fSDongjiu Geng * You should have received a copy of the GNU General Public License along 19*aa16508fSDongjiu Geng * with this program; if not, see <http://www.gnu.org/licenses/>. 20*aa16508fSDongjiu Geng */ 21*aa16508fSDongjiu Geng 22*aa16508fSDongjiu Geng #include "qemu/osdep.h" 23*aa16508fSDongjiu Geng #include "qemu/units.h" 24*aa16508fSDongjiu Geng #include "hw/acpi/ghes.h" 25*aa16508fSDongjiu Geng #include "hw/acpi/aml-build.h" 26*aa16508fSDongjiu Geng 27*aa16508fSDongjiu Geng #define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors" 28*aa16508fSDongjiu Geng #define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr" 29*aa16508fSDongjiu Geng 30*aa16508fSDongjiu Geng /* The max size in bytes for one error block */ 31*aa16508fSDongjiu Geng #define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB) 32*aa16508fSDongjiu Geng 33*aa16508fSDongjiu Geng /* Now only support ARMv8 SEA notification type error source */ 34*aa16508fSDongjiu Geng #define ACPI_GHES_ERROR_SOURCE_COUNT 1 35*aa16508fSDongjiu Geng 36*aa16508fSDongjiu Geng /* 37*aa16508fSDongjiu Geng * Build table for the hardware error fw_cfg blob. 38*aa16508fSDongjiu Geng * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs. 39*aa16508fSDongjiu Geng * See docs/specs/acpi_hest_ghes.rst for blobs format. 40*aa16508fSDongjiu Geng */ 41*aa16508fSDongjiu Geng void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) 42*aa16508fSDongjiu Geng { 43*aa16508fSDongjiu Geng int i, error_status_block_offset; 44*aa16508fSDongjiu Geng 45*aa16508fSDongjiu Geng /* Build error_block_address */ 46*aa16508fSDongjiu Geng for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) { 47*aa16508fSDongjiu Geng build_append_int_noprefix(hardware_errors, 0, sizeof(uint64_t)); 48*aa16508fSDongjiu Geng } 49*aa16508fSDongjiu Geng 50*aa16508fSDongjiu Geng /* Build read_ack_register */ 51*aa16508fSDongjiu Geng for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) { 52*aa16508fSDongjiu Geng /* 53*aa16508fSDongjiu Geng * Initialize the value of read_ack_register to 1, so GHES can be 54*aa16508fSDongjiu Geng * writeable after (re)boot. 55*aa16508fSDongjiu Geng * ACPI 6.2: 18.3.2.8 Generic Hardware Error Source version 2 56*aa16508fSDongjiu Geng * (GHESv2 - Type 10) 57*aa16508fSDongjiu Geng */ 58*aa16508fSDongjiu Geng build_append_int_noprefix(hardware_errors, 1, sizeof(uint64_t)); 59*aa16508fSDongjiu Geng } 60*aa16508fSDongjiu Geng 61*aa16508fSDongjiu Geng /* Generic Error Status Block offset in the hardware error fw_cfg blob */ 62*aa16508fSDongjiu Geng error_status_block_offset = hardware_errors->len; 63*aa16508fSDongjiu Geng 64*aa16508fSDongjiu Geng /* Reserve space for Error Status Data Block */ 65*aa16508fSDongjiu Geng acpi_data_push(hardware_errors, 66*aa16508fSDongjiu Geng ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_GHES_ERROR_SOURCE_COUNT); 67*aa16508fSDongjiu Geng 68*aa16508fSDongjiu Geng /* Tell guest firmware to place hardware_errors blob into RAM */ 69*aa16508fSDongjiu Geng bios_linker_loader_alloc(linker, ACPI_GHES_ERRORS_FW_CFG_FILE, 70*aa16508fSDongjiu Geng hardware_errors, sizeof(uint64_t), false); 71*aa16508fSDongjiu Geng 72*aa16508fSDongjiu Geng for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) { 73*aa16508fSDongjiu Geng /* 74*aa16508fSDongjiu Geng * Tell firmware to patch error_block_address entries to point to 75*aa16508fSDongjiu Geng * corresponding "Generic Error Status Block" 76*aa16508fSDongjiu Geng */ 77*aa16508fSDongjiu Geng bios_linker_loader_add_pointer(linker, 78*aa16508fSDongjiu Geng ACPI_GHES_ERRORS_FW_CFG_FILE, sizeof(uint64_t) * i, 79*aa16508fSDongjiu Geng sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 80*aa16508fSDongjiu Geng error_status_block_offset + i * ACPI_GHES_MAX_RAW_DATA_LENGTH); 81*aa16508fSDongjiu Geng } 82*aa16508fSDongjiu Geng 83*aa16508fSDongjiu Geng /* 84*aa16508fSDongjiu Geng * tell firmware to write hardware_errors GPA into 85*aa16508fSDongjiu Geng * hardware_errors_addr fw_cfg, once the former has been initialized. 86*aa16508fSDongjiu Geng */ 87*aa16508fSDongjiu Geng bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, 88*aa16508fSDongjiu Geng 0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0); 89*aa16508fSDongjiu Geng } 90