pc, acpi, pci, virtio: fixes, cleanups, features, tests

Some fixes and cleanups. New tests.
 Configurable tx queue size for virtio-net.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQEcBAABAgAGBQJZWp5VAAoJECgfDbjSjVRpI6sIAMFpi+UBsE8NR5s6kNZOJIEc
 rajYhfnuCoGmAXiDalVVgEjyEjlfeDqkdQyWb9r4XNRGfPAv76V4d9l0KNnuGEHF
 5GFNduAuECYm8Hl5e6J/gSNCau/hmdBOtFUZvYWs+yhVpRw7+8lJTvhviNzBIGa0
 mZBHCaAUzdyW7fvPh0inWxhXscPaUi8pHfohthsuTxRuBjKrQq4L/4zF9u4Mmtu+
 zNHpNMQ/mn3uC9IjiD7csfqF9IHxMlUl0IkoKXm1waIpZjr9LQ5hPhbP1KepVP6c
 fgPuJYHT+HeVfzyBIXbTZGhza2KduDLM7YCGWkprPBmjwM7OLrBl3JuWmw4Kg+4=
 =g6bo
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging

pc, acpi, pci, virtio: fixes, cleanups, features, tests

Some fixes and cleanups. New tests.
Configurable tx queue size for virtio-net.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Mon 03 Jul 2017 20:43:17 BST
# gpg:                using RSA key 0x281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# 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: (21 commits)
  i386/acpi: update expected acpi files
  virtio-net: fix tx queue size for !vhost-user
  tests: Add unit tests for the VM Generation ID feature
  vhost-user: unregister slave req handler at cleanup time
  vhost: ensure vhost_ops are set before calling iotlb callback
  intel_iommu: fix migration breakage on mr switch
  hw/acpi: remove dead acpi code
  fw_cfg: move setting of FW_CFG_VERSION_DMA bit to fw_cfg_init1()
  fw_cfg: don't map the fw_cfg IO ports in fw_cfg_io_realize()
  i386/kvm/pci-assign: Use errp directly rather than local_err
  i386/kvm/pci-assign: Fix return type of verify_irqchip_kernel()
  pci: Convert shpc_init() to Error
  pci: Convert to realize
  pci: Replace pci_add_capability2() with pci_add_capability()
  pci: Make errp the last parameter of pci_add_capability()
  pci: Fix the wrong assertion.
  pci: Add comment for pci_add_capability2()
  pci: Clean up error checking in pci_add_capability()
  intel_iommu: relax iq tail check on VTD_GCMD_QIE enable
  hw/pci-bridge/dec: Classify the DEC PCI bridge as bridge device
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-07-04 11:17:02 +01:00
commit 0c7a8b9baa
41 changed files with 493 additions and 205 deletions

View File

@ -1912,16 +1912,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
build_piix4_pci_hotplug(dsdt);
build_piix4_pci0_int(dsdt);
} else {
sb_scope = aml_scope("_SB");
aml_append(sb_scope,
aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x0c));
aml_append(sb_scope,
aml_operation_region("PCSB", AML_SYSTEM_IO, aml_int(0xae0c), 0x01));
field = aml_field("PCSB", AML_ANY_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
aml_append(field, aml_named_field("PCIB", 8));
aml_append(sb_scope, field);
aml_append(dsdt, sb_scope);
sb_scope = aml_scope("_SB");
dev = aml_device("PCI0");
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));

View File

