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