mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20200514' into staging
target-arm queue: * target/arm: Use correct GDB XML for M-profile cores * target/arm: Code cleanup to use gvec APIs better * aspeed: Add support for the sonorapass-bmc board * target/arm: Support reporting KVM host memory errors to the guest via ACPI notifications * target/arm: Finish conversion of Neon 3-reg-same insns to decodetree # gpg: Signature made Thu 14 May 2020 15:19:15 BST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20200514: (45 commits) target/arm: Convert NEON VFMA, VFMS 3-reg-same insns to decodetree target/arm: Convert Neon fp VMAX/VMIN/VMAXNM/VMINNM/VRECPS/VRSQRTS to decodetree target/arm: Move 'env' argument of recps_f32 and rsqrts_f32 helpers to usual place target/arm: Convert Neon 3-reg-same compare insns to decodetree target/arm: Convert Neon fp VMUL, VMLA, VMLS 3-reg-same insns to decodetree target/arm: Convert Neon VPMIN/VPMAX/VPADD float 3-reg-same insns to decodetree target/arm: Convert Neon VADD, VSUB, VABD 3-reg-same insns to decodetree target/arm: Convert Neon VQDMULH/VQRDMULH 3-reg-same to decodetree target/arm: Convert Neon VPADD 3-reg-same insns to decodetree target/arm: Convert Neon VPMAX/VPMIN 3-reg-same insns to decodetree target/arm: Convert Neon VQSHL, VRSHL, VQRSHL 3-reg-same insns to decodetree target/arm: Convert Neon VRHADD, VHSUB 3-reg-same insns to decodetree target/arm: Convert Neon VABA/VABD 3-reg-same to decodetree target/arm: Convert Neon VHADD 3-reg-same insns target/arm: Convert Neon 64-bit element 3-reg-same insns target/arm: Convert Neon 3-reg-same SHA to decodetree target/arm: Convert Neon 3-reg-same VQRDMLAH/VQRDMLSH to decodetree MAINTAINERS: Add ACPI/HEST/GHES entries target-arm: kvm64: handle SIGBUS signal from kernel or KVM ACPI: Record Generic Error Status Block(GESB) table ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -1516,6 +1516,15 @@ F: tests/qtest/bios-tables-test.c
|
||||
F: tests/qtest/acpi-utils.[hc]
|
||||
F: tests/data/acpi/
|
||||
|
||||
ACPI/HEST/GHES
|
||||
R: Dongjiu Geng <gengdongjiu@huawei.com>
|
||||
R: Xiang Zheng <zhengxiang9@huawei.com>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/acpi/ghes.c
|
||||
F: include/hw/acpi/ghes.h
|
||||
F: docs/specs/acpi_hest_ghes.rst
|
||||
|
||||
ppc4xx
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
L: qemu-ppc@nongnu.org
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi/qapi-types-common.h"
|
||||
#include "qapi/qapi-visit-common.h"
|
||||
#include "sysemu/reset.h"
|
||||
|
||||
#include "hw/boards.h"
|
||||
|
||||
@@ -883,6 +884,39 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension)
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct HWPoisonPage {
|
||||
ram_addr_t ram_addr;
|
||||
QLIST_ENTRY(HWPoisonPage) list;
|
||||
} HWPoisonPage;
|
||||
|
||||
static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
|
||||
QLIST_HEAD_INITIALIZER(hwpoison_page_list);
|
||||
|
||||
static void kvm_unpoison_all(void *param)
|
||||
{
|
||||
HWPoisonPage *page, *next_page;
|
||||
|
||||
QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
|
||||
QLIST_REMOVE(page, list);
|
||||
qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
|
||||
g_free(page);
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_hwpoison_page_add(ram_addr_t ram_addr)
|
||||
{
|
||||
HWPoisonPage *page;
|
||||
|
||||
QLIST_FOREACH(page, &hwpoison_page_list, list) {
|
||||
if (page->ram_addr == ram_addr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
page = g_new(HWPoisonPage, 1);
|
||||
page->ram_addr = ram_addr;
|
||||
QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
|
||||
}
|
||||
|
||||
static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size)
|
||||
{
|
||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||
@@ -2085,6 +2119,8 @@ static int kvm_init(MachineState *ms)
|
||||
s->kernel_irqchip_split = mc->default_kernel_irqchip_split ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
|
||||
}
|
||||
|
||||
qemu_register_reset(kvm_unpoison_all, NULL);
|
||||
|
||||
if (s->kernel_irqchip_allowed) {
|
||||
kvm_irqchip_create(s);
|
||||
}
|
||||
|
||||
@@ -7806,14 +7806,14 @@ case "$target_name" in
|
||||
TARGET_SYSTBL_ABI=common,oabi
|
||||
bflt="yes"
|
||||
mttcg="yes"
|
||||
gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
|
||||
gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml"
|
||||
;;
|
||||
aarch64|aarch64_be)
|
||||
TARGET_ARCH=aarch64
|
||||
TARGET_BASE_ARCH=arm
|
||||
bflt="yes"
|
||||
mttcg="yes"
|
||||
gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
|
||||
gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml"
|
||||
;;
|
||||
cris)
|
||||
;;
|
||||
|
||||
@@ -42,3 +42,4 @@ CONFIG_FSL_IMX7=y
|
||||
CONFIG_FSL_IMX6UL=y
|
||||
CONFIG_SEMIHOSTING=y
|
||||
CONFIG_ALLWINNER_H3=y
|
||||
CONFIG_ACPI_APEI=y
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
APEI tables generating and CPER record
|
||||
======================================
|
||||
|
||||
..
|
||||
Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
|
||||
|
||||
This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
See the COPYING file in the top-level directory.
|
||||
|
||||
Design Details
|
||||
--------------
|
||||
|
||||
::
|
||||
|
||||
etc/acpi/tables etc/hardware_errors
|
||||
==================== ===============================
|
||||
+ +--------------------------+ +----------------------------+
|
||||
| | HEST | +--------->| error_block_address1 |------+
|
||||
| +--------------------------+ | +----------------------------+ |
|
||||
| | GHES1 | | +------->| error_block_address2 |------+-+
|
||||
| +--------------------------+ | | +----------------------------+ | |
|
||||
| | ................. | | | | .............. | | |
|
||||
| | error_status_address-----+-+ | -----------------------------+ | |
|
||||
| | ................. | | +--->| error_block_addressN |------+-+---+
|
||||
| | read_ack_register--------+-+ | | +----------------------------+ | | |
|
||||
| | read_ack_preserve | +-+---+--->| read_ack_register1 | | | |
|
||||
| | read_ack_write | | | +----------------------------+ | | |
|
||||
+ +--------------------------+ | +-+--->| read_ack_register2 | | | |
|
||||
| | GHES2 | | | | +----------------------------+ | | |
|
||||
+ +--------------------------+ | | | | ............. | | | |
|
||||
| | ................. | | | | +----------------------------+ | | |
|
||||
| | error_status_address-----+---+ | | +->| read_ack_registerN | | | |
|
||||
| | ................. | | | | +----------------------------+ | | |
|
||||
| | read_ack_register--------+-----+ | | |Generic Error Status Block 1|<-----+ | |
|
||||
| | read_ack_preserve | | | |-+------------------------+-+ | |
|
||||
| | read_ack_write | | | | | CPER | | | |
|
||||
+ +--------------------------| | | | | CPER | | | |
|
||||
| | ............... | | | | | .... | | | |
|
||||
+ +--------------------------+ | | | | CPER | | | |
|
||||
| | GHESN | | | |-+------------------------+-| | |
|
||||
+ +--------------------------+ | | |Generic Error Status Block 2|<-------+ |
|
||||
| | ................. | | | |-+------------------------+-+ |
|
||||
| | error_status_address-----+-------+ | | | CPER | | |
|
||||
| | ................. | | | | CPER | | |
|
||||
| | read_ack_register--------+---------+ | | .... | | |
|
||||
| | read_ack_preserve | | | CPER | | |
|
||||
| | read_ack_write | +-+------------------------+-+ |
|
||||
+ +--------------------------+ | .......... | |
|
||||
|----------------------------+ |
|
||||
|Generic Error Status Block N |<----------+
|
||||
|-+-------------------------+-+
|
||||
| | CPER | |
|
||||
| | CPER | |
|
||||
| | .... | |
|
||||
| | CPER | |
|
||||
+-+-------------------------+-+
|
||||
|
||||
|
||||
(1) QEMU generates the ACPI HEST table. This table goes in the current
|
||||
"etc/acpi/tables" fw_cfg blob. Each error source has different
|
||||
notification types.
|
||||
|
||||
(2) A new fw_cfg blob called "etc/hardware_errors" is introduced. QEMU
|
||||
also needs to populate this blob. The "etc/hardware_errors" fw_cfg blob
|
||||
contains an address registers table and an Error Status Data Block table.
|
||||
|
||||
(3) The address registers table contains N Error Block Address entries
|
||||
and N Read Ack Register entries. The size for each entry is 8-byte.
|
||||
The Error Status Data Block table contains N Error Status Data Block
|
||||
entries. The size for each entry is 4096(0x1000) bytes. The total size
|
||||
for the "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes.
|
||||
N is the number of the kinds of hardware error sources.
|
||||
|
||||
(4) QEMU generates the ACPI linker/loader script for the firmware. The
|
||||
firmware pre-allocates memory for "etc/acpi/tables", "etc/hardware_errors"
|
||||
and copies blob contents there.
|
||||
|
||||
(5) QEMU generates N ADD_POINTER commands, which patch addresses in the
|
||||
"error_status_address" fields of the HEST table with a pointer to the
|
||||
corresponding "address registers" in the "etc/hardware_errors" blob.
|
||||
|
||||
(6) QEMU generates N ADD_POINTER commands, which patch addresses in the
|
||||
"read_ack_register" fields of the HEST table with a pointer to the
|
||||
corresponding "read_ack_register" within the "etc/hardware_errors" blob.
|
||||
|
||||
(7) QEMU generates N ADD_POINTER commands for the firmware, which patch
|
||||
addresses in the "error_block_address" fields with a pointer to the
|
||||
respective "Error Status Data Block" in the "etc/hardware_errors" blob.
|
||||
|
||||
(8) QEMU defines a third and write-only fw_cfg blob which is called
|
||||
"etc/hardware_errors_addr". Through that blob, the firmware can send back
|
||||
the guest-side allocation addresses to QEMU. The "etc/hardware_errors_addr"
|
||||
blob contains a 8-byte entry. QEMU generates a single WRITE_POINTER command
|
||||
for the firmware. The firmware will write back the start address of
|
||||
"etc/hardware_errors" blob to the fw_cfg file "etc/hardware_errors_addr".
|
||||
|
||||
(9) When QEMU gets a SIGBUS from the kernel, QEMU writes CPER into corresponding
|
||||
"Error Status Data Block", guest memory, and then injects platform specific
|
||||
interrupt (in case of arm/virt machine it's Synchronous External Abort) as a
|
||||
notification which is necessary for notifying the guest.
|
||||
|
||||
(10) This notification (in virtual hardware) will be handled by the guest
|
||||
kernel, on receiving notification, guest APEI driver could read the CPER error
|
||||
and take appropriate action.
|
||||
|
||||
(11) kvm_arch_on_sigbus_vcpu() uses source_id as index in "etc/hardware_errors" to
|
||||
find out "Error Status Data Block" entry corresponding to error source. So supported
|
||||
source_id values should be assigned here and not be changed afterwards to make sure
|
||||
that guest will write error into expected "Error Status Data Block" even if guest was
|
||||
migrated to a newer QEMU.
|
||||
@@ -14,3 +14,4 @@ Contents:
|
||||
ppc-spapr-xive
|
||||
acpi_hw_reduced_hotplug
|
||||
tpm
|
||||
acpi_hest_ghes
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Copyright (C) 2010-2020 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. -->
|
||||
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.arm.m-profile">
|
||||
<reg name="r0" bitsize="32"/>
|
||||
<reg name="r1" bitsize="32"/>
|
||||
<reg name="r2" bitsize="32"/>
|
||||
<reg name="r3" bitsize="32"/>
|
||||
<reg name="r4" bitsize="32"/>
|
||||
<reg name="r5" bitsize="32"/>
|
||||
<reg name="r6" bitsize="32"/>
|
||||
<reg name="r7" bitsize="32"/>
|
||||
<reg name="r8" bitsize="32"/>
|
||||
<reg name="r9" bitsize="32"/>
|
||||
<reg name="r10" bitsize="32"/>
|
||||
<reg name="r11" bitsize="32"/>
|
||||
<reg name="r12" bitsize="32"/>
|
||||
<reg name="sp" bitsize="32" type="data_ptr"/>
|
||||
<reg name="lr" bitsize="32"/>
|
||||
<reg name="pc" bitsize="32" type="code_ptr"/>
|
||||
<reg name="xpsr" bitsize="32" regnum="25"/>
|
||||
</feature>
|
||||
@@ -28,6 +28,10 @@ config ACPI_HMAT
|
||||
bool
|
||||
depends on ACPI
|
||||
|
||||
config ACPI_APEI
|
||||
bool
|
||||
depends on ACPI
|
||||
|
||||
config ACPI_PCI
|
||||
bool
|
||||
depends on ACPI && PCI
|
||||
|
||||
@@ -8,6 +8,7 @@ common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
|
||||
common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
|
||||
common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o
|
||||
common-obj-$(CONFIG_ACPI_HMAT) += hmat.o
|
||||
common-obj-$(CONFIG_ACPI_APEI) += ghes.o
|
||||
common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
|
||||
common-obj-$(call lnot,$(CONFIG_PC)) += acpi-x86-stub.o
|
||||
|
||||
|
||||
@@ -1578,6 +1578,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
|
||||
tables->table_data = g_array_new(false, true /* clear */, 1);
|
||||
tables->tcpalog = g_array_new(false, true /* clear */, 1);
|
||||
tables->vmgenid = g_array_new(false, true /* clear */, 1);
|
||||
tables->hardware_errors = g_array_new(false, true /* clear */, 1);
|
||||
tables->linker = bios_linker_loader_init();
|
||||
}
|
||||
|
||||
@@ -1588,6 +1589,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
|
||||
g_array_free(tables->table_data, true);
|
||||
g_array_free(tables->tcpalog, mfre);
|
||||
g_array_free(tables->vmgenid, mfre);
|
||||
g_array_free(tables->hardware_errors, mfre);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -247,6 +247,24 @@ static const VMStateDescription vmstate_ged_state = {
|
||||
}
|
||||
};
|
||||
|
||||
static bool ghes_needed(void *opaque)
|
||||
{
|
||||
AcpiGedState *s = opaque;
|
||||
return s->ghes_state.ghes_addr_le;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_ghes_state = {
|
||||
.name = "acpi-ged/ghes",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = ghes_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT(ghes_state, AcpiGedState, 1,
|
||||
vmstate_ghes_state, AcpiGhesState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_acpi_ged = {
|
||||
.name = "acpi-ged",
|
||||
.version_id = 1,
|
||||
@@ -257,6 +275,7 @@ static const VMStateDescription vmstate_acpi_ged = {
|
||||
},
|
||||
.subsections = (const VMStateDescription * []) {
|
||||
&vmstate_memhp_state,
|
||||
&vmstate_ghes_state,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
+448
@@ -0,0 +1,448 @@
|
||||
/*
|
||||
* Support for generating APEI tables and recording CPER for Guests
|
||||
*
|
||||
* Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
|
||||
*
|
||||
* Author: Dongjiu Geng <gengdongjiu@huawei.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "hw/acpi/ghes.h"
|
||||
#include "hw/acpi/aml-build.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/acpi/generic_event_device.h"
|
||||
#include "hw/nvram/fw_cfg.h"
|
||||
#include "qemu/uuid.h"
|
||||
|
||||
#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
|
||||
#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
|
||||
|
||||
/* The max size in bytes for one error block */
|
||||
#define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB)
|
||||
|
||||
/* Now only support ARMv8 SEA notification type error source */
|
||||
#define ACPI_GHES_ERROR_SOURCE_COUNT 1
|
||||
|
||||
/* Generic Hardware Error Source version 2 */
|
||||
#define ACPI_GHES_SOURCE_GENERIC_ERROR_V2 10
|
||||
|
||||
/* Address offset in Generic Address Structure(GAS) */
|
||||
#define GAS_ADDR_OFFSET 4
|
||||
|
||||
/*
|
||||
* The total size of Generic Error Data Entry
|
||||
* ACPI 6.1/6.2: 18.3.2.7.1 Generic Error Data,
|
||||
* Table 18-343 Generic Error Data Entry
|
||||
*/
|
||||
#define ACPI_GHES_DATA_LENGTH 72
|
||||
|
||||
/* The memory section CPER size, UEFI 2.6: N.2.5 Memory Error Section */
|
||||
#define ACPI_GHES_MEM_CPER_LENGTH 80
|
||||
|
||||
/* Masks for block_status flags */
|
||||
#define ACPI_GEBS_UNCORRECTABLE 1
|
||||
|
||||
/*
|
||||
* Total size for Generic Error Status Block except Generic Error Data Entries
|
||||
* ACPI 6.2: 18.3.2.7.1 Generic Error Data,
|
||||
* Table 18-380 Generic Error Status Block
|
||||
*/
|
||||
#define ACPI_GHES_GESB_SIZE 20
|
||||
|
||||
/*
|
||||
* Values for error_severity field
|
||||
*/
|
||||
enum AcpiGenericErrorSeverity {
|
||||
ACPI_CPER_SEV_RECOVERABLE = 0,
|
||||
ACPI_CPER_SEV_FATAL = 1,
|
||||
ACPI_CPER_SEV_CORRECTED = 2,
|
||||
ACPI_CPER_SEV_NONE = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* Hardware Error Notification
|
||||
* ACPI 4.0: 17.3.2.7 Hardware Error Notification
|
||||
* Composes dummy Hardware Error Notification descriptor of specified type
|
||||
*/
|
||||
static void build_ghes_hw_error_notification(GArray *table, const uint8_t type)
|
||||
{
|
||||
/* Type */
|
||||
build_append_int_noprefix(table, type, 1);
|
||||
/*
|
||||
* Length:
|
||||
* Total length of the structure in bytes
|
||||
*/
|
||||
build_append_int_noprefix(table, 28, 1);
|
||||
/* Configuration Write Enable */
|
||||
build_append_int_noprefix(table, 0, 2);
|
||||
/* Poll Interval */
|
||||
build_append_int_noprefix(table, 0, 4);
|
||||
/* Vector */
|
||||
build_append_int_noprefix(table, 0, 4);
|
||||
/* Switch To Polling Threshold Value */
|
||||
build_append_int_noprefix(table, 0, 4);
|
||||
/* Switch To Polling Threshold Window */
|
||||
build_append_int_noprefix(table, 0, 4);
|
||||
/* Error Threshold Value */
|
||||
build_append_int_noprefix(table, 0, 4);
|
||||
/* Error Threshold Window */
|
||||
build_append_int_noprefix(table, 0, 4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic Error Data Entry
|
||||
* ACPI 6.1: 18.3.2.7.1 Generic Error Data
|
||||
*/
|
||||
static void acpi_ghes_generic_error_data(GArray *table,
|
||||
const uint8_t *section_type, uint32_t error_severity,
|
||||
uint8_t validation_bits, uint8_t flags,
|
||||
uint32_t error_data_length, QemuUUID fru_id,
|
||||
uint64_t time_stamp)
|
||||
{
|
||||
const uint8_t fru_text[20] = {0};
|
||||
|
||||
/* Section Type */
|
||||
g_array_append_vals(table, section_type, 16);
|
||||
|
||||
/* Error Severity */
|
||||
build_append_int_noprefix(table, error_severity, 4);
|
||||
/* Revision */
|
||||
build_append_int_noprefix(table, 0x300, 2);
|
||||
/* Validation Bits */
|
||||
build_append_int_noprefix(table, validation_bits, 1);
|
||||
/* Flags */
|
||||
build_append_int_noprefix(table, flags, 1);
|
||||
/* Error Data Length */
|
||||
build_append_int_noprefix(table, error_data_length, 4);
|
||||
|
||||
/* FRU Id */
|
||||
g_array_append_vals(table, fru_id.data, ARRAY_SIZE(fru_id.data));
|
||||
|
||||
/* FRU Text */
|
||||
g_array_append_vals(table, fru_text, sizeof(fru_text));
|
||||
|
||||
/* Timestamp */
|
||||
build_append_int_noprefix(table, time_stamp, 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic Error Status Block
|
||||
* ACPI 6.1: 18.3.2.7.1 Generic Error Data
|
||||
*/
|
||||
static void acpi_ghes_generic_error_status(GArray *table, uint32_t block_status,
|
||||
uint32_t raw_data_offset, uint32_t raw_data_length,
|
||||
uint32_t data_length, uint32_t error_severity)
|
||||
{
|
||||
/* Block Status */
|
||||
build_append_int_noprefix(table, block_status, 4);
|
||||
/* Raw Data Offset */
|
||||
build_append_int_noprefix(table, raw_data_offset, 4);
|
||||
/* Raw Data Length */
|
||||
build_append_int_noprefix(table, raw_data_length, 4);
|
||||
/* Data Length */
|
||||
build_append_int_noprefix(table, data_length, 4);
|
||||
/* Error Severity */
|
||||
build_append_int_noprefix(table, error_severity, 4);
|
||||
}
|
||||
|
||||
/* UEFI 2.6: N.2.5 Memory Error Section */
|
||||
static void acpi_ghes_build_append_mem_cper(GArray *table,
|
||||
uint64_t error_physical_addr)
|
||||
{
|
||||
/*
|
||||
* Memory Error Record
|
||||
*/
|
||||
|
||||
/* Validation Bits */
|
||||
build_append_int_noprefix(table,
|
||||
(1ULL << 14) | /* Type Valid */
|
||||
(1ULL << 1) /* Physical Address Valid */,
|
||||
8);
|
||||
/* Error Status */
|
||||
build_append_int_noprefix(table, 0, 8);
|
||||
/* Physical Address */
|
||||
build_append_int_noprefix(table, error_physical_addr, 8);
|
||||
/* Skip all the detailed information normally found in such a record */
|
||||
build_append_int_noprefix(table, 0, 48);
|
||||
/* Memory Error Type */
|
||||
build_append_int_noprefix(table, 0 /* Unknown error */, 1);
|
||||
/* Skip all the detailed information normally found in such a record */
|
||||
build_append_int_noprefix(table, 0, 7);
|
||||
}
|
||||
|
||||
static int acpi_ghes_record_mem_error(uint64_t error_block_address,
|
||||
uint64_t error_physical_addr)
|
||||
{
|
||||
GArray *block;
|
||||
|
||||
/* Memory Error Section Type */
|
||||
const uint8_t uefi_cper_mem_sec[] =
|
||||
UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
|
||||
0xED, 0x7C, 0x83, 0xB1);
|
||||
|
||||
/* invalid fru id: ACPI 4.0: 17.3.2.6.1 Generic Error Data,
|
||||
* Table 17-13 Generic Error Data Entry
|
||||
*/
|
||||
QemuUUID fru_id = {};
|
||||
uint32_t data_length;
|
||||
|
||||
block = g_array_new(false, true /* clear */, 1);
|
||||
|
||||
/* This is the length if adding a new generic error data entry*/
|
||||
data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH;
|
||||
|
||||
/*
|
||||
* Check whether it will run out of the preallocated memory if adding a new
|
||||
* generic error data entry
|
||||
*/
|
||||
if ((data_length + ACPI_GHES_GESB_SIZE) > ACPI_GHES_MAX_RAW_DATA_LENGTH) {
|
||||
error_report("Not enough memory to record new CPER!!!");
|
||||
g_array_free(block, true);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Build the new generic error status block header */
|
||||
acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE,
|
||||
0, 0, data_length, ACPI_CPER_SEV_RECOVERABLE);
|
||||
|
||||
/* Build this new generic error data entry header */
|
||||
acpi_ghes_generic_error_data(block, uefi_cper_mem_sec,
|
||||
ACPI_CPER_SEV_RECOVERABLE, 0, 0,
|
||||
ACPI_GHES_MEM_CPER_LENGTH, fru_id, 0);
|
||||
|
||||
/* Build the memory section CPER for above new generic error data entry */
|
||||
acpi_ghes_build_append_mem_cper(block, error_physical_addr);
|
||||
|
||||
/* Write the generic error data entry into guest memory */
|
||||
cpu_physical_memory_write(error_block_address, block->data, block->len);
|
||||
|
||||
g_array_free(block, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build table for the hardware error fw_cfg blob.
|
||||
* Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
|
||||
* See docs/specs/acpi_hest_ghes.rst for blobs format.
|
||||
*/
|
||||
void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
|
||||
{
|
||||
int i, error_status_block_offset;
|
||||
|
||||
/* Build error_block_address */
|
||||
for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
|
||||
build_append_int_noprefix(hardware_errors, 0, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
/* Build read_ack_register */
|
||||
for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
|
||||
/*
|
||||
* Initialize the value of read_ack_register to 1, so GHES can be
|
||||
* writeable after (re)boot.
|
||||
* ACPI 6.2: 18.3.2.8 Generic Hardware Error Source version 2
|
||||
* (GHESv2 - Type 10)
|
||||
*/
|
||||
build_append_int_noprefix(hardware_errors, 1, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
/* Generic Error Status Block offset in the hardware error fw_cfg blob */
|
||||
error_status_block_offset = hardware_errors->len;
|
||||
|
||||
/* Reserve space for Error Status Data Block */
|
||||
acpi_data_push(hardware_errors,
|
||||
ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_GHES_ERROR_SOURCE_COUNT);
|
||||
|
||||
/* Tell guest firmware to place hardware_errors blob into RAM */
|
||||
bios_linker_loader_alloc(linker, ACPI_GHES_ERRORS_FW_CFG_FILE,
|
||||
hardware_errors, sizeof(uint64_t), false);
|
||||
|
||||
for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
|
||||
/*
|
||||
* Tell firmware to patch error_block_address entries to point to
|
||||
* corresponding "Generic Error Status Block"
|
||||
*/
|
||||
bios_linker_loader_add_pointer(linker,
|
||||
ACPI_GHES_ERRORS_FW_CFG_FILE, sizeof(uint64_t) * i,
|
||||
sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE,
|
||||
error_status_block_offset + i * ACPI_GHES_MAX_RAW_DATA_LENGTH);
|
||||
}
|
||||
|
||||
/*
|
||||
* tell firmware to write hardware_errors GPA into
|
||||
* hardware_errors_addr fw_cfg, once the former has been initialized.
|
||||
*/
|
||||
bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE,
|
||||
0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0);
|
||||
}
|
||||
|
||||
/* Build Generic Hardware Error Source version 2 (GHESv2) */
|
||||
static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
|
||||
{
|
||||
uint64_t address_offset;
|
||||
/*
|
||||
* Type:
|
||||
* Generic Hardware Error Source version 2(GHESv2 - Type 10)
|
||||
*/
|
||||
build_append_int_noprefix(table_data, ACPI_GHES_SOURCE_GENERIC_ERROR_V2, 2);
|
||||
/* Source Id */
|
||||
build_append_int_noprefix(table_data, source_id, 2);
|
||||
/* Related Source Id */
|
||||
build_append_int_noprefix(table_data, 0xffff, 2);
|
||||
/* Flags */
|
||||
build_append_int_noprefix(table_data, 0, 1);
|
||||
/* Enabled */
|
||||
build_append_int_noprefix(table_data, 1, 1);
|
||||
|
||||
/* Number of Records To Pre-allocate */
|
||||
build_append_int_noprefix(table_data, 1, 4);
|
||||
/* Max Sections Per Record */
|
||||
build_append_int_noprefix(table_data, 1, 4);
|
||||
/* Max Raw Data Length */
|
||||
build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4);
|
||||
|
||||
address_offset = table_data->len;
|
||||
/* Error Status Address */
|
||||
build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0,
|
||||
4 /* QWord access */, 0);
|
||||
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
|
||||
address_offset + GAS_ADDR_OFFSET, sizeof(uint64_t),
|
||||
ACPI_GHES_ERRORS_FW_CFG_FILE, source_id * sizeof(uint64_t));
|
||||
|
||||
switch (source_id) {
|
||||
case ACPI_HEST_SRC_ID_SEA:
|
||||
/*
|
||||
* Notification Structure
|
||||
* Now only enable ARMv8 SEA notification type
|
||||
*/
|
||||
build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_SEA);
|
||||
break;
|
||||
default:
|
||||
error_report("Not support this error source");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Error Status Block Length */
|
||||
build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4);
|
||||
|
||||
/*
|
||||
* Read Ack Register
|
||||
* ACPI 6.1: 18.3.2.8 Generic Hardware Error Source
|
||||
* version 2 (GHESv2 - Type 10)
|
||||
*/
|
||||
address_offset = table_data->len;
|
||||
build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0,
|
||||
4 /* QWord access */, 0);
|
||||
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
|
||||
address_offset + GAS_ADDR_OFFSET,
|
||||
sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE,
|
||||
(ACPI_GHES_ERROR_SOURCE_COUNT + source_id) * sizeof(uint64_t));
|
||||
|
||||
/*
|
||||
* Read Ack Preserve field
|
||||
* We only provide the first bit in Read Ack Register to OSPM to write
|
||||
* while the other bits are preserved.
|
||||
*/
|
||||
build_append_int_noprefix(table_data, ~0x1ULL, 8);
|
||||
/* Read Ack Write */
|
||||
build_append_int_noprefix(table_data, 0x1, 8);
|
||||
}
|
||||
|
||||
/* Build Hardware Error Source Table */
|
||||
void acpi_build_hest(GArray *table_data, BIOSLinker *linker)
|
||||
{
|
||||
uint64_t hest_start = table_data->len;
|
||||
|
||||
/* Hardware Error Source Table header*/
|
||||
acpi_data_push(table_data, sizeof(AcpiTableHeader));
|
||||
|
||||
/* Error Source Count */
|
||||
build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4);
|
||||
|
||||
build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker);
|
||||
|
||||
build_header(linker, table_data, (void *)(table_data->data + hest_start),
|
||||
"HEST", table_data->len - hest_start, 1, NULL, NULL);
|
||||
}
|
||||
|
||||
void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
|
||||
GArray *hardware_error)
|
||||
{
|
||||
/* Create a read-only fw_cfg file for GHES */
|
||||
fw_cfg_add_file(s, ACPI_GHES_ERRORS_FW_CFG_FILE, hardware_error->data,
|
||||
hardware_error->len);
|
||||
|
||||
/* Create a read-write fw_cfg file for Address */
|
||||
fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
|
||||
NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
|
||||
}
|
||||
|
||||
int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
|
||||
{
|
||||
uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0;
|
||||
uint64_t start_addr;
|
||||
bool ret = -1;
|
||||
AcpiGedState *acpi_ged_state;
|
||||
AcpiGhesState *ags;
|
||||
|
||||
assert(source_id < ACPI_HEST_SRC_ID_RESERVED);
|
||||
|
||||
acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
|
||||
NULL));
|
||||
g_assert(acpi_ged_state);
|
||||
ags = &acpi_ged_state->ghes_state;
|
||||
|
||||
start_addr = le64_to_cpu(ags->ghes_addr_le);
|
||||
|
||||
if (physical_address) {
|
||||
|
||||
if (source_id < ACPI_HEST_SRC_ID_RESERVED) {
|
||||
start_addr += source_id * sizeof(uint64_t);
|
||||
}
|
||||
|
||||
cpu_physical_memory_read(start_addr, &error_block_addr,
|
||||
sizeof(error_block_addr));
|
||||
|
||||
error_block_addr = le64_to_cpu(error_block_addr);
|
||||
|
||||
read_ack_register_addr = start_addr +
|
||||
ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t);
|
||||
|
||||
cpu_physical_memory_read(read_ack_register_addr,
|
||||
&read_ack_register, sizeof(read_ack_register));
|
||||
|
||||
/* zero means OSPM does not acknowledge the error */
|
||||
if (!read_ack_register) {
|
||||
error_report("OSPM does not acknowledge previous error,"
|
||||
" so can not record CPER for current error anymore");
|
||||
} else if (error_block_addr) {
|
||||
read_ack_register = cpu_to_le64(0);
|
||||
/*
|
||||
* Clear the Read Ack Register, OSPM will write it to 1 when
|
||||
* it acknowledges this error.
|
||||
*/
|
||||
cpu_physical_memory_write(read_ack_register_addr,
|
||||
&read_ack_register, sizeof(uint64_t));
|
||||
|
||||
ret = acpi_ghes_record_mem_error(error_block_addr,
|
||||
physical_address);
|
||||
} else
|
||||
error_report("can not find Generic Error Status Block");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
+3
-7
@@ -27,6 +27,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/uuid.h"
|
||||
#include "hw/acpi/acpi.h"
|
||||
#include "hw/acpi/aml-build.h"
|
||||
#include "hw/acpi/bios-linker-loader.h"
|
||||
@@ -34,18 +35,13 @@
|
||||
#include "hw/mem/nvdimm.h"
|
||||
#include "qemu/nvdimm-utils.h"
|
||||
|
||||
#define NVDIMM_UUID_LE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
|
||||
{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
|
||||
(b) & 0xff, ((b) >> 8) & 0xff, (c) & 0xff, ((c) >> 8) & 0xff, \
|
||||
(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }
|
||||
|
||||
/*
|
||||
* define Byte Addressable Persistent Memory (PM) Region according to
|
||||
* ACPI 6.0: 5.2.25.1 System Physical Address Range Structure.
|
||||
*/
|
||||
static const uint8_t nvdimm_nfit_spa_uuid[] =
|
||||
NVDIMM_UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
|
||||
0x18, 0xb7, 0x8c, 0xdb);
|
||||
UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
|
||||
0x18, 0xb7, 0x8c, 0xdb);
|
||||
|
||||
/*
|
||||
* NVDIMM Firmware Interface Table
|
||||
|
||||
@@ -73,6 +73,21 @@ struct AspeedBoardState {
|
||||
SCU_AST2500_HW_STRAP_ACPI_ENABLE | \
|
||||
SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
|
||||
|
||||
/* Sonorapass hardware value: 0xF100D216 */
|
||||
#define SONORAPASS_BMC_HW_STRAP1 ( \
|
||||
SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \
|
||||
SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \
|
||||
SCU_AST2500_HW_STRAP_UART_DEBUG | \
|
||||
SCU_AST2500_HW_STRAP_RESERVED28 | \
|
||||
SCU_AST2500_HW_STRAP_DDR4_ENABLE | \
|
||||
SCU_HW_STRAP_VGA_CLASS_CODE | \
|
||||
SCU_HW_STRAP_LPC_RESET_PIN | \
|
||||
SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER) | \
|
||||
SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(AXI_AHB_RATIO_2_1) | \
|
||||
SCU_HW_STRAP_VGA_BIOS_ROM | \
|
||||
SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
|
||||
SCU_AST2500_HW_STRAP_RESERVED1)
|
||||
|
||||
/* Swift hardware value: 0xF11AD206 */
|
||||
#define SWIFT_BMC_HW_STRAP1 ( \
|
||||
AST2500_HW_STRAP1_DEFAULTS | \
|
||||
@@ -437,6 +452,50 @@ static void swift_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 12), "tmp105", 0x4a);
|
||||
}
|
||||
|
||||
static void sonorapass_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
|
||||
/* bus 2 : */
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x48);
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x49);
|
||||
/* bus 2 : pca9546 @ 0x73 */
|
||||
|
||||
/* bus 3 : pca9548 @ 0x70 */
|
||||
|
||||
/* bus 4 : */
|
||||
uint8_t *eeprom4_54 = g_malloc0(8 * 1024);
|
||||
smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), 0x54,
|
||||
eeprom4_54);
|
||||
/* PCA9539 @ 0x76, but PCA9552 is compatible */
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x76);
|
||||
/* PCA9539 @ 0x77, but PCA9552 is compatible */
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x77);
|
||||
|
||||
/* bus 6 : */
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x48);
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x49);
|
||||
/* bus 6 : pca9546 @ 0x73 */
|
||||
|
||||
/* bus 8 : */
|
||||
uint8_t *eeprom8_56 = g_malloc0(8 * 1024);
|
||||
smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), 0x56,
|
||||
eeprom8_56);
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x60);
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x61);
|
||||
/* bus 8 : adc128d818 @ 0x1d */
|
||||
/* bus 8 : adc128d818 @ 0x1f */
|
||||
|
||||
/*
|
||||
* bus 13 : pca9548 @ 0x71
|
||||
* - channel 3:
|
||||
* - tmm421 @ 0x4c
|
||||
* - tmp421 @ 0x4e
|
||||
* - tmp421 @ 0x4f
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
@@ -549,6 +608,21 @@ static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
|
||||
mc->default_ram_size = 512 * MiB;
|
||||
};
|
||||
|
||||
static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
|
||||
|
||||
mc->desc = "OCP SonoraPass BMC (ARM1176)";
|
||||
amc->soc_name = "ast2500-a1";
|
||||
amc->hw_strap1 = SONORAPASS_BMC_HW_STRAP1;
|
||||
amc->fmc_model = "mx66l1g45g";
|
||||
amc->spi_model = "mx66l1g45g";
|
||||
amc->num_cs = 2;
|
||||
amc->i2c_init = sonorapass_bmc_i2c_init;
|
||||
mc->default_ram_size = 512 * MiB;
|
||||
};
|
||||
|
||||
static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
@@ -628,6 +702,10 @@ static const TypeInfo aspeed_machine_types[] = {
|
||||
.name = MACHINE_TYPE_NAME("swift-bmc"),
|
||||
.parent = TYPE_ASPEED_MACHINE,
|
||||
.class_init = aspeed_machine_swift_class_init,
|
||||
}, {
|
||||
.name = MACHINE_TYPE_NAME("sonorapass-bmc"),
|
||||
.parent = TYPE_ASPEED_MACHINE,
|
||||
.class_init = aspeed_machine_sonorapass_class_init,
|
||||
}, {
|
||||
.name = MACHINE_TYPE_NAME("witherspoon-bmc"),
|
||||
.parent = TYPE_ASPEED_MACHINE,
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "sysemu/reset.h"
|
||||
#include "kvm_arm.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/acpi/ghes.h"
|
||||
|
||||
#define ARM_SPI_BASE 32
|
||||
|
||||
@@ -818,6 +819,12 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_spcr(tables_blob, tables->linker, vms);
|
||||
|
||||
if (vms->ras) {
|
||||
build_ghes_error_table(tables->hardware_errors, tables->linker);
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
acpi_build_hest(tables_blob, tables->linker);
|
||||
}
|
||||
|
||||
if (ms->numa_state->num_nodes > 0) {
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_srat(tables_blob, tables->linker, vms);
|
||||
@@ -910,6 +917,7 @@ void virt_acpi_setup(VirtMachineState *vms)
|
||||
{
|
||||
AcpiBuildTables tables;
|
||||
AcpiBuildState *build_state;
|
||||
AcpiGedState *acpi_ged_state;
|
||||
|
||||
if (!vms->fw_cfg) {
|
||||
trace_virt_acpi_setup();
|
||||
@@ -940,6 +948,13 @@ void virt_acpi_setup(VirtMachineState *vms)
|
||||
fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
|
||||
acpi_data_len(tables.tcpalog));
|
||||
|
||||
if (vms->ras) {
|
||||
assert(vms->acpi_dev);
|
||||
acpi_ged_state = ACPI_GED(vms->acpi_dev);
|
||||
acpi_ghes_add_fw_cfg(&acpi_ged_state->ghes_state,
|
||||
vms->fw_cfg, tables.hardware_errors);
|
||||
}
|
||||
|
||||
build_state->rsdp_mr = acpi_add_rom_blob(virt_acpi_build_update,
|
||||
build_state, tables.rsdp,
|
||||
ACPI_BUILD_RSDP_FILE, 0);
|
||||
|
||||
@@ -1995,6 +1995,20 @@ static void virt_set_acpi(Object *obj, Visitor *v, const char *name,
|
||||
visit_type_OnOffAuto(v, name, &vms->acpi, errp);
|
||||
}
|
||||
|
||||
static bool virt_get_ras(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
|
||||
return vms->ras;
|
||||
}
|
||||
|
||||
static void virt_set_ras(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
|
||||
vms->ras = value;
|
||||
}
|
||||
|
||||
static char *virt_get_gic_version(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
@@ -2327,6 +2341,15 @@ static void virt_instance_init(Object *obj)
|
||||
"Valid values are none and smmuv3",
|
||||
NULL);
|
||||
|
||||
/* Default disallows RAS instantiation */
|
||||
vms->ras = false;
|
||||
object_property_add_bool(obj, "ras", virt_get_ras,
|
||||
virt_set_ras, NULL);
|
||||
object_property_set_description(obj, "ras",
|
||||
"Set on/off to enable/disable reporting host memory errors "
|
||||
"to a KVM guest using ACPI and guest external abort exceptions",
|
||||
NULL);
|
||||
|
||||
vms->irqmap = a15irqmap;
|
||||
|
||||
virt_flash_create(vms);
|
||||
|
||||
@@ -220,6 +220,7 @@ struct AcpiBuildTables {
|
||||
GArray *rsdp;
|
||||
GArray *tcpalog;
|
||||
GArray *vmgenid;
|
||||
GArray *hardware_errors;
|
||||
BIOSLinker *linker;
|
||||
} AcpiBuildTables;
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/acpi/memory_hotplug.h"
|
||||
#include "hw/acpi/ghes.h"
|
||||
|
||||
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
|
||||
|
||||
@@ -96,6 +97,7 @@ typedef struct AcpiGedState {
|
||||
GEDState ged_state;
|
||||
uint32_t ged_event_bitmap;
|
||||
qemu_irq irq;
|
||||
AcpiGhesState ghes_state;
|
||||
} AcpiGedState;
|
||||
|
||||
void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev,
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Support for generating APEI tables and recording CPER for Guests
|
||||
*
|
||||
* Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
|
||||
*
|
||||
* Author: Dongjiu Geng <gengdongjiu@huawei.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ACPI_GHES_H
|
||||
#define ACPI_GHES_H
|
||||
|
||||
#include "hw/acpi/bios-linker-loader.h"
|
||||
|
||||
/*
|
||||
* Values for Hardware Error Notification Type field
|
||||
*/
|
||||
enum AcpiGhesNotifyType {
|
||||
/* Polled */
|
||||
ACPI_GHES_NOTIFY_POLLED = 0,
|
||||
/* External Interrupt */
|
||||
ACPI_GHES_NOTIFY_EXTERNAL = 1,
|
||||
/* Local Interrupt */
|
||||
ACPI_GHES_NOTIFY_LOCAL = 2,
|
||||
/* SCI */
|
||||
ACPI_GHES_NOTIFY_SCI = 3,
|
||||
/* NMI */
|
||||
ACPI_GHES_NOTIFY_NMI = 4,
|
||||
/* CMCI, ACPI 5.0: 18.3.2.7, Table 18-290 */
|
||||
ACPI_GHES_NOTIFY_CMCI = 5,
|
||||
/* MCE, ACPI 5.0: 18.3.2.7, Table 18-290 */
|
||||
ACPI_GHES_NOTIFY_MCE = 6,
|
||||
/* GPIO-Signal, ACPI 6.0: 18.3.2.7, Table 18-332 */
|
||||
ACPI_GHES_NOTIFY_GPIO = 7,
|
||||
/* ARMv8 SEA, ACPI 6.1: 18.3.2.9, Table 18-345 */
|
||||
ACPI_GHES_NOTIFY_SEA = 8,
|
||||
/* ARMv8 SEI, ACPI 6.1: 18.3.2.9, Table 18-345 */
|
||||
ACPI_GHES_NOTIFY_SEI = 9,
|
||||
/* External Interrupt - GSIV, ACPI 6.1: 18.3.2.9, Table 18-345 */
|
||||
ACPI_GHES_NOTIFY_GSIV = 10,
|
||||
/* Software Delegated Exception, ACPI 6.2: 18.3.2.9, Table 18-383 */
|
||||
ACPI_GHES_NOTIFY_SDEI = 11,
|
||||
/* 12 and greater are reserved */
|
||||
ACPI_GHES_NOTIFY_RESERVED = 12
|
||||
};
|
||||
|
||||
enum {
|
||||
ACPI_HEST_SRC_ID_SEA = 0,
|
||||
/* future ids go here */
|
||||
ACPI_HEST_SRC_ID_RESERVED,
|
||||
};
|
||||
|
||||
typedef struct AcpiGhesState {
|
||||
uint64_t ghes_addr_le;
|
||||
} AcpiGhesState;
|
||||
|
||||
void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
|
||||
void acpi_build_hest(GArray *table_data, BIOSLinker *linker);
|
||||
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
|
||||
GArray *hardware_errors);
|
||||
int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
|
||||
#endif
|
||||
@@ -132,6 +132,7 @@ typedef struct {
|
||||
bool highmem_ecam;
|
||||
bool its;
|
||||
bool virt;
|
||||
bool ras;
|
||||
OnOffAuto acpi;
|
||||
VirtGICType gic_version;
|
||||
VirtIOMMUType iommu;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user