@ -1158,13 +1158,23 @@ static void amdvi_realize(DeviceState *dev, Error **err)
x86_iommu->type = TYPE_AMD;
qdev_set_parent_bus(DEVICE(&s->pci), &bus->qbus);
object_property_set_bool(OBJECT(&s->pci), true, "realized", err);
s->capab_offset = pci_add_capability(&s->pci.dev, AMDVI_CAPAB_ID_SEC, 0,
AMDVI_CAPAB_SIZE);
assert(s->capab_offset > 0);
ret = pci_add_capability(&s->pci.dev, PCI_CAP_ID_MSI, 0, AMDVI_CAPAB_REG_SIZE);
assert(ret > 0);
ret = pci_add_capability(&s->pci.dev, PCI_CAP_ID_HT, 0, AMDVI_CAPAB_REG_SIZE);
assert(ret > 0);
ret = pci_add_capability(&s->pci.dev, AMDVI_CAPAB_ID_SEC, 0,
AMDVI_CAPAB_SIZE, err);
if (ret < 0) {
return;
}
s->capab_offset = ret;
ret = pci_add_capability(&s->pci.dev, PCI_CAP_ID_MSI, 0,
AMDVI_CAPAB_REG_SIZE, err);
if (ret < 0) {
return;
}
ret = pci_add_capability(&s->pci.dev, PCI_CAP_ID_HT, 0,
AMDVI_CAPAB_REG_SIZE, err);
if (ret < 0) {
return;
}
/* set up MMIO */
memory_region_init_io(&s->mmio, OBJECT(s), &mmio_mem_ops, s, "amdvi-mmio",

View File

@ -1450,10 +1450,7 @@ static uint64_t vtd_iotlb_flush(IntelIOMMUState *s, uint64_t val)
return iaig;
}
static inline bool vtd_queued_inv_enable_check(IntelIOMMUState *s)
{
return s->iq_tail == 0;
}
static void vtd_fetch_inv_desc(IntelIOMMUState *s);
static inline bool vtd_queued_inv_disable_check(IntelIOMMUState *s)
{
@ -1468,16 +1465,24 @@ static void vtd_handle_gcmd_qie(IntelIOMMUState *s, bool en)
trace_vtd_inv_qi_enable(en);
if (en) {
if (vtd_queued_inv_enable_check(s)) {
s->iq = iqa_val & VTD_IQA_IQA_MASK;
/* 2^(x+8) entries */
s->iq_size = 1UL << ((iqa_val & VTD_IQA_QS) + 8);
s->qi_enabled = true;
trace_vtd_inv_qi_setup(s->iq, s->iq_size);
/* Ok - report back to driver */
vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_QIES);
} else {
trace_vtd_err_qi_enable(s->iq_tail);
s->iq = iqa_val & VTD_IQA_IQA_MASK;
/* 2^(x+8) entries */
s->iq_size = 1UL << ((iqa_val & VTD_IQA_QS) + 8);
s->qi_enabled = true;
trace_vtd_inv_qi_setup(s->iq, s->iq_size);
/* Ok - report back to driver */
vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_QIES);
if (s->iq_tail != 0) {
/*
* This is a spec violation but Windows guests are known to set up
* Queued Invalidation this way so we allow the write and process
* Invalidation Descriptors right away.
*/
trace_vtd_warn_invalid_qi_tail(s->iq_tail);
if (!(vtd_get_long_raw(s, DMAR_FSTS_REG) & VTD_FSTS_IQE)) {
vtd_fetch_inv_desc(s);
}
}
} else {
if (vtd_queued_inv_disable_check(s)) {
@ -2332,11 +2337,26 @@ static void vtd_iommu_notify_flag_changed(MemoryRegion *iommu,
}
}
static int vtd_post_load(void *opaque, int version_id)
{
IntelIOMMUState *iommu = opaque;
/*
* Memory regions are dynamically turned on/off depending on
* context entry configurations from the guest. After migration,
* we need to make sure the memory regions are still correct.
*/
vtd_switch_address_space_all(iommu);
return 0;
}
static const VMStateDescription vtd_vmstate = {
.name = "iommu-intel",
.version_id = 1,
.minimum_version_id = 1,
.priority = MIG_PRI_IOMMU,
.post_load = vtd_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT64(root, IntelIOMMUState),
VMSTATE_UINT64(intr_root, IntelIOMMUState),

View File

@ -824,12 +824,13 @@ static void assign_device(AssignedDevice *dev, Error **errp)
}
}
static void verify_irqchip_in_kernel(Error **errp)
static int verify_irqchip_in_kernel(Error **errp)
{
if (kvm_irqchip_in_kernel()) {
return;
return -1;
}
error_setg(errp, "pci-assign requires KVM with in-kernel irqchip enabled");
return 0;
}
static int assign_intx(AssignedDevice *dev, Error **errp)
@ -838,7 +839,6 @@ static int assign_intx(AssignedDevice *dev, Error **errp)
PCIINTxRoute intx_route;
bool intx_host_msi;
int r;
Error *local_err = NULL;
/* Interrupt PIN 0 means don't use INTx */
if (assigned_dev_pci_read_byte(&dev->dev, PCI_INTERRUPT_PIN) == 0) {
@ -846,9 +846,7 @@ static int assign_intx(AssignedDevice *dev, Error **errp)
return 0;
}
verify_irqchip_in_kernel(&local_err);
if (local_err) {
error_propagate(errp, local_err);
if (verify_irqchip_in_kernel(errp) < 0) {
return -ENOTSUP;
}
@ -1234,7 +1232,6 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
AssignedDevice *dev = PCI_ASSIGN(pci_dev);
PCIRegion *pci_region = dev->real_device.regions;
int ret, pos;
Error *local_err = NULL;
/* Clear initial capabilities pointer and status copied from hw */
pci_set_byte(pci_dev->config + PCI_CAPABILITY_LIST, 0);
@ -1246,18 +1243,15 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
* MSI capability is the 1st capability in capability config */
pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_MSI, 0);
if (pos != 0 && kvm_check_extension(kvm_state, KVM_CAP_ASSIGN_DEV_IRQ)) {
verify_irqchip_in_kernel(&local_err);
if (local_err) {
error_propagate(errp, local_err);
if (verify_irqchip_in_kernel(errp) < 0) {
return -ENOTSUP;
}
dev->dev.cap_present |= QEMU_PCI_CAP_MSI;
dev->cap.available |= ASSIGNED_DEVICE_CAP_MSI;
/* Only 32-bit/no-mask currently supported */
ret = pci_add_capability2(pci_dev, PCI_CAP_ID_MSI, pos, 10,
&local_err);
ret = pci_add_capability(pci_dev, PCI_CAP_ID_MSI, pos, 10,
errp);
if (ret < 0) {
error_propagate(errp, local_err);
return ret;
}
pci_dev->msi_cap = pos;
@ -1281,17 +1275,14 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
uint32_t msix_table_entry;
uint16_t msix_max;
verify_irqchip_in_kernel(&local_err);
if (local_err) {
error_propagate(errp, local_err);
if (verify_irqchip_in_kernel(errp) < 0) {
return -ENOTSUP;
}
dev->dev.cap_present |= QEMU_PCI_CAP_MSIX;
dev->cap.available |= ASSIGNED_DEVICE_CAP_MSIX;
ret = pci_add_capability2(pci_dev, PCI_CAP_ID_MSIX, pos, 12,
&local_err);
ret = pci_add_capability(pci_dev, PCI_CAP_ID_MSIX, pos, 12,
errp);
if (ret < 0) {
error_propagate(errp, local_err);
return ret;
}
pci_dev->msix_cap = pos;
@ -1318,10 +1309,9 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
if (pos) {
uint16_t pmc;
ret = pci_add_capability2(pci_dev, PCI_CAP_ID_PM, pos, PCI_PM_SIZEOF,
&local_err);
ret = pci_add_capability(pci_dev, PCI_CAP_ID_PM, pos, PCI_PM_SIZEOF,
errp);
if (ret < 0) {
error_propagate(errp, local_err);
return ret;
}
@ -1386,10 +1376,9 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
return -EINVAL;
}
ret = pci_add_capability2(pci_dev, PCI_CAP_ID_EXP, pos, size,
&local_err);
ret = pci_add_capability(pci_dev, PCI_CAP_ID_EXP, pos, size,
errp);
if (ret < 0) {
error_propagate(errp, local_err);
return ret;
}
@ -1462,10 +1451,9 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
uint32_t status;
/* Only expose the minimum, 8 byte capability */
ret = pci_add_capability2(pci_dev, PCI_CAP_ID_PCIX, pos, 8,
&local_err);
ret = pci_add_capability(pci_dev, PCI_CAP_ID_PCIX, pos, 8,
errp);
if (ret < 0) {
error_propagate(errp, local_err);
return ret;
}
@ -1490,10 +1478,9 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_VPD, 0);
if (pos) {
/* Direct R/W passthrough */
ret = pci_add_capability2(pci_dev, PCI_CAP_ID_VPD, pos, 8,
&local_err);
ret = pci_add_capability(pci_dev, PCI_CAP_ID_VPD, pos, 8,
errp);
if (ret < 0) {
error_propagate(errp, local_err);
return ret;
}
@ -1508,10 +1495,9 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
pos += PCI_CAP_LIST_NEXT) {
uint8_t len = pci_get_byte(pci_dev->config + pos + PCI_CAP_FLAGS);
/* Direct R/W passthrough */
ret = pci_add_capability2(pci_dev, PCI_CAP_ID_VNDR, pos, len,
&local_err);
ret = pci_add_capability(pci_dev, PCI_CAP_ID_VNDR, pos, len,
errp);
if (ret < 0) {
error_propagate(errp, local_err);
return ret;
}

View File

@ -74,7 +74,7 @@ vtd_err_dmar_slpte_read_error(uint64_t iova, int level) "iova 0x%"PRIx64" level
vtd_err_dmar_slpte_perm_error(uint64_t iova, int level, uint64_t slpte, bool is_write) "iova 0x%"PRIx64" level %d slpte 0x%"PRIx64" write %d"
vtd_err_dmar_slpte_resv_error(uint64_t iova, int level, uint64_t slpte) "iova 0x%"PRIx64" level %d slpte 0x%"PRIx64
vtd_err_dmar_translate(uint8_t bus, uint8_t slot, uint8_t func, uint64_t iova) "dev %02x:%02x.%02x iova 0x%"PRIx64
vtd_err_qi_enable(uint16_t tail) "tail 0x%"PRIx16
vtd_warn_invalid_qi_tail(uint16_t tail) "tail 0x%"PRIx16
vtd_err_qi_disable(uint16_t head, uint16_t tail, int type) "head 0x%"PRIx16" tail 0x%"PRIx16" last_desc_type %d"
vtd_err_qi_tail(uint16_t tail, uint16_t size) "tail 0x%"PRIx16" size 0x%"PRIx16
vtd_err_irte(int index, uint64_t lo, uint64_t hi) "index %d low 0x%"PRIx64" high 0x%"PRIx64

View File

@ -130,7 +130,7 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
pci_register_bar(dev, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY,
&d->ahci.mem);
sata_cap_offset = pci_add_capability2(dev, PCI_CAP_ID_SATA,
sata_cap_offset = pci_add_capability(dev, PCI_CAP_ID_SATA,
ICH9_SATA_CAP_OFFSET, SATA_CAP_SIZE,
errp);
if (sata_cap_offset < 0) {

View File

@ -47,6 +47,7 @@
#include "e1000e_core.h"
#include "trace.h"
#include "qapi/error.h"
#define TYPE_E1000E "e1000e"
#define E1000E(obj) OBJECT_CHECK(E1000EState, (obj), TYPE_E1000E)
@ -372,22 +373,27 @@ e1000e_gen_dsn(uint8_t *mac)
static int
e1000e_add_pm_capability(PCIDevice *pdev, uint8_t offset, uint16_t pmc)
{
int ret = pci_add_capability(pdev, PCI_CAP_ID_PM, offset, PCI_PM_SIZEOF);
Error *local_err = NULL;
int ret = pci_add_capability(pdev, PCI_CAP_ID_PM, offset,
PCI_PM_SIZEOF, &local_err);
if (ret >= 0) {
pci_set_word(pdev->config + offset + PCI_PM_PMC,
PCI_PM_CAP_VER_1_1 |
pmc);
pci_set_word(pdev->wmask + offset + PCI_PM_CTRL,
PCI_PM_CTRL_STATE_MASK |
PCI_PM_CTRL_PME_ENABLE |
PCI_PM_CTRL_DATA_SEL_MASK);
pci_set_word(pdev->w1cmask + offset + PCI_PM_CTRL,
PCI_PM_CTRL_PME_STATUS);
if (local_err) {
error_report_err(local_err);
return ret;
}
pci_set_word(pdev->config + offset + PCI_PM_PMC,
PCI_PM_CAP_VER_1_1 |
pmc);
pci_set_word(pdev->wmask + offset + PCI_PM_CTRL,
PCI_PM_CTRL_STATE_MASK |
PCI_PM_CTRL_PME_ENABLE |
PCI_PM_CTRL_DATA_SEL_MASK);
pci_set_word(pdev->w1cmask + offset + PCI_PM_CTRL,
PCI_PM_CTRL_PME_STATUS);
return ret;
}

View File

@ -48,6 +48,7 @@
#include "sysemu/sysemu.h"
#include "sysemu/dma.h"
#include "qemu/bitops.h"
#include "qapi/error.h"
/* QEMU sends frames smaller than 60 bytes to ethernet nics.
* Such frames are rejected by real nics and their emulations.
@ -494,7 +495,7 @@ static void eepro100_fcp_interrupt(EEPRO100State * s)
}
#endif
static void e100_pci_reset(EEPRO100State * s)
static void e100_pci_reset(EEPRO100State *s, Error **errp)
{
E100PCIDeviceInfo *info = eepro100_get_class(s);
uint32_t device = s->device;
@ -570,8 +571,12 @@ static void e100_pci_reset(EEPRO100State * s)
/* Power Management Capabilities */
int cfg_offset = 0xdc;
int r = pci_add_capability(&s->dev, PCI_CAP_ID_PM,
cfg_offset, PCI_PM_SIZEOF);
assert(r >= 0);
cfg_offset, PCI_PM_SIZEOF,
errp);
if (r < 0) {
return;
}
pci_set_word(pci_conf + cfg_offset + PCI_PM_PMC, 0x7e21);
#if 0 /* TODO: replace dummy code for power management emulation. */
/* TODO: Power Management Control / Status. */
@ -1858,12 +1863,17 @@ static void e100_nic_realize(PCIDevice *pci_dev, Error **errp)
{
EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
E100PCIDeviceInfo *info = eepro100_get_class(s);
Error *local_err = NULL;
TRACE(OTHER, logout("\n"));
s->device = info->device;
e100_pci_reset(s);
e100_pci_reset(s, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
/* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
* i82559 and later support 64 or 256 word EEPROM. */

View File

@ -34,8 +34,11 @@
/* previously fixed value */
#define VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE 256
#define VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE 256
/* for now, only allow larger queues; with virtio-1, guest can downsize */
#define VIRTIO_NET_RX_QUEUE_MIN_SIZE VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE
#define VIRTIO_NET_TX_QUEUE_MIN_SIZE VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE
/*
* Calculate the number of bytes up to and including the given 'field' of
@ -495,6 +498,24 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
}
}
static int virtio_net_max_tx_queue_size(VirtIONet *n)
{
NetClientState *peer = n->nic_conf.peers.ncs[0];
/*
* Backends other than vhost-user don't support max queue size.
*/
if (!peer) {
return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE;
}
if (peer->info->type != NET_CLIENT_DRIVER_VHOST_USER) {
return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE;
}
return VIRTQUEUE_MAX_SIZE;
}
static int peer_attach(VirtIONet *n, int index)
{
NetClientState *nc = qemu_get_subqueue(n->nic, index);
@ -1508,15 +1529,18 @@ static void virtio_net_add_queue(VirtIONet *n, int index)
n->vqs[index].rx_vq = virtio_add_queue(vdev, n->net_conf.rx_queue_size,
virtio_net_handle_rx);
if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) {
n->vqs[index].tx_vq =
virtio_add_queue(vdev, 256, virtio_net_handle_tx_timer);
virtio_add_queue(vdev, n->net_conf.tx_queue_size,
virtio_net_handle_tx_timer);
n->vqs[index].tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
virtio_net_tx_timer,
&n->vqs[index]);
} else {
n->vqs[index].tx_vq =
virtio_add_queue(vdev, 256, virtio_net_handle_tx_bh);
virtio_add_queue(vdev, n->net_conf.tx_queue_size,
virtio_net_handle_tx_bh);
n->vqs[index].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[index]);
}
@ -1927,6 +1951,17 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
return;
}
if (n->net_conf.tx_queue_size < VIRTIO_NET_TX_QUEUE_MIN_SIZE ||
n->net_conf.tx_queue_size > VIRTQUEUE_MAX_SIZE ||
!is_power_of_2(n->net_conf.tx_queue_size)) {
error_setg(errp, "Invalid tx_queue_size (= %" PRIu16 "), "
"must be a power of 2 between %d and %d",
n->net_conf.tx_queue_size, VIRTIO_NET_TX_QUEUE_MIN_SIZE,
VIRTQUEUE_MAX_SIZE);
virtio_cleanup(vdev);
return;
}
n->max_queues = MAX(n->nic_conf.peers.queues, 1);
if (n->max_queues * 2 + 1 > VIRTIO_QUEUE_MAX) {
error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
@ -1947,6 +1982,9 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
error_report("Defaulting to \"bh\"");
}
n->net_conf.tx_queue_size = MIN(virtio_net_max_tx_queue_size(n),
n->net_conf.tx_queue_size);
for (i = 0; i < n->max_queues; i++) {
virtio_net_add_queue(n, i);
}
@ -2106,6 +2144,8 @@ static Property virtio_net_properties[] = {
DEFINE_PROP_STRING("tx", VirtIONet, net_conf.tx),
DEFINE_PROP_UINT16("rx_queue_size", VirtIONet, net_conf.rx_queue_size,
VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE),
DEFINE_PROP_UINT16("tx_queue_size", VirtIONet, net_conf.tx_queue_size,
VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE),
DEFINE_PROP_UINT16("host_mtu", VirtIONet, net_conf.mtu, 0),
DEFINE_PROP_BOOL("x-mtu-bypass-backend", VirtIONet, mtu_bypass_backend,
true),

View File

@ -96,7 +96,6 @@ struct FWCfgIoState {
/*< public >*/
MemoryRegion comb_iomem;
uint32_t iobase, dma_iobase;
};
struct FWCfgMemState {
@ -914,6 +913,7 @@ static void fw_cfg_init1(DeviceState *dev)
{
FWCfgState *s = FW_CFG(dev);
MachineState *machine = MACHINE(qdev_get_machine());
uint32_t version = FW_CFG_VERSION;
assert(!object_resolve_path(FW_CFG_PATH, NULL));
@ -928,6 +928,12 @@ static void fw_cfg_init1(DeviceState *dev)
fw_cfg_bootsplash(s);
fw_cfg_reboot(s);
if (s->dma_enabled) {
version |= FW_CFG_VERSION_DMA;
}
fw_cfg_add_i32(s, FW_CFG_ID, version);
s->machine_ready.notify = fw_cfg_machine_ready;
qemu_add_machine_init_done_notifier(&s->machine_ready);
}
@ -936,30 +942,31 @@ FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase,
AddressSpace *dma_as)
{
DeviceState *dev;
SysBusDevice *sbd;
FWCfgIoState *ios;
FWCfgState *s;
uint32_t version = FW_CFG_VERSION;
bool dma_requested = dma_iobase && dma_as;
dev = qdev_create(NULL, TYPE_FW_CFG_IO);
qdev_prop_set_uint32(dev, "iobase", iobase);
qdev_prop_set_uint32(dev, "dma_iobase", dma_iobase);
if (!dma_requested) {
qdev_prop_set_bit(dev, "dma_enabled", false);
}
fw_cfg_init1(dev);
sbd = SYS_BUS_DEVICE(dev);
ios = FW_CFG_IO(dev);
sysbus_add_io(sbd, iobase, &ios->comb_iomem);
s = FW_CFG(dev);
if (s->dma_enabled) {
/* 64 bits for the address field */
s->dma_as = dma_as;
s->dma_addr = 0;
version |= FW_CFG_VERSION_DMA;
sysbus_add_io(sbd, dma_iobase, &s->dma_iomem);
}
fw_cfg_add_i32(s, FW_CFG_ID, version);
return s;
}
@ -975,7 +982,6 @@ FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr,
DeviceState *dev;
SysBusDevice *sbd;
FWCfgState *s;
uint32_t version = FW_CFG_VERSION;
bool dma_requested = dma_addr && dma_as;
dev = qdev_create(NULL, TYPE_FW_CFG_MEM);
@ -996,11 +1002,8 @@ FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr,
s->dma_as = dma_as;
s->dma_addr = 0;
sysbus_mmio_map(sbd, 2, dma_addr);
version |= FW_CFG_VERSION_DMA;
}
fw_cfg_add_i32(s, FW_CFG_ID, version);
return s;
}
@ -1059,8 +1062,6 @@ static void fw_cfg_file_slots_allocate(FWCfgState *s, Error **errp)
}
static Property fw_cfg_io_properties[] = {
DEFINE_PROP_UINT32("iobase", FWCfgIoState, iobase, -1),
DEFINE_PROP_UINT32("dma_iobase", FWCfgIoState, dma_iobase, -1),
DEFINE_PROP_BOOL("dma_enabled", FWCfgIoState, parent_obj.dma_enabled,
true),
DEFINE_PROP_UINT16("x-file-slots", FWCfgIoState, parent_obj.file_slots,
@ -1071,7 +1072,6 @@ static Property fw_cfg_io_properties[] = {
static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
{
FWCfgIoState *s = FW_CFG_IO(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
Error *local_err = NULL;
fw_cfg_file_slots_allocate(FW_CFG(s), &local_err);
@ -1085,13 +1085,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
* of the i/o region used is FW_CFG_CTL_SIZE */
memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops,
FW_CFG(s), "fwcfg", FW_CFG_CTL_SIZE);
sysbus_add_io(sbd, s->iobase, &s->comb_iomem);
if (FW_CFG(s)->dma_enabled) {
memory_region_init_io(&FW_CFG(s)->dma_iomem, OBJECT(s),
&fw_cfg_dma_mem_ops, FW_CFG(s), "fwcfg.dma",
sizeof(dma_addr_t));
sysbus_add_io(sbd, s->dma_iobase, &FW_CFG(s)->dma_iomem);
}
}

View File

@ -62,6 +62,7 @@ static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
k->realize = dec_pci_bridge_realize;
k->exit = pci_bridge_exitfn;
k->vendor_id = PCI_VENDOR_ID_DEC;
@ -118,6 +119,7 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data)
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
k->realize = dec_21154_pci_host_realize;
k->vendor_id = PCI_VENDOR_ID_DEC;
k->device_id = PCI_DEVICE_ID_DEC_21154;

View File

@ -44,6 +44,7 @@
#include "qemu/osdep.h"
#include "hw/pci/pci.h"
#include "hw/i386/ich9.h"
#include "qapi/error.h"
/*****************************************************************************/
@ -58,24 +59,23 @@ typedef struct I82801b11Bridge {
/*< public >*/
} I82801b11Bridge;
static int i82801b11_bridge_initfn(PCIDevice *d)
static void i82801b11_bridge_realize(PCIDevice *d, Error **errp)
{
int rc;
pci_bridge_initfn(d, TYPE_PCI_BUS);
rc = pci_bridge_ssvid_init(d, I82801ba_SSVID_OFFSET,
I82801ba_SSVID_SVID, I82801ba_SSVID_SSID);
I82801ba_SSVID_SVID, I82801ba_SSVID_SSID,
errp);
if (rc < 0) {
goto err_bridge;
}
pci_config_set_prog_interface(d->config, PCI_CLASS_BRIDGE_PCI_INF_SUB);
return 0;
return;
err_bridge:
pci_bridge_exitfn(d);
return rc;
}
static const VMStateDescription i82801b11_bridge_dev_vmstate = {
@ -95,7 +95,7 @@ static void i82801b11_bridge_class_init(ObjectClass *klass, void *data)
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_82801BA_11;
k->revision = ICH9_D2P_A2_REVISION;
k->init = i82801b11_bridge_initfn;
k->realize = i82801b11_bridge_realize;
k->config_write = pci_bridge_write_config;
dc->vmsd = &i82801b11_bridge_dev_vmstate;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);

View File

@ -49,7 +49,7 @@ struct PCIBridgeDev {
};
typedef struct PCIBridgeDev PCIBridgeDev;
static int pci_bridge_dev_initfn(PCIDevice *dev)
static void pci_bridge_dev_realize(PCIDevice *dev, Error **errp)
{
PCIBridge *br = PCI_BRIDGE(dev);
PCIBridgeDev *bridge_dev = PCI_BRIDGE_DEV(dev);
@ -62,7 +62,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
dev->config[PCI_INTERRUPT_PIN] = 0x1;
memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar",
shpc_bar_size(dev));
err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0);
err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0, errp);
if (err) {
goto shpc_error;
}
@ -71,7 +71,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
bridge_dev->msi = ON_OFF_AUTO_OFF;
}
err = slotid_cap_init(dev, 0, bridge_dev->chassis_nr, 0);
err = slotid_cap_init(dev, 0, bridge_dev->chassis_nr, 0, errp);
if (err) {
goto slotid_error;
}
@ -87,7 +87,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
/* Can't satisfy user's explicit msi=on request, fail */
error_append_hint(&local_err, "You have to use msi=auto (default) "
"or msi=off with this machine type.\n");
error_report_err(local_err);
error_propagate(errp, local_err);
goto msi_error;
}
assert(!local_err || bridge_dev->msi == ON_OFF_AUTO_AUTO);
@ -101,7 +101,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
}
return 0;
return;
msi_error:
slotid_cap_cleanup(dev);
@ -111,8 +111,6 @@ slotid_error:
}
shpc_error:
pci_bridge_exitfn(dev);
return err;
}
static void pci_bridge_dev_exitfn(PCIDevice *dev)
@ -216,7 +214,7 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
k->init = pci_bridge_dev_initfn;
k->realize = pci_bridge_dev_realize;
k->exit = pci_bridge_dev_exitfn;
k->config_write = pci_bridge_dev_write_config;
k->vendor_id = PCI_VENDOR_ID_REDHAT;

