diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-07-04 11:17:02 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-07-04 11:17:02 +0100 |
commit | 0c7a8b9baa744ae4323bb46cb4fe942355beaa85 (patch) | |
tree | e28faa62f48d74006d5b1c871ef13a23f4f9bb64 /hw | |
parent | fd479c60f5766f7fb247ad146b9e3c33d03d2055 (diff) | |
parent | d2f9ca94165b10c51d6d6cae5fe1cadf1ca42076 (diff) | |
download | qemu-0c7a8b9baa744ae4323bb46cb4fe942355beaa85.zip qemu-0c7a8b9baa744ae4323bb46cb4fe942355beaa85.tar.gz qemu-0c7a8b9baa744ae4323bb46cb4fe942355beaa85.tar.bz2 |
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>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/i386/acpi-build.c | 10 | ||||
-rw-r--r-- | hw/i386/amd_iommu.c | 24 | ||||
-rw-r--r-- | hw/i386/intel_iommu.c | 48 | ||||
-rw-r--r-- | hw/i386/kvm/pci-assign.c | 54 | ||||
-rw-r--r-- | hw/i386/trace-events | 2 | ||||
-rw-r--r-- | hw/ide/ich.c | 2 | ||||
-rw-r--r-- | hw/net/e1000e.c | 30 | ||||
-rw-r--r-- | hw/net/eepro100.c | 18 | ||||
-rw-r--r-- | hw/net/virtio-net.c | 44 | ||||
-rw-r--r-- | hw/nvram/fw_cfg.c | 32 | ||||
-rw-r--r-- | hw/pci-bridge/dec.c | 2 | ||||
-rw-r--r-- | hw/pci-bridge/i82801b11.c | 12 | ||||
-rw-r--r-- | hw/pci-bridge/pci_bridge_dev.c | 14 | ||||
-rw-r--r-- | hw/pci-bridge/pcie_root_port.c | 18 | ||||
-rw-r--r-- | hw/pci-bridge/xio3130_downstream.c | 20 | ||||
-rw-r--r-- | hw/pci-bridge/xio3130_upstream.c | 20 | ||||
-rw-r--r-- | hw/pci/msi.c | 2 | ||||
-rw-r--r-- | hw/pci/msix.c | 2 | ||||
-rw-r--r-- | hw/pci/pci.c | 24 | ||||
-rw-r--r-- | hw/pci/pci_bridge.c | 8 | ||||
-rw-r--r-- | hw/pci/pcie.c | 28 | ||||
-rw-r--r-- | hw/pci/shpc.c | 10 | ||||
-rw-r--r-- | hw/pci/slotid_cap.c | 12 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 2 | ||||
-rw-r--r-- | hw/vfio/pci.c | 15 | ||||
-rw-r--r-- | hw/virtio/vhost-backend.c | 10 | ||||
-rw-r--r-- | hw/virtio/vhost-user.c | 1 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.c | 12 |
28 files changed, 278 insertions, 198 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 0b8bc62..5464977 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1913,16 +1913,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 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"))); aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 7b6d4ea..d93ffc2 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -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", diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index a9b59bd..88dc042 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -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), diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c index 87dcbdd..9f2615c 100644 --- a/hw/i386/kvm/pci-assign.c +++ b/hw/i386/kvm/pci-assign.c @@ -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; } diff --git a/hw/i386/trace-events b/hw/i386/trace-events index 5f111d6..42d8a7e 100644 --- a/hw/i386/trace-events +++ b/hw/i386/trace-events @@ -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 diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 4599169..989fca5 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -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) { diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index 0e0a1dc..6c42b44 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -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,21 +373,26 @@ 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); + if (local_err) { + error_report_err(local_err); + return ret; + } - 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->config + offset + PCI_PM_PMC, + PCI_PM_CAP_VER_1_1 | + pmc); - pci_set_word(pdev->w1cmask + offset + PCI_PM_CTRL, - PCI_PM_CTRL_PME_STATUS); - } + 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; } diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index 4bf71f2d..5a4774a 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -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. */ diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 91eddaf..5630a9e 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -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), diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 316fca9..99bdbc2 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -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); } } diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c index cca9362..eb275e1 100644 --- a/hw/pci-bridge/dec.c +++ b/hw/pci-bridge/dec.c @@ -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; diff --git a/hw/pci-bridge/i82801b11.c b/hw/pci-bridge/i82801b11.c index 2404e7e..2c1b747 100644 --- a/hw/pci-bridge/i82801b11.c +++ b/hw/pci-bridge/i82801b11.c @@ -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); diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c index 5dbd933..4373f1d 100644 --- a/hw/pci-bridge/pci_bridge_dev.c +++ b/hw/pci-bridge/pci_bridge_dev.c @@ -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; diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c index cf36318..4d588cb 100644 --- a/hw/pci-bridge/pcie_root_port.c +++ b/hw/pci-bridge/pcie_root_port.c @@ -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); diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c index cfe8a36..e706f36 100644 --- a/hw/pci-bridge/xio3130_downstream.c +++ b/hw/pci-bridge/xio3130_downstream.c @@ -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; diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c index 401c784..a052224 100644 --- a/hw/pci-bridge/xio3130_upstream.c +++ b/hw/pci-bridge/xio3130_upstream.c @@ -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; diff --git a/hw/pci/msi.c b/hw/pci/msi.c index a87b227..5e05ce5 100644 --- a/hw/pci/msi.c +++ b/hw/pci/msi.c @@ -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; diff --git a/hw/pci/msix.c b/hw/pci/msix.c index fc5fe51..5078d3d 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -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; diff --git a/hw/pci/pci.c b/hw/pci/pci.c index b7fee4b..0c6f74a 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -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) { diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index 5118ef4..720119b 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -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; } diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 18e634f..32191f2 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -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) diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index 42fafac..69fc14b 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -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; diff --git a/hw/pci/slotid_cap.c b/hw/pci/slotid_cap.c index aec1e91..36d021b 100644 --- a/hw/pci/slotid_cap.c +++ b/hw/pci/slotid_cap.c @@ -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; } diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 760135c..204ea69 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -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) { diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 32aca77..8de8272 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -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: diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index 4e31de1..cb055e8 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -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, diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 958ee09..2203011 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -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; } diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 301920e..93480a7 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -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; /* |