virtio, pci, pc: cleanups, features
stricter rules for acpi tables: we now fail on any difference that isn't whitelisted. vhost-scsi migration. some cleanups all over the place Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJc+B4YAAoJECgfDbjSjVRpq1EIAJR7tCxcpu9GggVlinmUA8G4 tmSAe06IryH7+nF3RsnINuGu7ius9qC2/E2y0uJUHhTqiU/RWOfWZ7PPM0EcYZaA TLPaCe2NUF6/8afeqmvE9Usk7VspI5TDZRms+bonmZz2xP1lHIMN0qW4s7HHLWr8 sZKDtCJ+9cYII93VQwtlR0qiHgv5f0kzcuZeJaZHsAHH6XZGqRuQjI6txcFa4o53 lkdLCEwTnRuwu2wyL84eL5p+E8SzOgR/x1QI+nffrJfsvnmiT7lnOrkjnQlWAp5G xqwqsUrUxUCuQ+zitwJqmv+H6nx79MwAM7fTHAETCWX703N5o9tZxAnHHqLoa8I= =cQNg -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging virtio, pci, pc: cleanups, features stricter rules for acpi tables: we now fail on any difference that isn't whitelisted. vhost-scsi migration. some cleanups all over the place Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Wed 05 Jun 2019 20:55:04 BST # gpg: using RSA key 281F0DB8D28D5469 # 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: bios-tables-test: ignore identical binaries tests: acpi: add simple arm/virt testcase tests: add expected ACPI tables for arm/virt board bios-tables-test: list all tables that differ vhost-scsi: Allow user to enable migration vhost-scsi: Add VMState descriptor vhost-scsi: The vhost backend should be stopped when the VM is not running bios-tables-test: add diff allowed list vhost: fix memory leak in vhost_user_scsi_realize vhost: fix incorrect print type vhost: remove the dead code docs: smbios: remove family=x from type2 entry description pci: Fold pci_get_bus_devfn() into its sole caller pci: Make is_bridge a bool pcie: Simplify pci_adjust_config_limit() acpi: pci: use build_append_foo() API to construct MCFG hw/acpi: Consolidate build_mcfg to pci.c Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
347a6f44e9
@ -25,3 +25,4 @@
|
||||
CONFIG_ISAPC=y
|
||||
CONFIG_I440FX=y
|
||||
CONFIG_Q35=y
|
||||
CONFIG_ACPI_PCI=y
|
||||
|
@ -23,6 +23,10 @@ config ACPI_NVDIMM
|
||||
bool
|
||||
depends on ACPI
|
||||
|
||||
config ACPI_PCI
|
||||
bool
|
||||
depends on ACPI && PCI
|
||||
|
||||
config ACPI_VMGENID
|
||||
bool
|
||||
default y
|
||||
|
@ -11,6 +11,7 @@ common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
|
||||
common-obj-y += acpi_interface.o
|
||||
common-obj-y += bios-linker-loader.o
|
||||
common-obj-y += aml-build.o
|
||||
common-obj-$(CONFIG_ACPI_PCI) += pci.o
|
||||
common-obj-$(CONFIG_TPM) += tpm.o
|
||||
|
||||
common-obj-$(CONFIG_IPMI) += ipmi.o
|
||||
|
61
hw/acpi/pci.c
Normal file
61
hw/acpi/pci.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Support for generating PCI related ACPI tables and passing them to Guests
|
||||
*
|
||||
* Copyright (C) 2006 Fabrice Bellard
|
||||
* Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
|
||||
* Copyright (C) 2013-2019 Red Hat Inc
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
*
|
||||
* Author: Wei Yang <richardw.yang@linux.intel.com>
|
||||
* Author: Michael S. Tsirkin <mst@redhat.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 "hw/acpi/aml-build.h"
|
||||
#include "hw/acpi/pci.h"
|
||||
#include "hw/pci/pcie_host.h"
|
||||
|
||||
void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
|
||||
{
|
||||
int mcfg_start = table_data->len;
|
||||
|
||||
/*
|
||||
* PCI Firmware Specification, Revision 3.0
|
||||
* 4.1.2 MCFG Table Description.
|
||||
*/
|
||||
acpi_data_push(table_data, sizeof(AcpiTableHeader));
|
||||
/* Reserved */
|
||||
build_append_int_noprefix(table_data, 0, 8);
|
||||
|
||||
/*
|
||||
* Memory Mapped Enhanced Configuration Space Base Address Allocation
|
||||
* Structure
|
||||
*/
|
||||
/* Base address, processor-relative */
|
||||
build_append_int_noprefix(table_data, info->base, 8);
|
||||
/* PCI segment group number */
|
||||
build_append_int_noprefix(table_data, 0, 2);
|
||||
/* Starting PCI Bus number */
|
||||
build_append_int_noprefix(table_data, 0, 1);
|
||||
/* Final PCI Bus number */
|
||||
build_append_int_noprefix(table_data, PCIE_MMCFG_BUS(info->size - 1), 1);
|
||||
/* Reserved */
|
||||
build_append_int_noprefix(table_data, 0, 4);
|
||||
|
||||
build_header(linker, table_data, (void *)(table_data->data + mcfg_start),
|
||||
"MCFG", table_data->len - mcfg_start, 1, NULL, NULL);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ config ARM_VIRT
|
||||
select PLATFORM_BUS
|
||||
select SMBIOS
|
||||
select VIRTIO_MMIO
|
||||
select ACPI_PCI
|
||||
|
||||
config CHEETAH
|
||||
bool
|
||||
|
@ -546,23 +546,6 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
"SRAT", table_data->len - srat_start, 3, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
|
||||
{
|
||||
AcpiTableMcfg *mcfg;
|
||||
int len = sizeof(*mcfg) + sizeof(mcfg->allocation[0]);
|
||||
|
||||
mcfg = acpi_data_push(table_data, len);
|
||||
mcfg->allocation[0].address = cpu_to_le64(info->base);
|
||||
|
||||
/* Only a single allocation so no need to play with segments */
|
||||
mcfg->allocation[0].pci_segment = cpu_to_le16(0);
|
||||
mcfg->allocation[0].start_bus_number = 0;
|
||||
mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->size - 1);
|
||||
|
||||
build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1, NULL, NULL);
|
||||
}
|
||||
|
||||
/* GTDT */
|
||||
static void
|
||||
build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
|
@ -2405,22 +2405,6 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
table_data->len - srat_start, 1, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
build_mcfg_q35(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
|
||||
{
|
||||
AcpiTableMcfg *mcfg;
|
||||
int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
|
||||
|
||||
mcfg = acpi_data_push(table_data, len);
|
||||
mcfg->allocation[0].address = cpu_to_le64(info->base);
|
||||
/* Only a single allocation so no need to play with segments */
|
||||
mcfg->allocation[0].pci_segment = cpu_to_le16(0);
|
||||
mcfg->allocation[0].start_bus_number = 0;
|
||||
mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->size - 1);
|
||||
|
||||
build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* VT-d spec 8.1 DMA Remapping Reporting Structure
|
||||
* (version Oct. 2014 or later)
|
||||
@ -2690,7 +2674,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
}
|
||||
if (acpi_get_mcfg(&mcfg)) {
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_mcfg_q35(tables_blob, tables->linker, &mcfg);
|
||||
build_mcfg(tables_blob, tables->linker, &mcfg);
|
||||
}
|
||||
if (x86_iommu_get_default()) {
|
||||
IommuType IOMMUType = x86_iommu_get_type();
|
||||
|
@ -68,7 +68,7 @@ static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data)
|
||||
k->vendor_id = PCI_VENDOR_ID_DEC;
|
||||
k->device_id = PCI_DEVICE_ID_DEC_21154;
|
||||
k->config_write = pci_bridge_write_config;
|
||||
k->is_bridge = 1;
|
||||
k->is_bridge = true;
|
||||
dc->desc = "DEC 21154 PCI-PCI bridge";
|
||||
dc->reset = pci_bridge_reset;
|
||||
dc->vmsd = &vmstate_pci_device;
|
||||
@ -129,7 +129,7 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data)
|
||||
k->device_id = PCI_DEVICE_ID_DEC_21154;
|
||||
k->revision = 0x02;
|
||||
k->class_id = PCI_CLASS_BRIDGE_PCI;
|
||||
k->is_bridge = 1;
|
||||
k->is_bridge = true;
|
||||
/*
|
||||
* PCI-facing part of the host bridge, not usable without the
|
||||
* host-facing part, which can't be device_add'ed, yet.
|
||||
|
@ -90,7 +90,7 @@ static void i82801b11_bridge_class_init(ObjectClass *klass, void *data)
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
k->is_bridge = 1;
|
||||
k->is_bridge = true;
|
||||
k->vendor_id = PCI_VENDOR_ID_INTEL;
|
||||
k->device_id = PCI_DEVICE_ID_INTEL_82801BA_11;
|
||||
k->revision = ICH9_D2P_A2_REVISION;
|
||||
|
@ -253,7 +253,7 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
|
||||
k->vendor_id = PCI_VENDOR_ID_REDHAT;
|
||||
k->device_id = PCI_DEVICE_ID_REDHAT_BRIDGE;
|
||||
k->class_id = PCI_CLASS_BRIDGE_PCI;
|
||||
k->is_bridge = 1,
|
||||
k->is_bridge = true;
|
||||
dc->desc = "Standard PCI Bridge";
|
||||
dc->reset = qdev_pci_bridge_dev_reset;
|
||||
dc->props = pci_bridge_dev_properties;
|
||||
|
@ -143,7 +143,7 @@ static void pcie_pci_bridge_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
|
||||
|
||||
k->is_bridge = 1;
|
||||
k->is_bridge = true;
|
||||
k->vendor_id = PCI_VENDOR_ID_REDHAT;
|
||||
k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE;
|
||||
k->realize = pcie_pci_bridge_realize;
|
||||
|
@ -162,7 +162,7 @@ static void rp_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->is_bridge = 1;
|
||||
k->is_bridge = true;
|
||||
k->config_write = rp_write_config;
|
||||
k->realize = rp_realize;
|
||||
k->exit = rp_exit;
|
||||
|
@ -76,7 +76,7 @@ static void simba_pci_bridge_class_init(ObjectClass *klass, void *data)
|
||||
k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
|
||||
k->revision = 0x11;
|
||||
k->config_write = pci_bridge_write_config;
|
||||
k->is_bridge = 1;
|
||||
k->is_bridge = true;
|
||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||
dc->reset = pci_bridge_reset;
|
||||
dc->vmsd = &vmstate_pci_device;
|
||||
|
@ -152,7 +152,7 @@ static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->is_bridge = 1;
|
||||
k->is_bridge = true;
|
||||
k->config_write = xio3130_downstream_write_config;
|
||||
k->realize = xio3130_downstream_realize;
|
||||
k->exit = xio3130_downstream_exitfn;
|
||||
|
@ -126,7 +126,7 @@ static void xio3130_upstream_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->is_bridge = 1;
|
||||
k->is_bridge = true;
|
||||
k->config_write = xio3130_upstream_write_config;
|
||||
k->realize = xio3130_upstream_realize;
|
||||
k->exit = xio3130_upstream_exitfn;
|
||||
|
101
hw/pci/pci.c
101
hw/pci/pci.c
@ -120,6 +120,27 @@ static void pci_bus_realize(BusState *qbus, Error **errp)
|
||||
vmstate_register(NULL, -1, &vmstate_pcibus, bus);
|
||||
}
|
||||
|
||||
static void pcie_bus_realize(BusState *qbus, Error **errp)
|
||||
{
|
||||
PCIBus *bus = PCI_BUS(qbus);
|
||||
|
||||
pci_bus_realize(qbus, errp);
|
||||
|
||||
/*
|
||||
* A PCI-E bus can support extended config space if it's the root
|
||||
* bus, or if the bus/bridge above it does as well
|
||||
*/
|
||||
if (pci_bus_is_root(bus)) {
|
||||
bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
|
||||
} else {
|
||||
PCIBus *parent_bus = pci_get_bus(bus->parent_dev);
|
||||
|
||||
if (pci_bus_allows_extended_config_space(parent_bus)) {
|
||||
bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pci_bus_unrealize(BusState *qbus, Error **errp)
|
||||
{
|
||||
PCIBus *bus = PCI_BUS(qbus);
|
||||
@ -142,11 +163,6 @@ static uint16_t pcibus_numa_node(PCIBus *bus)
|
||||
return NUMA_NODE_UNASSIGNED;
|
||||
}
|
||||
|
||||
static bool pcibus_allows_extended_config_space(PCIBus *bus)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static void pci_bus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
BusClass *k = BUS_CLASS(klass);
|
||||
@ -161,7 +177,6 @@ static void pci_bus_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
pbc->bus_num = pcibus_num;
|
||||
pbc->numa_node = pcibus_numa_node;
|
||||
pbc->allows_extended_config_space = pcibus_allows_extended_config_space;
|
||||
}
|
||||
|
||||
static const TypeInfo pci_bus_info = {
|
||||
@ -182,16 +197,11 @@ static const TypeInfo conventional_pci_interface_info = {
|
||||
.parent = TYPE_INTERFACE,
|
||||
};
|
||||
|
||||
static bool pciebus_allows_extended_config_space(PCIBus *bus)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void pcie_bus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PCIBusClass *pbc = PCI_BUS_CLASS(klass);
|
||||
BusClass *k = BUS_CLASS(klass);
|
||||
|
||||
pbc->allows_extended_config_space = pciebus_allows_extended_config_space;
|
||||
k->realize = pcie_bus_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo pcie_bus_info = {
|
||||
@ -410,11 +420,6 @@ bool pci_bus_is_express(PCIBus *bus)
|
||||
return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS);
|
||||
}
|
||||
|
||||
bool pci_bus_allows_extended_config_space(PCIBus *bus)
|
||||
{
|
||||
return PCI_BUS_GET_CLASS(bus)->allows_extended_config_space(bus);
|
||||
}
|
||||
|
||||
void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
|
||||
const char *name,
|
||||
MemoryRegion *address_space_mem,
|
||||
@ -718,37 +723,6 @@ static int pci_parse_devaddr(const char *addr, int *domp, int *busp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root,
|
||||
const char *devaddr)
|
||||
{
|
||||
int dom, bus;
|
||||
unsigned slot;
|
||||
|
||||
if (!root) {
|
||||
fprintf(stderr, "No primary PCI bus\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(!root->parent_dev);
|
||||
|
||||
if (!devaddr) {
|
||||
*devfnp = -1;
|
||||
return pci_find_bus_nr(root, 0);
|
||||
}
|
||||
|
||||
if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dom != 0) {
|
||||
fprintf(stderr, "No support for non-zero PCI domains\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*devfnp = PCI_DEVFN(slot, 0);
|
||||
return pci_find_bus_nr(root, bus);
|
||||
}
|
||||
|
||||
static void pci_init_cmask(PCIDevice *dev)
|
||||
{
|
||||
pci_set_word(dev->cmask + PCI_VENDOR_ID, 0xffff);
|
||||
@ -1890,6 +1864,8 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
|
||||
DeviceState *dev;
|
||||
int devfn;
|
||||
int i;
|
||||
int dom, busnr;
|
||||
unsigned slot;
|
||||
|
||||
if (nd->model && !strcmp(nd->model, "virtio")) {
|
||||
g_free(nd->model);
|
||||
@ -1923,7 +1899,32 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bus = pci_get_bus_devfn(&devfn, rootbus, devaddr);
|
||||
if (!rootbus) {
|
||||
error_report("No primary PCI bus");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(!rootbus->parent_dev);
|
||||
|
||||
if (!devaddr) {
|
||||
devfn = -1;
|
||||
busnr = 0;
|
||||
} else {
|
||||
if (pci_parse_devaddr(devaddr, &dom, &busnr, &slot, NULL) < 0) {
|
||||
error_report("Invalid PCI device address %s for device %s",
|
||||
devaddr, nd->model);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (dom != 0) {
|
||||
error_report("No support for non-zero PCI domains");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
devfn = PCI_DEVFN(slot, 0);
|
||||
}
|
||||
|
||||
bus = pci_find_bus_nr(rootbus, busnr);
|
||||
if (!bus) {
|
||||
error_report("Invalid PCI device address %s for device %s",
|
||||
devaddr, nd->model);
|
||||
|
@ -53,16 +53,9 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
|
||||
|
||||
static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit)
|
||||
{
|
||||
if (*limit > PCI_CONFIG_SPACE_SIZE) {
|
||||
if (!pci_bus_allows_extended_config_space(bus)) {
|
||||
*limit = PCI_CONFIG_SPACE_SIZE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pci_bus_is_root(bus)) {
|
||||
PCIDevice *bridge = pci_bridge_get_device(bus);
|
||||
pci_adjust_config_limit(pci_get_bus(bridge), limit);
|
||||
}
|
||||
if ((*limit > PCI_CONFIG_SPACE_SIZE) &&
|
||||
!pci_bus_allows_extended_config_space(bus)) {
|
||||
*limit = PCI_CONFIG_SPACE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1626,28 +1626,6 @@ static void spapr_phb_unrealize(DeviceState *dev, Error **errp)
|
||||
memory_region_del_subregion(get_system_memory(), &sphb->mem32window);
|
||||
}
|
||||
|
||||
static bool spapr_phb_allows_extended_config_space(PCIBus *bus)
|
||||
{
|
||||
SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(BUS(bus)->parent);
|
||||
|
||||
return sphb->pcie_ecs;
|
||||
}
|
||||
|
||||
static void spapr_phb_root_bus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PCIBusClass *pbc = PCI_BUS_CLASS(klass);
|
||||
|
||||
pbc->allows_extended_config_space = spapr_phb_allows_extended_config_space;
|
||||
}
|
||||
|
||||
#define TYPE_SPAPR_PHB_ROOT_BUS "pci"
|
||||
|
||||
static const TypeInfo spapr_phb_root_bus_info = {
|
||||
.name = TYPE_SPAPR_PHB_ROOT_BUS,
|
||||
.parent = TYPE_PCI_BUS,
|
||||
.class_init = spapr_phb_root_bus_class_init,
|
||||
};
|
||||
|
||||
static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
/* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
|
||||
@ -1753,7 +1731,16 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
pci_spapr_set_irq, pci_swizzle_map_irq_fn, sphb,
|
||||
&sphb->memspace, &sphb->iospace,
|
||||
PCI_DEVFN(0, 0), PCI_NUM_PINS,
|
||||
TYPE_SPAPR_PHB_ROOT_BUS);
|
||||
TYPE_PCI_BUS);
|
||||
|
||||
/*
|
||||
* Despite resembling a vanilla PCI bus in most ways, the PAPR
|
||||
* para-virtualized PCI bus *does* permit PCI-E extended config
|
||||
* space access
|
||||
*/
|
||||
if (sphb->pcie_ecs) {
|
||||
bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
|
||||
}
|
||||
phb->bus = bus;
|
||||
qbus_set_hotplug_handler(BUS(phb->bus), OBJECT(sphb), NULL);
|
||||
|
||||
@ -2348,7 +2335,6 @@ void spapr_pci_rtas_init(void)
|
||||
static void spapr_pci_register_types(void)
|
||||
{
|
||||
type_register_static(&spapr_phb_info);
|
||||
type_register_static(&spapr_phb_root_bus_info);
|
||||
}
|
||||
|
||||
type_init(spapr_pci_register_types)
|
||||
|
@ -114,6 +114,10 @@ static void vhost_scsi_set_status(VirtIODevice *vdev, uint8_t val)
|
||||
VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
|
||||
bool start = (val & VIRTIO_CONFIG_S_DRIVER_OK);
|
||||
|
||||
if (!vdev->vm_running) {
|
||||
start = false;
|
||||
}
|
||||
|
||||
if (vsc->dev.started == start) {
|
||||
return;
|
||||
}
|
||||
@ -135,6 +139,28 @@ static void vhost_dummy_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
}
|
||||
|
||||
static int vhost_scsi_pre_save(void *opaque)
|
||||
{
|
||||
VHostSCSICommon *vsc = opaque;
|
||||
|
||||
/* At this point, backend must be stopped, otherwise
|
||||
* it might keep writing to memory. */
|
||||
assert(!vsc->dev.started);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_virtio_vhost_scsi = {
|
||||
.name = "virtio-vhost_scsi",
|
||||
.minimum_version_id = 1,
|
||||
.version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_VIRTIO_DEVICE,
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.pre_save = vhost_scsi_pre_save,
|
||||
};
|
||||
|
||||
static void vhost_scsi_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
|
||||
@ -173,13 +199,18 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
error_setg(&vsc->migration_blocker,
|
||||
"vhost-scsi does not support migration");
|
||||
migrate_add_blocker(vsc->migration_blocker, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
error_free(vsc->migration_blocker);
|
||||
goto close_fd;
|
||||
if (!vsc->migratable) {
|
||||
error_setg(&vsc->migration_blocker,
|
||||
"vhost-scsi does not support migration in all cases. "
|
||||
"When external environment supports it (Orchestrator migrates "
|
||||
"target SCSI device state or use shared storage over network), "
|
||||
"set 'migratable' property to true to enable migration.");
|
||||
migrate_add_blocker(vsc->migration_blocker, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
error_free(vsc->migration_blocker);
|
||||
goto close_fd;
|
||||
}
|
||||
}
|
||||
|
||||
vsc->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
|
||||
@ -204,7 +235,9 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
|
||||
free_vqs:
|
||||
migrate_del_blocker(vsc->migration_blocker);
|
||||
if (!vsc->migratable) {
|
||||
migrate_del_blocker(vsc->migration_blocker);
|
||||
}
|
||||
g_free(vsc->dev.vqs);
|
||||
close_fd:
|
||||
close(vhostfd);
|
||||
@ -217,8 +250,10 @@ static void vhost_scsi_unrealize(DeviceState *dev, Error **errp)
|
||||
VHostSCSICommon *vsc = VHOST_SCSI_COMMON(dev);
|
||||
struct vhost_virtqueue *vqs = vsc->dev.vqs;
|
||||
|
||||
migrate_del_blocker(vsc->migration_blocker);
|
||||
error_free(vsc->migration_blocker);
|
||||
if (!vsc->migratable) {
|
||||
migrate_del_blocker(vsc->migration_blocker);
|
||||
error_free(vsc->migration_blocker);
|
||||
}
|
||||
|
||||
/* This will stop vhost backend. */
|
||||
vhost_scsi_set_status(vdev, 0);
|
||||
@ -242,6 +277,7 @@ static Property vhost_scsi_properties[] = {
|
||||
DEFINE_PROP_BIT64("t10_pi", VHostSCSICommon, host_features,
|
||||
VIRTIO_SCSI_F_T10_PI,
|
||||
false),
|
||||
DEFINE_PROP_BOOL("migratable", VHostSCSICommon, migratable, false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@ -252,6 +288,7 @@ static void vhost_scsi_class_init(ObjectClass *klass, void *data)
|
||||
FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(klass);
|
||||
|
||||
dc->props = vhost_scsi_properties;
|
||||
dc->vmsd = &vmstate_virtio_vhost_scsi;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
vdc->realize = vhost_scsi_realize;
|
||||
vdc->unrealize = vhost_scsi_unrealize;
|
||||
|
@ -69,6 +69,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
|
||||
VHostUserSCSI *s = VHOST_USER_SCSI(dev);
|
||||
VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
|
||||
struct vhost_virtqueue *vqs = NULL;
|
||||
Error *err = NULL;
|
||||
int ret;
|
||||
|
||||
@ -93,6 +94,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
|
||||
vsc->dev.vqs = g_new(struct vhost_virtqueue, vsc->dev.nvqs);
|
||||
vsc->dev.vq_index = 0;
|
||||
vsc->dev.backend_features = 0;
|
||||
vqs = vsc->dev.vqs;
|
||||
|
||||
ret = vhost_dev_init(&vsc->dev, &s->vhost_user,
|
||||
VHOST_BACKEND_TYPE_USER, 0);
|
||||
@ -100,6 +102,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
|
||||
error_setg(errp, "vhost-user-scsi: vhost initialization failed: %s",
|
||||
strerror(-ret));
|
||||
vhost_user_cleanup(&s->vhost_user);
|
||||
g_free(vqs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1081,7 +1081,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
|
||||
|
||||
r = dev->vhost_ops->vhost_get_vring_base(dev, &state);
|
||||
if (r < 0) {
|
||||
VHOST_OPS_DEBUG("vhost VQ %d ring restore failed: %d", idx, r);
|
||||
VHOST_OPS_DEBUG("vhost VQ %u ring restore failed: %d", idx, r);
|
||||
/* Connection to the backend is broken, so let's sync internal
|
||||
* last avail idx to the device used idx.
|
||||
*/
|
||||
@ -1650,7 +1650,6 @@ fail_vq:
|
||||
hdev->vqs + i,
|
||||
hdev->vq_index + i);
|
||||
}
|
||||
i = hdev->nvqs;
|
||||
|
||||
fail_mem:
|
||||
fail_features:
|
||||
|
@ -449,24 +449,6 @@ struct AcpiSratProcessorGiccAffinity {
|
||||
|
||||
typedef struct AcpiSratProcessorGiccAffinity AcpiSratProcessorGiccAffinity;
|
||||
|
||||
/* PCI fw r3.0 MCFG table. */
|
||||
/* Subtable */
|
||||
struct AcpiMcfgAllocation {
|
||||
uint64_t address; /* Base address, processor-relative */
|
||||
uint16_t pci_segment; /* PCI segment group number */
|
||||
uint8_t start_bus_number; /* Starting PCI Bus number */
|
||||
uint8_t end_bus_number; /* Final PCI Bus number */
|
||||
uint32_t reserved;
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiMcfgAllocation AcpiMcfgAllocation;
|
||||
|
||||
struct AcpiTableMcfg {
|
||||
ACPI_TABLE_HEADER_DEF;
|
||||
uint8_t reserved[8];
|
||||
AcpiMcfgAllocation allocation[0];
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiTableMcfg AcpiTableMcfg;
|
||||
|
||||
/*
|
||||
* TCPA Description Table
|
||||
*
|
||||
|
@ -30,4 +30,5 @@ typedef struct AcpiMcfgInfo {
|
||||
uint32_t size;
|
||||
} AcpiMcfgInfo;
|
||||
|
||||
void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info);
|
||||
#endif
|
||||
|
@ -234,7 +234,7 @@ typedef struct PCIDeviceClass {
|
||||
* This doesn't mean pci host switch.
|
||||
* When card bus bridge is supported, this would be enhanced.
|
||||
*/
|
||||
int is_bridge;
|
||||
bool is_bridge;
|
||||
|
||||
/* rom bar */
|
||||
const char *romfile;
|
||||
@ -395,7 +395,6 @@ typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
|
||||
#define TYPE_PCIE_BUS "PCIE"
|
||||
|
||||
bool pci_bus_is_express(PCIBus *bus);
|
||||
bool pci_bus_allows_extended_config_space(PCIBus *bus);
|
||||
|
||||
void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
|
||||
const char *name,
|
||||
|
@ -17,12 +17,13 @@ typedef struct PCIBusClass {
|
||||
|
||||
int (*bus_num)(PCIBus *bus);
|
||||
uint16_t (*numa_node)(PCIBus *bus);
|
||||
bool (*allows_extended_config_space)(PCIBus *bus);
|
||||
} PCIBusClass;
|
||||
|
||||
enum PCIBusFlags {
|
||||
/* This bus is the root of a PCI domain */
|
||||
PCI_BUS_IS_ROOT = 0x0001,
|
||||
/* PCIe extended configuration space is accessible on this bus */
|
||||
PCI_BUS_EXTENDED_CONFIG_SPACE = 0x0002,
|
||||
};
|
||||
|
||||
struct PCIBus {
|
||||
@ -57,4 +58,9 @@ static inline bool pci_bus_is_root(PCIBus *bus)
|
||||
return !!(bus->flags & PCI_BUS_IS_ROOT);
|
||||
}
|
||||
|
||||
static inline bool pci_bus_allows_extended_config_space(PCIBus *bus)
|
||||
{
|
||||
return !!(bus->flags & PCI_BUS_EXTENDED_CONFIG_SPACE);
|
||||
}
|
||||
|
||||
#endif /* QEMU_PCI_BUS_H */
|
||||
|
@ -36,6 +36,7 @@ typedef struct VHostSCSICommon {
|
||||
int target;
|
||||
int lun;
|
||||
uint64_t host_features;
|
||||
bool migratable;
|
||||
} VHostSCSICommon;
|
||||
|
||||
int vhost_scsi_common_start(VHostSCSICommon *vsc);
|
||||
|
@ -2080,7 +2080,7 @@ Specify SMBIOS type 0 fields
|
||||
@item -smbios type=1[,manufacturer=@var{str}][,product=@var{str}][,version=@var{str}][,serial=@var{str}][,uuid=@var{uuid}][,sku=@var{str}][,family=@var{str}]
|
||||
Specify SMBIOS type 1 fields
|
||||
|
||||
@item -smbios type=2[,manufacturer=@var{str}][,product=@var{str}][,version=@var{str}][,serial=@var{str}][,asset=@var{str}][,location=@var{str}][,family=@var{str}]
|
||||
@item -smbios type=2[,manufacturer=@var{str}][,product=@var{str}][,version=@var{str}][,serial=@var{str}][,asset=@var{str}][,location=@var{str}]
|
||||
Specify SMBIOS type 2 fields
|
||||
|
||||
@item -smbios type=3[,manufacturer=@var{str}][,version=@var{str}][,serial=@var{str}][,asset=@var{str}][,sku=@var{str}]
|
||||
|
@ -264,6 +264,10 @@ check-qtest-arm-y += tests/hexloader-test$(EXESUF)
|
||||
check-qtest-aarch64-y = tests/numa-test$(EXESUF)
|
||||
check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF)
|
||||
check-qtest-aarch64-y += tests/migration-test$(EXESUF)
|
||||
# TODO: once aarch64 TCG is fixed on ARM 32 bit host, make test unconditional
|
||||
ifneq ($(ARCH),arm)
|
||||
check-qtest-aarch64-y += tests/bios-tables-test$(EXESUF)
|
||||
endif
|
||||
|
||||
check-qtest-microblazeel-y += $(check-qtest-microblaze-y)
|
||||
|
||||
|
1
tests/bios-tables-test-allowed-diff.h
Normal file
1
tests/bios-tables-test-allowed-diff.h
Normal file
@ -0,0 +1 @@
|
||||
/* List of comma-separated changed AML files to ignore */
|
@ -342,13 +342,29 @@ try_again:
|
||||
return exp_tables;
|
||||
}
|
||||
|
||||
static bool test_acpi_find_diff_allowed(AcpiSdtTable *sdt)
|
||||
{
|
||||
const gchar *allowed_diff_file[] = {
|
||||
#include "bios-tables-test-allowed-diff.h"
|
||||
NULL
|
||||
};
|
||||
const gchar **f;
|
||||
|
||||
for (f = allowed_diff_file; *f; ++f) {
|
||||
if (!g_strcmp0(sdt->aml_file, *f)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* test the list of tables in @data->tables against reference tables */
|
||||
static void test_acpi_asl(test_data *data)
|
||||
{
|
||||
int i;
|
||||
AcpiSdtTable *sdt, *exp_sdt;
|
||||
test_data exp_data;
|
||||
gboolean exp_err, err;
|
||||
gboolean exp_err, err, all_tables_match = true;
|
||||
|
||||
memset(&exp_data, 0, sizeof(exp_data));
|
||||
exp_data.tables = load_expected_aml(data);
|
||||
@ -359,6 +375,20 @@ static void test_acpi_asl(test_data *data)
|
||||
sdt = &g_array_index(data->tables, AcpiSdtTable, i);
|
||||
exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i);
|
||||
|
||||
if (sdt->aml_len == exp_sdt->aml_len &&
|
||||
!memcmp(sdt->aml, exp_sdt->aml, sdt->aml_len)) {
|
||||
/* Identical table binaries: no need to disassemble. */
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"acpi-test: Warning! %.4s binary file mismatch. "
|
||||
"Actual [aml:%s], Expected [aml:%s].\n",
|
||||
exp_sdt->aml, sdt->aml_file, exp_sdt->aml_file);
|
||||
|
||||
all_tables_match = all_tables_match &&
|
||||
test_acpi_find_diff_allowed(exp_sdt);
|
||||
|
||||
err = load_asl(data->tables, sdt);
|
||||
asl = normalize_asl(sdt->asl);
|
||||
|
||||
@ -396,11 +426,12 @@ static void test_acpi_asl(test_data *data)
|
||||
"see ASL difference.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g_string_free(asl, true);
|
||||
g_string_free(exp_asl, true);
|
||||
}
|
||||
g_assert(all_tables_match);
|
||||
|
||||
free_test_data(&exp_data);
|
||||
}
|
||||
@ -813,6 +844,22 @@ static void test_acpi_piix4_tcg_dimm_pxm(void)
|
||||
test_acpi_tcg_dimm_pxm(MACHINE_PC);
|
||||
}
|
||||
|
||||
static void test_acpi_virt_tcg(void)
|
||||
{
|
||||
test_data data = {
|
||||
.machine = "virt",
|
||||
.accel = "tcg",
|
||||
.uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
|
||||
.uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
|
||||
.cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2",
|
||||
.ram_start = 0x40000000ULL,
|
||||
.scan_len = 128ULL * 1024 * 1024,
|
||||
};
|
||||
|
||||
test_acpi_one("-cpu cortex-a57", &data);
|
||||
free_test_data(&data);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *arch = qtest_get_arch();
|
||||
@ -841,6 +888,8 @@ int main(int argc, char *argv[])
|
||||
qtest_add_func("acpi/q35/numamem", test_acpi_q35_tcg_numamem);
|
||||
qtest_add_func("acpi/piix4/dimmpxm", test_acpi_piix4_tcg_dimm_pxm);
|
||||
qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm);
|
||||
} else if (strcmp(arch, "aarch64") == 0) {
|
||||
qtest_add_func("acpi/virt", test_acpi_virt_tcg);
|
||||
}
|
||||
ret = g_test_run();
|
||||
boot_sector_cleanup(disk);
|
||||
|
@ -12,7 +12,7 @@
|
||||
# This work is licensed under the terms of the GNU GPLv2.
|
||||
# See the COPYING.LIB file in the top-level directory.
|
||||
|
||||
qemu_bins="x86_64-softmmu/qemu-system-x86_64"
|
||||
qemu_bins="x86_64-softmmu/qemu-system-x86_64 aarch64-softmmu/qemu-system-aarch64"
|
||||
|
||||
if [ ! -e "tests/bios-tables-test" ]; then
|
||||
echo "Test: bios-tables-test is required! Run make check before this script."
|
||||
|
BIN
tests/data/acpi/virt/APIC
Normal file
BIN
tests/data/acpi/virt/APIC
Normal file
Binary file not shown.
BIN
tests/data/acpi/virt/DSDT
Normal file
BIN
tests/data/acpi/virt/DSDT
Normal file
Binary file not shown.
BIN
tests/data/acpi/virt/FACP
Normal file
BIN
tests/data/acpi/virt/FACP
Normal file
Binary file not shown.
BIN
tests/data/acpi/virt/GTDT
Normal file
BIN
tests/data/acpi/virt/GTDT
Normal file
Binary file not shown.
BIN
tests/data/acpi/virt/MCFG
Normal file
BIN
tests/data/acpi/virt/MCFG
Normal file
Binary file not shown.
BIN
tests/data/acpi/virt/SPCR
Normal file
BIN
tests/data/acpi/virt/SPCR
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user