View File

@ -59,29 +59,30 @@ static void rp_realize(PCIDevice *d, Error **errp)
PCIDeviceClass *dc = PCI_DEVICE_GET_CLASS(d);
PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
int rc;
Error *local_err = NULL;
pci_config_set_interrupt_pin(d->config, 1);
pci_bridge_initfn(d, TYPE_PCIE_BUS);
pcie_port_init_reg(d);
rc = pci_bridge_ssvid_init(d, rpc->ssvid_offset, dc->vendor_id, rpc->ssid);
rc = pci_bridge_ssvid_init(d, rpc->ssvid_offset, dc->vendor_id,
rpc->ssid, errp);
if (rc < 0) {
error_setg(errp, "Can't init SSV ID, error %d", rc);
error_append_hint(errp, "Can't init SSV ID, error %d\n", rc);
goto err_bridge;
}
if (rpc->interrupts_init) {
rc = rpc->interrupts_init(d, &local_err);
rc = rpc->interrupts_init(d, errp);
if (rc < 0) {
error_propagate(errp, local_err);
goto err_bridge;
}
}
rc = pcie_cap_init(d, rpc->exp_offset, PCI_EXP_TYPE_ROOT_PORT, p->port);
rc = pcie_cap_init(d, rpc->exp_offset, PCI_EXP_TYPE_ROOT_PORT,
p->port, errp);
if (rc < 0) {
error_setg(errp, "Can't add Root Port capability, error %d", rc);
error_append_hint(errp, "Can't add Root Port capability, "
"error %d\n", rc);
goto err_int;
}
@ -98,9 +99,8 @@ static void rp_realize(PCIDevice *d, Error **errp)
}
rc = pcie_aer_init(d, PCI_ERR_VER, rpc->aer_offset,
PCI_ERR_SIZEOF, &local_err);
PCI_ERR_SIZEOF, errp);
if (rc < 0) {
error_propagate(errp, local_err);
goto err;
}
pcie_aer_root_init(d);

View File

@ -56,33 +56,33 @@ static void xio3130_downstream_reset(DeviceState *qdev)
pci_bridge_reset(qdev);
}
static int xio3130_downstream_initfn(PCIDevice *d)
static void xio3130_downstream_realize(PCIDevice *d, Error **errp)
{
PCIEPort *p = PCIE_PORT(d);
PCIESlot *s = PCIE_SLOT(d);
int rc;
Error *err = NULL;
pci_bridge_initfn(d, TYPE_PCIE_BUS);
pcie_port_init_reg(d);
rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, &err);
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT,
errp);
if (rc < 0) {
assert(rc == -ENOTSUP);
error_report_err(err);
goto err_bridge;
}
rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,
XIO3130_SSVID_SVID, XIO3130_SSVID_SSID);
XIO3130_SSVID_SVID, XIO3130_SSVID_SSID,
errp);
if (rc < 0) {
goto err_bridge;
}
rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_DOWNSTREAM,
p->port);
p->port, errp);
if (rc < 0) {
goto err_msi;
}
@ -98,13 +98,12 @@ static int xio3130_downstream_initfn(PCIDevice *d)
}
rc = pcie_aer_init(d, PCI_ERR_VER, XIO3130_AER_OFFSET,
PCI_ERR_SIZEOF, &err);
PCI_ERR_SIZEOF, errp);
if (rc < 0) {
error_report_err(err);
goto err;
}
return 0;
return;
err:
pcie_chassis_del_slot(s);
@ -114,7 +113,6 @@ err_msi:
msi_uninit(d);
err_bridge:
pci_bridge_exitfn(d);
return rc;
}
static void xio3130_downstream_exitfn(PCIDevice *d)
@ -181,7 +179,7 @@ static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
k->is_express = 1;
k->is_bridge = 1;
k->config_write = xio3130_downstream_write_config;
k->init = xio3130_downstream_initfn;
k->realize = xio3130_downstream_realize;
k->exit = xio3130_downstream_exitfn;
k->vendor_id = PCI_VENDOR_ID_TI;
k->device_id = PCI_DEVICE_ID_TI_XIO3130D;

