xref: /openbmc/qemu/hw/acpi/ghes.c (revision aa16508f1d1bce2411fdbe82aa20e559bbd90e48)
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