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