View File

@ -53,32 +53,32 @@ static void xio3130_upstream_reset(DeviceState *qdev)
pcie_cap_deverr_reset(d);
}
static int xio3130_upstream_initfn(PCIDevice *d)
static void xio3130_upstream_realize(PCIDevice *d, Error **errp)
{
PCIEPort *p = PCIE_PORT(d);
int rc;
Error *err = NULL;
pci_bridge_initfn(d, TYPE_PCIE_BUS);
pcie_port_init_reg(d);
rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, &err);
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT,
errp);
if (rc < 0) {
assert(rc == -ENOTSUP);
error_report_err(err);
goto err_bridge;
}
rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,
XIO3130_SSVID_SVID, XIO3130_SSVID_SSID);
XIO3130_SSVID_SVID, XIO3130_SSVID_SSID,
errp);
if (rc < 0) {
goto err_bridge;
}
rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_UPSTREAM,
p->port);
p->port, errp);
if (rc < 0) {
goto err_msi;
}
@ -86,13 +86,12 @@ static int xio3130_upstream_initfn(PCIDevice *d)
pcie_cap_deverr_init(d);
rc = pcie_aer_init(d, PCI_ERR_VER, XIO3130_AER_OFFSET,
PCI_ERR_SIZEOF, &err);
PCI_ERR_SIZEOF, errp);
if (rc < 0) {
error_report_err(err);
goto err;
}
return 0;
return;
err:
pcie_cap_exit(d);
@ -100,7 +99,6 @@ err_msi:
msi_uninit(d);
err_bridge:
pci_bridge_exitfn(d);
return rc;
}
static void xio3130_upstream_exitfn(PCIDevice *d)
@ -153,7 +151,7 @@ static void xio3130_upstream_class_init(ObjectClass *klass, void *data)
k->is_express = 1;
k->is_bridge = 1;
k->config_write = xio3130_upstream_write_config;
k->init = xio3130_upstream_initfn;
k->realize = xio3130_upstream_realize;
k->exit = xio3130_upstream_exitfn;
k->vendor_id = PCI_VENDOR_ID_TI;
k->device_id = PCI_DEVICE_ID_TI_XIO3130U;

View File

@ -216,7 +216,7 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
}
cap_size = msi_cap_sizeof(flags);
config_offset = pci_add_capability2(dev, PCI_CAP_ID_MSI, offset,
config_offset = pci_add_capability(dev, PCI_CAP_ID_MSI, offset,
cap_size, errp);
if (config_offset < 0) {
return config_offset;

View File

@ -301,7 +301,7 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
return -EINVAL;
}
cap = pci_add_capability2(dev, PCI_CAP_ID_MSIX,
cap = pci_add_capability(dev, PCI_CAP_ID_MSIX,
cap_pos, MSIX_CAP_LENGTH, errp);
if (cap < 0) {
return cap;

View File

@ -2259,28 +2259,12 @@ static void pci_del_option_rom(PCIDevice *pdev)
}
/*
* if offset = 0,
* Find and reserve space and add capability to the linked list
* in pci config space
* On success, pci_add_capability() returns a positive value
* that the offset of the pci capability.
* On failure, it sets an error and returns a negative error
* code.
*/
int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
uint8_t offset, uint8_t size)
{
int ret;
Error *local_err = NULL;
ret = pci_add_capability2(pdev, cap_id, offset, size, &local_err);
if (local_err) {
assert(ret < 0);
error_report_err(local_err);
} else {
/* success implies a positive offset in config space */
assert(ret > 0);
}
return ret;
}
int pci_add_capability2(PCIDevice *pdev, uint8_t cap_id,
uint8_t offset, uint8_t size,
Error **errp)
{

View File

@ -33,6 +33,7 @@
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pci_bus.h"
#include "qemu/range.h"
#include "qapi/error.h"
/* PCI bridge subsystem vendor ID helper functions */
#define PCI_SSVID_SIZEOF 8
@ -40,10 +41,13 @@
#define PCI_SSVID_SSID 6
int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
uint16_t svid, uint16_t ssid)
uint16_t svid, uint16_t ssid,
Error **errp)
{
int pos;
pos = pci_add_capability(dev, PCI_CAP_ID_SSVID, offset, PCI_SSVID_SIZEOF);
pos = pci_add_capability(dev, PCI_CAP_ID_SSVID, offset,
PCI_SSVID_SIZEOF, errp);
if (pos < 0) {
return pos;
}

View File

@ -86,7 +86,9 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version)
pci_set_word(cmask + PCI_EXP_LNKSTA, 0);
}
int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
int pcie_cap_init(PCIDevice *dev, uint8_t offset,
uint8_t type, uint8_t port,
Error **errp)
{
/* PCIe cap v2 init */
int pos;
@ -94,7 +96,8 @@ int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
assert(pci_is_express(dev));
pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset, PCI_EXP_VER2_SIZEOF);
pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
PCI_EXP_VER2_SIZEOF, errp);
if (pos < 0) {
return pos;
}
@ -123,11 +126,14 @@ int pcie_cap_v1_init(PCIDevice *dev, uint8_t offset, uint8_t type,
{
/* PCIe cap v1 init */
int pos;
Error *local_err = NULL;
assert(pci_is_express(dev));
pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset, PCI_EXP_VER1_SIZEOF);
pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
PCI_EXP_VER1_SIZEOF, &local_err);
if (pos < 0) {
error_report_err(local_err);
return pos;
}
dev->exp.exp_cap = pos;
@ -141,6 +147,8 @@ static int
pcie_endpoint_cap_common_init(PCIDevice *dev, uint8_t offset, uint8_t cap_size)
{
uint8_t type = PCI_EXP_TYPE_ENDPOINT;
Error *local_err = NULL;
int ret;
/*
* Windows guests will report Code 10, device cannot start, if
@ -151,9 +159,17 @@ pcie_endpoint_cap_common_init(PCIDevice *dev, uint8_t offset, uint8_t cap_size)
type = PCI_EXP_TYPE_RC_END;
}
return (cap_size == PCI_EXP_VER1_SIZEOF)
? pcie_cap_v1_init(dev, offset, type, 0)
: pcie_cap_init(dev, offset, type, 0);
if (cap_size == PCI_EXP_VER1_SIZEOF) {
return pcie_cap_v1_init(dev, offset, type, 0);
} else {
ret = pcie_cap_init(dev, offset, type, 0, &local_err);
if (ret < 0) {
error_report_err(local_err);
}
return ret;
}
}
int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset)

View File

@ -446,12 +446,13 @@ static void shpc_cap_update_dword(PCIDevice *d)
}
/* Add SHPC capability to the config space for the device. */
static int shpc_cap_add_config(PCIDevice *d)
static int shpc_cap_add_config(PCIDevice *d, Error **errp)
{
uint8_t *config;
int config_offset;
config_offset = pci_add_capability(d, PCI_CAP_ID_SHPC,
0, SHPC_CAP_LENGTH);
0, SHPC_CAP_LENGTH,
errp);
if (config_offset < 0) {
return config_offset;
}
@ -581,13 +582,14 @@ void shpc_device_hot_unplug_request_cb(HotplugHandler *hotplug_dev,
}
/* Initialize the SHPC structure in bridge's BAR. */
int shpc_init(PCIDevice *d, PCIBus *sec_bus, MemoryRegion *bar, unsigned offset)
int shpc_init(PCIDevice *d, PCIBus *sec_bus, MemoryRegion *bar,
unsigned offset, Error **errp)
{
int i, ret;
int nslots = SHPC_MAX_SLOTS; /* TODO: qdev property? */
SHPCDevice *shpc = d->shpc = g_malloc0(sizeof(*d->shpc));
shpc->sec_bus = sec_bus;
ret = shpc_cap_add_config(d);
ret = shpc_cap_add_config(d, errp);
if (ret) {
g_free(d->shpc);
return ret;

View File

@ -2,18 +2,21 @@
#include "hw/pci/slotid_cap.h"
#include "hw/pci/pci.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#define SLOTID_CAP_LENGTH 4
#define SLOTID_NSLOTS_SHIFT ctz32(PCI_SID_ESR_NSLOTS)
int slotid_cap_init(PCIDevice *d, int nslots,
uint8_t chassis,
unsigned offset)
unsigned offset,
Error **errp)
{
int cap;
if (!chassis) {
error_report("Bridge chassis not specified. Each bridge is required "
"to be assigned a unique chassis id > 0.");
error_setg(errp, "Bridge chassis not specified. Each bridge is required"
" to be assigned a unique chassis id > 0.");
return -EINVAL;
}
if (nslots < 0 || nslots > (PCI_SID_ESR_NSLOTS >> SLOTID_NSLOTS_SHIFT)) {
@ -21,7 +24,8 @@ int slotid_cap_init(PCIDevice *d, int nslots,
return -EINVAL;
}
cap = pci_add_capability(d, PCI_CAP_ID_SLOTID, offset, SLOTID_CAP_LENGTH);
cap = pci_add_capability(d, PCI_CAP_ID_SLOTID, offset,
SLOTID_CAP_LENGTH, errp);
if (cap < 0) {
return cap;
}

View File

@ -3419,7 +3419,7 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
if (pci_bus_is_express(dev->bus) ||
xhci_get_flag(xhci, XHCI_FLAG_FORCE_PCIE_ENDCAP)) {
ret = pcie_endpoint_cap_init(dev, 0xa0);
assert(ret >= 0);
assert(ret > 0);
}
if (xhci->msix != ON_OFF_AUTO_OFF) {

View File

@ -1743,11 +1743,14 @@ static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
}
pos = pci_add_capability(&vdev->pdev, PCI_CAP_ID_EXP, pos, size);
if (pos >= 0) {
vdev->pdev.exp.exp_cap = pos;
pos = pci_add_capability(&vdev->pdev, PCI_CAP_ID_EXP, pos, size,
errp);
if (pos < 0) {
return pos;
}
vdev->pdev.exp.exp_cap = pos;
return pos;
}
@ -1834,14 +1837,14 @@ static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos, Error **errp)
case PCI_CAP_ID_PM:
vfio_check_pm_reset(vdev, pos);
vdev->pm_cap = pos;
ret = pci_add_capability2(pdev, cap_id, pos, size, errp);
ret = pci_add_capability(pdev, cap_id, pos, size, errp);
break;
case PCI_CAP_ID_AF:
vfio_check_af_flr(vdev, pos);
ret = pci_add_capability2(pdev, cap_id, pos, size, errp);
ret = pci_add_capability(pdev, cap_id, pos, size, errp);
break;
default:
ret = pci_add_capability2(pdev, cap_id, pos, size, errp);
ret = pci_add_capability(pdev, cap_id, pos, size, errp);
break;
}
out:

View File

@ -309,7 +309,10 @@ int vhost_backend_update_device_iotlb(struct vhost_dev *dev,
return -EINVAL;
}
return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg)
return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
return -ENODEV;
}
int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev,
@ -321,7 +324,10 @@ int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev,
imsg.size = len;
imsg.type = VHOST_IOTLB_INVALIDATE;
return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg)
return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
return -ENODEV;
}
int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev,

View File

@ -779,6 +779,7 @@ static int vhost_user_cleanup(struct vhost_dev *dev)
u = dev->opaque;
if (u->slave_fd >= 0) {
qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
close(u->slave_fd);
u->slave_fd = -1;
}

View File

@ -1162,8 +1162,8 @@ static int virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy,
PCIDevice *dev = &proxy->pci_dev;
int offset;
offset = pci_add_capability(dev, PCI_CAP_ID_VNDR, 0, cap->cap_len);
assert(offset > 0);
offset = pci_add_capability(dev, PCI_CAP_ID_VNDR, 0,
cap->cap_len, &error_abort);
assert(cap->cap_len >= sizeof *cap);
memcpy(dev->config + offset + PCI_CAP_FLAGS, &cap->cap_len,
@ -1810,8 +1810,12 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
pos = pcie_endpoint_cap_init(pci_dev, 0);
assert(pos > 0);
pos = pci_add_capability(pci_dev, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF);
assert(pos > 0);
pos = pci_add_capability(pci_dev, PCI_CAP_ID_PM, 0,
PCI_PM_SIZEOF, errp);
if (pos < 0) {
return;
}
pci_dev->exp.pm_cap = pos;
/*

View File

@ -356,8 +356,6 @@ void pci_unregister_vga(PCIDevice *pci_dev);
pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
uint8_t offset, uint8_t size);
int pci_add_capability2(PCIDevice *pdev, uint8_t cap_id,
uint8_t offset, uint8_t size,
Error **errp);

View File

@ -33,7 +33,8 @@
#define PCI_BRIDGE_DEV_PROP_SHPC "shpc"
int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
uint16_t svid, uint16_t ssid);
uint16_t svid, uint16_t ssid,
Error **errp);
PCIDevice *pci_bridge_get_device(PCIBus *bus);
PCIBus *pci_bridge_get_sec_bus(PCIBridge *br);

View File

@ -84,7 +84,8 @@ struct PCIExpressDevice {
#define COMPAT_PROP_PCP "power_controller_present"
/* PCI express capability helper functions */
int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port);
int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type,
uint8_t port, Error **errp);
int pcie_cap_v1_init(PCIDevice *dev, uint8_t offset,
uint8_t type, uint8_t port);
int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset);

View File

@ -38,7 +38,8 @@ struct SHPCDevice {
void shpc_reset(PCIDevice *d);
int shpc_bar_size(PCIDevice *dev);
int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar, unsigned off);
int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar,
unsigned off, Error **errp);
void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar);
void shpc_free(PCIDevice *dev);
void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len);

View File

@ -5,7 +5,8 @@
int slotid_cap_init(PCIDevice *dev, int nslots,
uint8_t chassis,
unsigned offset);
unsigned offset,
Error **errp);
void slotid_cap_cleanup(PCIDevice *dev);
#endif

View File

@ -36,6 +36,7 @@ typedef struct virtio_net_conf
int32_t txburst;
char *tx;
uint16_t rx_queue_size;
uint16_t tx_queue_size;
uint16_t mtu;
} virtio_net_conf;

View File

@ -250,6 +250,7 @@ check-qtest-i386-y += tests/usb-hcd-xhci-test$(EXESUF)
gcov-files-i386-y += hw/usb/hcd-xhci.c
check-qtest-i386-y += tests/pc-cpu-test$(EXESUF)
check-qtest-i386-y += tests/q35-test$(EXESUF)
check-qtest-i386-y += tests/vmgenid-test$(EXESUF)
gcov-files-i386-y += hw/pci-host/q35.c
check-qtest-i386-$(CONFIG_VHOST_NET_TEST_i386) += tests/vhost-user-test$(EXESUF)
ifeq ($(CONFIG_VHOST_NET_TEST_i386),)
@ -760,6 +761,7 @@ tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y)
tests/test-arm-mptimer$(EXESUF): tests/test-arm-mptimer.o
tests/test-qapi-util$(EXESUF): tests/test-qapi-util.o $(test-util-obj-y)
tests/numa-test$(EXESUF): tests/numa-test.o
tests/vmgenid-test$(EXESUF): tests/vmgenid-test.o tests/acpi-utils.o
tests/migration/stress$(EXESUF): tests/migration/stress.o
$(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"LINK","$(TARGET_DIR)$@")

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

203
tests/vmgenid-test.c Normal file
View File

@ -0,0 +1,203 @@
/*
* QTest testcase for VM Generation ID
*
* Copyright (c) 2016 Red Hat, Inc.
* Copyright (c) 2017 Skyport Systems
*
* 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 <glib.h>
#include <string.h>
#include <unistd.h>
#include "qemu/osdep.h"
#include "qemu/bitmap.h"
#include "qemu/uuid.h"
#include "hw/acpi/acpi-defs.h"
#include "acpi-utils.h"
#include "libqtest.h"
#define VGID_GUID "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
#define VMGENID_GUID_OFFSET 40 /* allow space for
* OVMF SDT Header Probe Supressor
*/
#define RSDP_ADDR_INVALID 0x100000 /* RSDP must be below this address */
#define RSDP_SLEEP_US 100000 /* Sleep for 100ms between tries */
#define RSDP_TRIES_MAX 100 /* Max total time is 10 seconds */
typedef struct {
AcpiTableHeader header;
gchar name_op;
gchar vgia[4];
gchar val_op;
uint32_t vgia_val;
} QEMU_PACKED VgidTable;
static uint32_t acpi_find_vgia(void)
{
uint32_t rsdp_offset;
uint32_t guid_offset = 0;
AcpiRsdpDescriptor rsdp_table;
uint32_t rsdt;
AcpiRsdtDescriptorRev1 rsdt_table;
int tables_nr;
uint32_t *tables;
AcpiTableHeader ssdt_table;
VgidTable vgid_table;
int i;
/* Tables may take a short time to be set up by the guest */
for (i = 0; i < RSDP_TRIES_MAX; i++) {
rsdp_offset = acpi_find_rsdp_address();
if (rsdp_offset < RSDP_ADDR_INVALID) {
break;
}
g_usleep(RSDP_SLEEP_US);
}
g_assert_cmphex(rsdp_offset, <, RSDP_ADDR_INVALID);
acpi_parse_rsdp_table(rsdp_offset, &rsdp_table);
rsdt = rsdp_table.rsdt_physical_address;
/* read the header */
ACPI_READ_TABLE_HEADER(&rsdt_table, rsdt);
ACPI_ASSERT_CMP(rsdt_table.signature, "RSDT");
/* compute the table entries in rsdt */
tables_nr = (rsdt_table.length - sizeof(AcpiRsdtDescriptorRev1)) /
sizeof(uint32_t);
g_assert_cmpint(tables_nr, >, 0);
/* get the addresses of the tables pointed by rsdt */
tables = g_new0(uint32_t, tables_nr);
ACPI_READ_ARRAY_PTR(tables, tables_nr, rsdt);
for (i = 0; i < tables_nr; i++) {
ACPI_READ_TABLE_HEADER(&ssdt_table, tables[i]);
if (!strncmp((char *)ssdt_table.oem_table_id, "VMGENID", 7)) {
/* the first entry in the table should be VGIA
* That's all we need
*/
ACPI_READ_FIELD(vgid_table.name_op, tables[i]);
g_assert(vgid_table.name_op == 0x08); /* name */
ACPI_READ_ARRAY(vgid_table.vgia, tables[i]);
g_assert(memcmp(vgid_table.vgia, "VGIA", 4) == 0);
ACPI_READ_FIELD(vgid_table.val_op, tables[i]);
g_assert(vgid_table.val_op == 0x0C); /* dword */
ACPI_READ_FIELD(vgid_table.vgia_val, tables[i]);
/* The GUID is written at a fixed offset into the fw_cfg file
* in order to implement the "OVMF SDT Header probe suppressor"
* see docs/specs/vmgenid.txt for more details
*/
guid_offset = vgid_table.vgia_val + VMGENID_GUID_OFFSET;
break;
}
}
g_free(tables);
return guid_offset;
}
static void read_guid_from_memory(QemuUUID *guid)
{
uint32_t vmgenid_addr;
int i;
vmgenid_addr = acpi_find_vgia();
g_assert(vmgenid_addr);
/* Read the GUID directly from guest memory */
for (i = 0; i < 16; i++) {
guid->data[i] = readb(vmgenid_addr + i);
}
/* The GUID is in little-endian format in the guest, while QEMU
* uses big-endian. Swap after reading.
*/
qemu_uuid_bswap(guid);
}
static void read_guid_from_monitor(QemuUUID *guid)
{
QDict *rsp, *rsp_ret;
const char *guid_str;
rsp = qmp("{ 'execute': 'query-vm-generation-id' }");
if (qdict_haskey(rsp, "return")) {
rsp_ret = qdict_get_qdict(rsp, "return");
g_assert(qdict_haskey(rsp_ret, "guid"));
guid_str = qdict_get_str(rsp_ret, "guid");
g_assert(qemu_uuid_parse(guid_str, guid) == 0);
}
QDECREF(rsp);
}
static void vmgenid_set_guid_test(void)
{
QemuUUID expected, measured;
gchar *cmd;
g_assert(qemu_uuid_parse(VGID_GUID, &expected) == 0);
cmd = g_strdup_printf("-machine accel=tcg -device vmgenid,id=testvgid,"
"guid=%s", VGID_GUID);
qtest_start(cmd);
/* Read the GUID from accessing guest memory */
read_guid_from_memory(&measured);
g_assert(memcmp(measured.data, expected.data, sizeof(measured.data)) == 0);
qtest_quit(global_qtest);
g_free(cmd);
}
static void vmgenid_set_guid_auto_test(void)
{
const char *cmd;
QemuUUID measured;
cmd = "-machine accel=tcg -device vmgenid,id=testvgid," "guid=auto";
qtest_start(cmd);
read_guid_from_memory(&measured);
/* Just check that the GUID is non-null */
g_assert(!qemu_uuid_is_null(&measured));
qtest_quit(global_qtest);
}
static void vmgenid_query_monitor_test(void)
{
QemuUUID expected, measured;
gchar *cmd;
g_assert(qemu_uuid_parse(VGID_GUID, &expected) == 0);
cmd = g_strdup_printf("-machine accel=tcg -device vmgenid,id=testvgid,"
"guid=%s", VGID_GUID);
qtest_start(cmd);
/* Read the GUID via the monitor */
read_guid_from_monitor(&measured);
g_assert(memcmp(measured.data, expected.data, sizeof(measured.data)) == 0);
qtest_quit(global_qtest);
g_free(cmd);
}
int main(int argc, char **argv)
{
int ret;
g_test_init(&argc, &argv, NULL);
qtest_add_func("/vmgenid/vmgenid/set-guid",
vmgenid_set_guid_test);
qtest_add_func("/vmgenid/vmgenid/set-guid-auto",
vmgenid_set_guid_auto_test);
qtest_add_func("/vmgenid/vmgenid/query-monitor",
vmgenid_query_monitor_test);
ret = g_test_run();
return ret;
}