mirror of https://gitee.com/openkylin/qemu.git
virtio,pc: features, cleanups, fixes
Part of ACPI ERST support fixes, cleanups Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQFCBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmH/lpgPHG1zdEByZWRo YXQuY29tAAoJECgfDbjSjVRpntwH+LTJ3MIX5tHL2FWR9vfQoIOQms4A2YJb5GFv f/wZMQ4Hx/4k3KsicJF4ONJ04cT4IuxtsY9WtUroNcpuh9qy+cMYw61xsd7oa2DB k7vInrVaDP1pKmNzK+R1DV4VsbghAZzCh23hKKS8HGOd+DM6PWSozzCSpbQGerNX H61bS7lvESLONhHIJdmo5/d4aGEGlt5xs2KzZe/pwl8OU4/WRYK8MgEKOhvAZT7T Ups0IDSAOJ5pqzXCLESKFfImNIzak16+lnY9iOMcIFWQVEphMvjkn9jtCu4wvDRe 500GC8i9Q8X3B/D5Y9TB78mDuiqfQP69zBRfhSjgQeU9+eWCxA== =JIT5 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging virtio,pc: features, cleanups, fixes Part of ACPI ERST support fixes, cleanups Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Sun 06 Feb 2022 09:36:24 GMT # gpg: using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469 # gpg: issuer "mst@redhat.com" # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full] # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full] # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67 # Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469 * remotes/mst/tags/for_upstream: (24 commits) util/oslib-posix: Fix missing unlock in the error path of os_mem_prealloc() ACPI ERST: step 6 of bios-tables-test.c ACPI ERST: bios-tables-test testcase ACPI ERST: qtest for ERST ACPI ERST: create ACPI ERST table for pc/x86 machines ACPI ERST: build the ACPI ERST table ACPI ERST: support for ACPI ERST feature ACPI ERST: header file for ERST ACPI ERST: PCI device_id for ERST ACPI ERST: bios-tables-test.c steps 1 and 2 libvhost-user: Map shared RAM with MAP_NORESERVE to support virtio-mem with hugetlb libvhost-user: handle removal of identical regions libvhost-user: prevent over-running max RAM slots libvhost-user: fix VHOST_USER_REM_MEM_REG not closing the fd libvhost-user: Simplify VHOST_USER_REM_MEM_REG libvhost-user: Add vu_add_mem_reg input validation libvhost-user: Add vu_rem_mem_reg input validation tests: acpi: test short OEM_ID/OEM_TABLE_ID values in test_oem_fields() tests: acpi: update expected blobs acpi: fix OEM ID/OEM Table ID padding ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
0d564a3e32
|
@ -2768,7 +2768,7 @@ cat > $TMPC << EOF
|
|||
#include <cpuid.h>
|
||||
int main(void) {
|
||||
unsigned a, b, c, d;
|
||||
int max = __get_cpuid_max(0, 0);
|
||||
unsigned max = __get_cpuid_max(0, 0);
|
||||
|
||||
if (max >= 1) {
|
||||
__cpuid(1, a, b, c, d);
|
||||
|
|
|
@ -10,6 +10,7 @@ config ACPI_X86
|
|||
select ACPI_HMAT
|
||||
select ACPI_PIIX4
|
||||
select ACPI_PCIHP
|
||||
select ACPI_ERST
|
||||
|
||||
config ACPI_X86_ICH
|
||||
bool
|
||||
|
@ -60,3 +61,8 @@ config ACPI_HW_REDUCED
|
|||
select ACPI
|
||||
select ACPI_MEMORY_HOTPLUG
|
||||
select ACPI_NVDIMM
|
||||
|
||||
config ACPI_ERST
|
||||
bool
|
||||
default y
|
||||
depends on ACPI && PCI
|
||||
|
|
|
@ -1724,9 +1724,9 @@ void acpi_table_begin(AcpiTable *desc, GArray *array)
|
|||
build_append_int_noprefix(array, 0, 4); /* Length */
|
||||
build_append_int_noprefix(array, desc->rev, 1); /* Revision */
|
||||
build_append_int_noprefix(array, 0, 1); /* Checksum */
|
||||
build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
|
||||
build_append_padded_str(array, desc->oem_id, 6, '\0'); /* OEMID */
|
||||
/* OEM Table ID */
|
||||
build_append_padded_str(array, desc->oem_table_id, 8, ' ');
|
||||
build_append_padded_str(array, desc->oem_table_id, 8, '\0');
|
||||
build_append_int_noprefix(array, 1, 4); /* OEM Revision */
|
||||
g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */
|
||||
build_append_int_noprefix(array, 1, 4); /* Creator Revision */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,6 +22,7 @@ acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_true: files('pcihp.c'))
|
|||
acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_false: files('acpi-pci-hotplug-stub.c'))
|
||||
acpi_ss.add(when: 'CONFIG_ACPI_VIOT', if_true: files('viot.c'))
|
||||
acpi_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('ich9.c', 'tco.c'))
|
||||
acpi_ss.add(when: 'CONFIG_ACPI_ERST', if_true: files('erst.c'))
|
||||
acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c'))
|
||||
acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c'))
|
||||
acpi_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c'))
|
||||
|
|
|
@ -55,3 +55,18 @@ piix4_gpe_writeb(uint64_t addr, unsigned width, uint64_t val) "addr: 0x%" PRIx64
|
|||
# tco.c
|
||||
tco_timer_reload(int ticks, int msec) "ticks=%d (%d ms)"
|
||||
tco_timer_expired(int timeouts_no, bool strap, bool no_reboot) "timeouts_no=%d no_reboot=%d/%d"
|
||||
|
||||
# erst.c
|
||||
acpi_erst_reg_write(uint64_t addr, uint64_t val, unsigned size) "addr: 0x%04" PRIx64 " <== 0x%016" PRIx64 " (size: %u)"
|
||||
acpi_erst_reg_read(uint64_t addr, uint64_t val, unsigned size) " addr: 0x%04" PRIx64 " ==> 0x%016" PRIx64 " (size: %u)"
|
||||
acpi_erst_mem_write(uint64_t addr, uint64_t val, unsigned size) "addr: 0x%06" PRIx64 " <== 0x%016" PRIx64 " (size: %u)"
|
||||
acpi_erst_mem_read(uint64_t addr, uint64_t val, unsigned size) " addr: 0x%06" PRIx64 " ==> 0x%016" PRIx64 " (size: %u)"
|
||||
acpi_erst_pci_bar_0(uint64_t addr) "BAR0: 0x%016" PRIx64
|
||||
acpi_erst_pci_bar_1(uint64_t addr) "BAR1: 0x%016" PRIx64
|
||||
acpi_erst_realizefn_in(void)
|
||||
acpi_erst_realizefn_out(unsigned size) "total nvram size %u bytes"
|
||||
acpi_erst_reset_in(unsigned record_count) "record_count %u"
|
||||
acpi_erst_reset_out(unsigned record_count) "record_count %u"
|
||||
acpi_erst_post_load(void *header, unsigned slot_size) "header: 0x%p slot_size %u"
|
||||
acpi_erst_class_init_in(void)
|
||||
acpi_erst_class_init_out(void)
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "sysemu/tpm.h"
|
||||
#include "hw/acpi/tpm.h"
|
||||
#include "hw/acpi/vmgenid.h"
|
||||
#include "hw/acpi/erst.h"
|
||||
#include "sysemu/tpm_backend.h"
|
||||
#include "hw/rtc/mc146818rtc_regs.h"
|
||||
#include "migration/vmstate.h"
|
||||
|
@ -74,6 +75,8 @@
|
|||
#include "hw/acpi/hmat.h"
|
||||
#include "hw/acpi/viot.h"
|
||||
|
||||
#include CONFIG_DEVICES
|
||||
|
||||
/* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
|
||||
* -M pc-i440fx-2.0. Even if the actual amount of AML generated grows
|
||||
* a little bit, there should be plenty of free space since the DSDT
|
||||
|
@ -2575,6 +2578,18 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
|||
ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
|
||||
x86ms->oem_table_id);
|
||||
|
||||
#ifdef CONFIG_ACPI_ERST
|
||||
{
|
||||
Object *erst_dev;
|
||||
erst_dev = find_erst_dev();
|
||||
if (erst_dev) {
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_erst(tables_blob, tables->linker, erst_dev,
|
||||
x86ms->oem_id, x86ms->oem_table_id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vmgenid_dev = find_vmgenid_dev();
|
||||
if (vmgenid_dev) {
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "hw/acpi/bios-linker-loader.h"
|
||||
#include "hw/acpi/generic_event_device.h"
|
||||
#include "hw/acpi/utils.h"
|
||||
#include "hw/acpi/erst.h"
|
||||
#include "hw/i386/fw_cfg.h"
|
||||
#include "hw/i386/microvm.h"
|
||||
#include "hw/pci/pci.h"
|
||||
|
@ -40,6 +41,8 @@
|
|||
#include "acpi-common.h"
|
||||
#include "acpi-microvm.h"
|
||||
|
||||
#include CONFIG_DEVICES
|
||||
|
||||
static void acpi_dsdt_add_virtio(Aml *scope,
|
||||
MicrovmMachineState *mms)
|
||||
{
|
||||
|
@ -207,6 +210,18 @@ static void acpi_build_microvm(AcpiBuildTables *tables,
|
|||
ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
|
||||
x86ms->oem_table_id);
|
||||
|
||||
#ifdef CONFIG_ACPI_ERST
|
||||
{
|
||||
Object *erst_dev;
|
||||
erst_dev = find_erst_dev();
|
||||
if (erst_dev) {
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_erst(tables_blob, tables->linker, erst_dev,
|
||||
x86ms->oem_id, x86ms->oem_table_id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
xsdt = tables_blob->len;
|
||||
build_xsdt(tables_blob, tables->linker, table_offsets, x86ms->oem_id,
|
||||
x86ms->oem_table_id);
|
||||
|
|
|
@ -357,10 +357,12 @@ static void pc_compat_1_4_fn(MachineState *machine)
|
|||
pc_compat_1_5_fn(machine);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISAPC
|
||||
static void pc_init_isa(MachineState *machine)
|
||||
{
|
||||
pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XEN
|
||||
static void pc_xen_hvm_init_pci(MachineState *machine)
|
||||
|
@ -916,6 +918,7 @@ void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id)
|
|||
pci_config_set_revision(bridge_dev->config, pch_rev_id);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISAPC
|
||||
static void isapc_machine_options(MachineClass *m)
|
||||
{
|
||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||
|
@ -935,7 +938,7 @@ static void isapc_machine_options(MachineClass *m)
|
|||
|
||||
DEFINE_PC_MACHINE(isapc, "isapc", pc_init_isa,
|
||||
isapc_machine_options);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XEN
|
||||
static void xenfv_4_2_machine_options(MachineClass *m)
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* ACPI Error Record Serialization Table, ERST, Implementation
|
||||
*
|
||||
* ACPI ERST introduced in ACPI 4.0, June 16, 2009.
|
||||
* ACPI Platform Error Interfaces : Error Serialization
|
||||
*
|
||||
* Copyright (c) 2021 Oracle and/or its affiliates.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef HW_ACPI_ERST_H
|
||||
#define HW_ACPI_ERST_H
|
||||
|
||||
void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
|
||||
const char *oem_id, const char *oem_table_id);
|
||||
|
||||
#define TYPE_ACPI_ERST "acpi-erst"
|
||||
|
||||
/* returns NULL unless there is exactly one device */
|
||||
static inline Object *find_erst_dev(void)
|
||||
{
|
||||
return object_resolve_path_type("", TYPE_ACPI_ERST, NULL);
|
||||
}
|
||||
#endif
|
|
@ -108,6 +108,7 @@ extern bool pci_available;
|
|||
#define PCI_DEVICE_ID_REDHAT_MDPY 0x000f
|
||||
#define PCI_DEVICE_ID_REDHAT_NVME 0x0010
|
||||
#define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
|
||||
#define PCI_DEVICE_ID_REDHAT_ACPI_ERST 0x0012
|
||||
#define PCI_DEVICE_ID_REDHAT_QXL 0x0100
|
||||
|
||||
#define FMT_PCIBUS PRIx64
|
||||
|
|
|
@ -690,6 +690,29 @@ vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
|
|||
VuDevRegion *dev_region = &dev->regions[dev->nregions];
|
||||
void *mmap_addr;
|
||||
|
||||
if (vmsg->fd_num != 1) {
|
||||
vmsg_close_fds(vmsg);
|
||||
vu_panic(dev, "VHOST_USER_ADD_MEM_REG received %d fds - only 1 fd "
|
||||
"should be sent for this message type", vmsg->fd_num);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vmsg->size < VHOST_USER_MEM_REG_SIZE) {
|
||||
close(vmsg->fds[0]);
|
||||
vu_panic(dev, "VHOST_USER_ADD_MEM_REG requires a message size of at "
|
||||
"least %d bytes and only %d bytes were received",
|
||||
VHOST_USER_MEM_REG_SIZE, vmsg->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dev->nregions == VHOST_USER_MAX_RAM_SLOTS) {
|
||||
close(vmsg->fds[0]);
|
||||
vu_panic(dev, "failing attempt to hot add memory via "
|
||||
"VHOST_USER_ADD_MEM_REG message because the backend has "
|
||||
"no free ram slots available");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are in postcopy mode and we receive a u64 payload with a 0 value
|
||||
* we know all the postcopy client bases have been received, and we
|
||||
|
@ -728,12 +751,12 @@ vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
|
|||
* accessing it before we userfault.
|
||||
*/
|
||||
mmap_addr = mmap(0, dev_region->size + dev_region->mmap_offset,
|
||||
PROT_NONE, MAP_SHARED,
|
||||
PROT_NONE, MAP_SHARED | MAP_NORESERVE,
|
||||
vmsg->fds[0], 0);
|
||||
} else {
|
||||
mmap_addr = mmap(0, dev_region->size + dev_region->mmap_offset,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, vmsg->fds[0],
|
||||
0);
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE,
|
||||
vmsg->fds[0], 0);
|
||||
}
|
||||
|
||||
if (mmap_addr == MAP_FAILED) {
|
||||
|
@ -796,10 +819,24 @@ static inline bool reg_equal(VuDevRegion *vudev_reg,
|
|||
|
||||
static bool
|
||||
vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
|
||||
int i, j;
|
||||
bool found = false;
|
||||
VuDevRegion shadow_regions[VHOST_USER_MAX_RAM_SLOTS] = {};
|
||||
VhostUserMemoryRegion m = vmsg->payload.memreg.region, *msg_region = &m;
|
||||
int i;
|
||||
bool found = false;
|
||||
|
||||
if (vmsg->fd_num != 1) {
|
||||
vmsg_close_fds(vmsg);
|
||||
vu_panic(dev, "VHOST_USER_REM_MEM_REG received %d fds - only 1 fd "
|
||||
"should be sent for this message type", vmsg->fd_num);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vmsg->size < VHOST_USER_MEM_REG_SIZE) {
|
||||
close(vmsg->fds[0]);
|
||||
vu_panic(dev, "VHOST_USER_REM_MEM_REG requires a message size of at "
|
||||
"least %d bytes and only %d bytes were received",
|
||||
VHOST_USER_MEM_REG_SIZE, vmsg->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
DPRINT("Removing region:\n");
|
||||
DPRINT(" guest_phys_addr: 0x%016"PRIx64"\n",
|
||||
|
@ -811,35 +848,40 @@ vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
|
|||
DPRINT(" mmap_offset 0x%016"PRIx64"\n",
|
||||
msg_region->mmap_offset);
|
||||
|
||||
for (i = 0, j = 0; i < dev->nregions; i++) {
|
||||
if (!reg_equal(&dev->regions[i], msg_region)) {
|
||||
shadow_regions[j].gpa = dev->regions[i].gpa;
|
||||
shadow_regions[j].size = dev->regions[i].size;
|
||||
shadow_regions[j].qva = dev->regions[i].qva;
|
||||
shadow_regions[j].mmap_addr = dev->regions[i].mmap_addr;
|
||||
shadow_regions[j].mmap_offset = dev->regions[i].mmap_offset;
|
||||
j++;
|
||||
} else {
|
||||
found = true;
|
||||
for (i = 0; i < dev->nregions; i++) {
|
||||
if (reg_equal(&dev->regions[i], msg_region)) {
|
||||
VuDevRegion *r = &dev->regions[i];
|
||||
void *m = (void *) (uintptr_t) r->mmap_addr;
|
||||
|
||||
if (m) {
|
||||
munmap(m, r->size + r->mmap_offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shift all affected entries by 1 to close the hole at index i and
|
||||
* zero out the last entry.
|
||||
*/
|
||||
memmove(dev->regions + i, dev->regions + i + 1,
|
||||
sizeof(VuDevRegion) * (dev->nregions - i - 1));
|
||||
memset(dev->regions + dev->nregions - 1, 0, sizeof(VuDevRegion));
|
||||
DPRINT("Successfully removed a region\n");
|
||||
dev->nregions--;
|
||||
i--;
|
||||
|
||||
found = true;
|
||||
|
||||
/* Continue the search for eventual duplicates. */
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
memcpy(dev->regions, shadow_regions,
|
||||
sizeof(VuDevRegion) * VHOST_USER_MAX_RAM_SLOTS);
|
||||
DPRINT("Successfully removed a region\n");
|
||||
dev->nregions--;
|
||||
vmsg_set_reply_u64(vmsg, 0);
|
||||
} else {
|
||||
vu_panic(dev, "Specified region not found\n");
|
||||
}
|
||||
|
||||
close(vmsg->fds[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -878,7 +920,7 @@ vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg)
|
|||
* accessing it before we userfault
|
||||
*/
|
||||
mmap_addr = mmap(0, dev_region->size + dev_region->mmap_offset,
|
||||
PROT_NONE, MAP_SHARED,
|
||||
PROT_NONE, MAP_SHARED | MAP_NORESERVE,
|
||||
vmsg->fds[i], 0);
|
||||
|
||||
if (mmap_addr == MAP_FAILED) {
|
||||
|
@ -965,7 +1007,7 @@ vu_set_mem_table_exec(VuDev *dev, VhostUserMsg *vmsg)
|
|||
* mapped address has to be page aligned, and we use huge
|
||||
* pages. */
|
||||
mmap_addr = mmap(0, dev_region->size + dev_region->mmap_offset,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE,
|
||||
vmsg->fds[i], 0);
|
||||
|
||||
if (mmap_addr == MAP_FAILED) {
|
||||
|
|
|
@ -129,6 +129,8 @@ typedef struct VhostUserMemoryRegion {
|
|||
uint64_t mmap_offset;
|
||||
} VhostUserMemoryRegion;
|
||||
|
||||
#define VHOST_USER_MEM_REG_SIZE (sizeof(VhostUserMemoryRegion))
|
||||
|
||||
typedef struct VhostUserMemory {
|
||||
uint32_t nregions;
|
||||
uint32_t padding;
|
||||
|
|
|
@ -3747,7 +3747,7 @@ static void tcg_target_init(TCGContext *s)
|
|||
{
|
||||
#ifdef CONFIG_CPUID_H
|
||||
unsigned a, b, c, d, b7 = 0;
|
||||
int max = __get_cpuid_max(0, 0);
|
||||
unsigned max = __get_cpuid_max(0, 0);
|
||||
|
||||
if (max >= 7) {
|
||||
/* BMI1 is available on AMD Piledriver and Intel Haswell CPUs. */
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -73,7 +73,8 @@
|
|||
|
||||
#define OEM_ID "TEST"
|
||||
#define OEM_TABLE_ID "OEM"
|
||||
#define OEM_TEST_ARGS "-machine x-oem-id="OEM_ID",x-oem-table-id="OEM_TABLE_ID
|
||||
#define OEM_TEST_ARGS "-machine x-oem-id=" OEM_ID ",x-oem-table-id=" \
|
||||
OEM_TABLE_ID
|
||||
|
||||
typedef struct {
|
||||
bool tcg_only;
|
||||
|
@ -1446,6 +1447,57 @@ static void test_acpi_piix4_tcg_acpi_hmat(void)
|
|||
test_acpi_tcg_acpi_hmat(MACHINE_PC);
|
||||
}
|
||||
|
||||
static void test_acpi_erst(const char *machine)
|
||||
{
|
||||
gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XXXXXX", NULL);
|
||||
gchar *params;
|
||||
test_data data;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.machine = machine;
|
||||
data.variant = ".acpierst";
|
||||
params = g_strdup_printf(
|
||||
" -object memory-backend-file,id=erstnvram,"
|
||||
"mem-path=%s,size=0x10000,share=on"
|
||||
" -device acpi-erst,memdev=erstnvram", tmp_path);
|
||||
test_acpi_one(params, &data);
|
||||
free_test_data(&data);
|
||||
g_free(params);
|
||||
g_assert(g_rmdir(tmp_path) == 0);
|
||||
g_free(tmp_path);
|
||||
}
|
||||
|
||||
static void test_acpi_piix4_acpi_erst(void)
|
||||
{
|
||||
test_acpi_erst(MACHINE_PC);
|
||||
}
|
||||
|
||||
static void test_acpi_q35_acpi_erst(void)
|
||||
{
|
||||
test_acpi_erst(MACHINE_Q35);
|
||||
}
|
||||
|
||||
static void test_acpi_microvm_acpi_erst(void)
|
||||
{
|
||||
gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XXXXXX", NULL);
|
||||
gchar *params;
|
||||
test_data data;
|
||||
|
||||
test_acpi_microvm_prepare(&data);
|
||||
data.variant = ".pcie";
|
||||
data.tcg_only = true; /* need constant host-phys-bits */
|
||||
params = g_strdup_printf(" -machine microvm,"
|
||||
"acpi=on,ioapic2=off,rtc=off,pcie=on"
|
||||
" -object memory-backend-file,id=erstnvram,"
|
||||
"mem-path=%s,size=0x10000,share=on"
|
||||
" -device acpi-erst,memdev=erstnvram", tmp_path);
|
||||
test_acpi_one(params, &data);
|
||||
g_free(params);
|
||||
g_assert(g_rmdir(tmp_path) == 0);
|
||||
g_free(tmp_path);
|
||||
free_test_data(&data);
|
||||
}
|
||||
|
||||
static void test_acpi_virt_tcg(void)
|
||||
{
|
||||
test_data data = {
|
||||
|
@ -1519,11 +1571,7 @@ static void test_acpi_q35_slic(void)
|
|||
static void test_oem_fields(test_data *data)
|
||||
{
|
||||
int i;
|
||||
char oem_id[6];
|
||||
char oem_table_id[8];
|
||||
|
||||
strpadcpy(oem_id, sizeof oem_id, OEM_ID, ' ');
|
||||
strpadcpy(oem_table_id, sizeof oem_table_id, OEM_TABLE_ID, ' ');
|
||||
for (i = 0; i < data->tables->len; ++i) {
|
||||
AcpiSdtTable *sdt;
|
||||
|
||||
|
@ -1533,8 +1581,8 @@ static void test_oem_fields(test_data *data)
|
|||
continue;
|
||||
}
|
||||
|
||||
g_assert(memcmp(sdt->aml + 10, oem_id, 6) == 0);
|
||||
g_assert(memcmp(sdt->aml + 16, oem_table_id, 8) == 0);
|
||||
g_assert(strncmp((char *)sdt->aml + 10, OEM_ID, 6) == 0);
|
||||
g_assert(strncmp((char *)sdt->aml + 16, OEM_TABLE_ID, 8) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1675,6 +1723,8 @@ int main(int argc, char *argv[])
|
|||
qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm);
|
||||
qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat);
|
||||
qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat);
|
||||
qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst);
|
||||
qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst);
|
||||
qtest_add_func("acpi/microvm", test_acpi_microvm_tcg);
|
||||
qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg);
|
||||
qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg);
|
||||
|
@ -1684,6 +1734,7 @@ int main(int argc, char *argv[])
|
|||
qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs);
|
||||
if (strcmp(arch, "x86_64") == 0) {
|
||||
qtest_add_func("acpi/microvm/pcie", test_acpi_microvm_pcie_tcg);
|
||||
qtest_add_func("acpi/microvm/acpierst", test_acpi_microvm_acpi_erst);
|
||||
}
|
||||
}
|
||||
if (has_kvm) {
|
||||
|
|
|
@ -138,7 +138,7 @@ static void add_x86_tests(void)
|
|||
* Unstable CI test under load
|
||||
* See https://lists.gnu.org/archive/html/qemu-devel/2019-02/msg05509.html
|
||||
*/
|
||||
if (g_test_slow()) {
|
||||
if (g_test_slow() && qtest_has_machine("isapc")) {
|
||||
qtest_add_data_func("cdrom/boot/isapc", "-M isapc "
|
||||
"-drive if=ide,media=cdrom,file=", test_cdboot);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* QTest testcase for acpi-erst
|
||||
*
|
||||
* Copyright (c) 2021 Oracle
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <glib/gstdio.h>
|
||||
#include "libqos/libqos-pc.h"
|
||||
#include "libqos/libqtest.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
#include "hw/pci/pci.h"
|
||||
|
||||
static void save_fn(QPCIDevice *dev, int devfn, void *data)
|
||||
{
|
||||
QPCIDevice **pdev = (QPCIDevice **) data;
|
||||
|
||||
*pdev = dev;
|
||||
}
|
||||
|
||||
static QPCIDevice *get_erst_device(QPCIBus *pcibus)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
|
||||
dev = NULL;
|
||||
qpci_device_foreach(pcibus,
|
||||
PCI_VENDOR_ID_REDHAT,
|
||||
PCI_DEVICE_ID_REDHAT_ACPI_ERST,
|
||||
save_fn, &dev);
|
||||
g_assert(dev != NULL);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
typedef struct _ERSTState {
|
||||
QOSState *qs;
|
||||
QPCIBar reg_bar, mem_bar;
|
||||
uint64_t reg_barsize, mem_barsize;
|
||||
QPCIDevice *dev;
|
||||
} ERSTState;
|
||||
|
||||
#define ACTION 0
|
||||
#define VALUE 8
|
||||
|
||||
static const char *reg2str(unsigned reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0:
|
||||
return "ACTION";
|
||||
case 8:
|
||||
return "VALUE";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t in_reg32(ERSTState *s, unsigned reg)
|
||||
{
|
||||
const char *name = reg2str(reg);
|
||||
uint32_t res;
|
||||
|
||||
res = qpci_io_readl(s->dev, s->reg_bar, reg);
|
||||
g_test_message("*%s -> %08x", name, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline uint64_t in_reg64(ERSTState *s, unsigned reg)
|
||||
{
|
||||
const char *name = reg2str(reg);
|
||||
uint64_t res;
|
||||
|
||||
res = qpci_io_readq(s->dev, s->reg_bar, reg);
|
||||
g_test_message("*%s -> %016llx", name, (unsigned long long)res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void out_reg32(ERSTState *s, unsigned reg, uint32_t v)
|
||||
{
|
||||
const char *name = reg2str(reg);
|
||||
|
||||
g_test_message("%08x -> *%s", v, name);
|
||||
qpci_io_writel(s->dev, s->reg_bar, reg, v);
|
||||
}
|
||||
|
||||
static void cleanup_vm(ERSTState *s)
|
||||
{
|
||||
g_free(s->dev);
|
||||
qtest_shutdown(s->qs);
|
||||
}
|
||||
|
||||
static void setup_vm_cmd(ERSTState *s, const char *cmd)
|
||||
{
|
||||
const char *arch = qtest_get_arch();
|
||||
|
||||
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||
s->qs = qtest_pc_boot(cmd);
|
||||
} else {
|
||||
g_printerr("erst-test tests are only available on x86\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
s->dev = get_erst_device(s->qs->pcibus);
|
||||
|
||||
s->reg_bar = qpci_iomap(s->dev, 0, &s->reg_barsize);
|
||||
g_assert_cmpuint(s->reg_barsize, ==, 16);
|
||||
|
||||
s->mem_bar = qpci_iomap(s->dev, 1, &s->mem_barsize);
|
||||
g_assert_cmpuint(s->mem_barsize, ==, 0x2000);
|
||||
|
||||
qpci_device_enable(s->dev);
|
||||
}
|
||||
|
||||
static void test_acpi_erst_basic(void)
|
||||
{
|
||||
ERSTState state;
|
||||
uint64_t log_address_range;
|
||||
uint64_t log_address_length;
|
||||
uint32_t log_address_attr;
|
||||
|
||||
setup_vm_cmd(&state,
|
||||
"-object memory-backend-file,"
|
||||
"mem-path=acpi-erst.XXXXXX,"
|
||||
"size=64K,"
|
||||
"share=on,"
|
||||
"id=nvram "
|
||||
"-device acpi-erst,"
|
||||
"memdev=nvram");
|
||||
|
||||
out_reg32(&state, ACTION, 0xD);
|
||||
log_address_range = in_reg64(&state, VALUE);
|
||||
out_reg32(&state, ACTION, 0xE);
|
||||
log_address_length = in_reg64(&state, VALUE);
|
||||
out_reg32(&state, ACTION, 0xF);
|
||||
log_address_attr = in_reg32(&state, VALUE);
|
||||
|
||||
/* Check log_address_range is not 0, ~0 or base */
|
||||
g_assert_cmpuint(log_address_range, !=, 0ULL);
|
||||
g_assert_cmpuint(log_address_range, !=, ~0ULL);
|
||||
g_assert_cmpuint(log_address_range, !=, state.reg_bar.addr);
|
||||
g_assert_cmpuint(log_address_range, ==, state.mem_bar.addr);
|
||||
|
||||
/* Check log_address_length is bar1_size */
|
||||
g_assert_cmpuint(log_address_length, ==, state.mem_barsize);
|
||||
|
||||
/* Check log_address_attr is 0 */
|
||||
g_assert_cmpuint(log_address_attr, ==, 0);
|
||||
|
||||
cleanup_vm(&state);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
qtest_add_func("/acpi-erst/basic", test_acpi_erst_basic);
|
||||
ret = g_test_run();
|
||||
return ret;
|
||||
}
|
|
@ -68,6 +68,7 @@ qtests_i386 = \
|
|||
(config_all_devices.has_key('CONFIG_RTL8139_PCI') ? ['rtl8139-test'] : []) + \
|
||||
(config_all_devices.has_key('CONFIG_E1000E_PCI_EXPRESS') ? ['fuzz-e1000e-test'] : []) + \
|
||||
(config_all_devices.has_key('CONFIG_ESP_PCI') ? ['am53c974-test'] : []) + \
|
||||
(config_all_devices.has_key('CONFIG_ACPI_ERST') ? ['erst-test'] : []) + \
|
||||
(config_all_devices.has_key('CONFIG_VIRTIO_NET') and \
|
||||
config_all_devices.has_key('CONFIG_Q35') and \
|
||||
config_all_devices.has_key('CONFIG_VIRTIO_PCI') and \
|
||||
|
@ -278,6 +279,7 @@ qtests = {
|
|||
'bios-tables-test': [io, 'boot-sector.c', 'acpi-utils.c', 'tpm-emu.c'],
|
||||
'cdrom-test': files('boot-sector.c'),
|
||||
'dbus-vmstate-test': files('migration-helpers.c') + dbus_vmstate1,
|
||||
'erst-test': files('erst-test.c'),
|
||||
'ivshmem-test': [rt, '../../contrib/ivshmem-server/ivshmem-server.c'],
|
||||
'migration-test': files('migration-helpers.c'),
|
||||
'pxe-test': files('boot-sector.c'),
|
||||
|
|
|
@ -272,7 +272,7 @@ static void init_accel(unsigned cache)
|
|||
|
||||
static void __attribute__((constructor)) init_cpuid_cache(void)
|
||||
{
|
||||
int max = __get_cpuid_max(0, NULL);
|
||||
unsigned max = __get_cpuid_max(0, NULL);
|
||||
int a, b, c, d;
|
||||
unsigned cache = 0;
|
||||
|
||||
|
|
|
@ -683,6 +683,7 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus,
|
|||
|
||||
ret = sigaction(SIGBUS, &act, &sigbus_oldact);
|
||||
if (ret) {
|
||||
qemu_mutex_unlock(&sigbus_mutex);
|
||||
error_setg_errno(errp, errno,
|
||||
"os_mem_prealloc: failed to install signal handler");
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue