From 530a0963184e57e71a5b538e9161f115df533e96 Mon Sep 17 00:00:00 2001 From: Julia Suvorova Date: Wed, 26 Feb 2020 18:46:07 +0100 Subject: [PATCH 1/4] pcie_root_port: Add hotplug disabling option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make hot-plug/hot-unplug on PCIe Root Ports optional to allow libvirt manage it and restrict unplug for the whole machine. This is going to prevent user-initiated unplug in guests (Windows mostly). Hotplug is enabled by default. Usage: -device pcie-root-port,hotplug=off,... If you want to disable hot-unplug on some downstream ports of one switch, disable hot-unplug on PCIe Root Port connected to the upstream port as well as on the selected downstream ports. Discussion related: https://lists.gnu.org/archive/html/qemu-devel/2020-02/msg00530.html Signed-off-by: Julia Suvorova Message-Id: <20200226174607.205941-1-jusual@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Ján Tomko --- hw/pci-bridge/pcie_root_port.c | 2 +- hw/pci-bridge/xio3130_downstream.c | 2 +- hw/pci/pcie.c | 11 +++++++---- hw/pci/pcie_port.c | 1 + include/hw/pci/pcie.h | 2 +- include/hw/pci/pcie_port.h | 3 +++ 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c index 0ba4e4dea4..f1cfe9d14a 100644 --- a/hw/pci-bridge/pcie_root_port.c +++ b/hw/pci-bridge/pcie_root_port.c @@ -94,7 +94,7 @@ static void rp_realize(PCIDevice *d, Error **errp) pcie_cap_arifwd_init(d); pcie_cap_deverr_init(d); - pcie_cap_slot_init(d, s->slot); + pcie_cap_slot_init(d, s); pcie_cap_root_init(d); pcie_chassis_create(s->chassis); diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c index 153a4acad2..04aae72cd6 100644 --- a/hw/pci-bridge/xio3130_downstream.c +++ b/hw/pci-bridge/xio3130_downstream.c @@ -94,7 +94,7 @@ static void xio3130_downstream_realize(PCIDevice *d, Error **errp) } pcie_cap_flr_init(d); pcie_cap_deverr_init(d); - pcie_cap_slot_init(d, s->slot); + pcie_cap_slot_init(d, s); pcie_cap_arifwd_init(d); pcie_chassis_create(s->chassis); diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 08718188bb..0eb3a2a5d2 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -495,7 +495,7 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, /* pci express slot for pci express root/downstream port PCI express capability slot registers */ -void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot) +void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s) { uint32_t pos = dev->exp.exp_cap; @@ -505,13 +505,16 @@ void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot) pci_long_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCAP, ~PCI_EXP_SLTCAP_PSN); pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP, - (slot << PCI_EXP_SLTCAP_PSN_SHIFT) | + (s->slot << PCI_EXP_SLTCAP_PSN_SHIFT) | PCI_EXP_SLTCAP_EIP | - PCI_EXP_SLTCAP_HPS | - PCI_EXP_SLTCAP_HPC | PCI_EXP_SLTCAP_PIP | PCI_EXP_SLTCAP_AIP | PCI_EXP_SLTCAP_ABP); + if (s->hotplug) { + pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP, + PCI_EXP_SLTCAP_HPS | + PCI_EXP_SLTCAP_HPC); + } if (dev->cap_present & QEMU_PCIE_SLTCAP_PCP) { pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP, diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c index f8263cb306..eb563ad435 100644 --- a/hw/pci/pcie_port.c +++ b/hw/pci/pcie_port.c @@ -147,6 +147,7 @@ static const TypeInfo pcie_port_type_info = { static Property pcie_slot_props[] = { DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0), DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0), + DEFINE_PROP_BOOL("hotplug", PCIESlot, hotplug, true), DEFINE_PROP_END_OF_LIST() }; diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index 7064875835..14c58ebdb6 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -104,7 +104,7 @@ void pcie_cap_deverr_reset(PCIDevice *dev); void pcie_cap_lnkctl_init(PCIDevice *dev); void pcie_cap_lnkctl_reset(PCIDevice *dev); -void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot); +void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s); void pcie_cap_slot_reset(PCIDevice *dev); void pcie_cap_slot_get(PCIDevice *dev, uint16_t *slt_ctl, uint16_t *slt_sta); void pcie_cap_slot_write_config(PCIDevice *dev, diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h index 4b3d254b08..caae57573b 100644 --- a/include/hw/pci/pcie_port.h +++ b/include/hw/pci/pcie_port.h @@ -55,6 +55,9 @@ struct PCIESlot { /* Disable ACS (really for a pcie_root_port) */ bool disable_acs; + + /* Indicates whether hot-plug is enabled on the slot */ + bool hotplug; QLIST_ENTRY(PCIESlot) next; }; From f7ef7e6e3ba6e994e070cc609eb154339d1c4a11 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Mon, 2 Mar 2020 12:24:54 +0800 Subject: [PATCH 2/4] vhost: correctly turn on VIRTIO_F_IOMMU_PLATFORM We turn on device IOTLB via VIRTIO_F_IOMMU_PLATFORM unconditionally on platform without IOMMU support. This can lead unnecessary IOTLB transactions which will damage the performance. Fixing this by check whether the device is backed by IOMMU and disable device IOTLB. Reported-by: Halil Pasic Tested-by: Halil Pasic Reviewed-by: Halil Pasic Signed-off-by: Jason Wang Message-Id: <20200302042454.24814-1-jasowang@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 0d226dae10..01ebe12f28 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -290,7 +290,14 @@ static int vhost_dev_has_iommu(struct vhost_dev *dev) { VirtIODevice *vdev = dev->vdev; - return virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); + /* + * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support + * incremental memory mapping API via IOTLB API. For platform that + * does not have IOMMU, there's no need to enable this feature + * which may cause unnecessary IOTLB miss/update trnasactions. + */ + return vdev->dma_as != &address_space_memory && + virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); } static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr, @@ -765,6 +772,9 @@ static int vhost_dev_set_features(struct vhost_dev *dev, if (enable_log) { features |= 0x1ULL << VHOST_F_LOG_ALL; } + if (!vhost_dev_has_iommu(dev)) { + features &= ~(0x1ULL << VIRTIO_F_IOMMU_PLATFORM); + } r = dev->vhost_ops->vhost_set_features(dev, features); if (r < 0) { VHOST_OPS_DEBUG("vhost_set_features failed"); From f1e92c3d52d2223306a1ea289a57fca2bc5c40a5 Mon Sep 17 00:00:00 2001 From: Nick Erdmann Date: Sun, 1 Mar 2020 13:03:06 +0100 Subject: [PATCH 3/4] vhost-vsock: fix error message output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit error_setg_errno takes a positive error number, so we should not invert errno's sign. Signed-off-by: Nick Erdmann Message-Id: <04df3f47-c93b-1d02-d250-f9bda8dbc0fa@nirf.de> Reviewed-by: Ján Tomko Fixes: fc0b9b0e1cbb ("vhost-vsock: add virtio sockets device") Reviewed-by: Laurent Vivier Reviewed-by: Stefano Garzarella Reviewed-by: Stefan Hajnoczi Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost-vsock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index 66da96583b..9f9093e196 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -325,7 +325,7 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) } else { vhostfd = open("/dev/vhost-vsock", O_RDWR); if (vhostfd < 0) { - error_setg_errno(errp, -errno, + error_setg_errno(errp, errno, "vhost-vsock: failed to open vhost device"); return; } From a6f65f4fc217713ee2c78b99baae1cc31c761778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 5 Mar 2020 11:27:02 +0100 Subject: [PATCH 4/4] hw/i386/intel_iommu: Simplify vtd_find_as_from_bus_num() logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vtd_find_as_from_bus_num() function was introduced (in commit dbaabb25f) in a code format that could return an incorrect pointer, which was later fixed by commit a2e1cd41ccf. We could have avoided this by writing the if() statement differently. Do it now, in case this function is re-used. The code is easier to review (harder to miss bugs). Reviewed-by: Peter Xu Reviewed-by: Eric Auger Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20200305102702.31512-1-philmd@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/intel_iommu.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 6258c58ac9..204b6841ec 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -987,24 +987,26 @@ static bool vtd_slpte_nonzero_rsvd(uint64_t slpte, uint32_t level) static VTDBus *vtd_find_as_from_bus_num(IntelIOMMUState *s, uint8_t bus_num) { VTDBus *vtd_bus = s->vtd_as_by_bus_num[bus_num]; - if (!vtd_bus) { - /* - * Iterate over the registered buses to find the one which - * currently hold this bus number, and update the bus_num - * lookup table: - */ - GHashTableIter iter; + GHashTableIter iter; - g_hash_table_iter_init(&iter, s->vtd_as_by_busptr); - while (g_hash_table_iter_next(&iter, NULL, (void **)&vtd_bus)) { - if (pci_bus_num(vtd_bus->bus) == bus_num) { - s->vtd_as_by_bus_num[bus_num] = vtd_bus; - return vtd_bus; - } - } - vtd_bus = NULL; + if (vtd_bus) { + return vtd_bus; } - return vtd_bus; + + /* + * Iterate over the registered buses to find the one which + * currently holds this bus number and update the bus_num + * lookup table. + */ + g_hash_table_iter_init(&iter, s->vtd_as_by_busptr); + while (g_hash_table_iter_next(&iter, NULL, (void **)&vtd_bus)) { + if (pci_bus_num(vtd_bus->bus) == bus_num) { + s->vtd_as_by_bus_num[bus_num] = vtd_bus; + return vtd_bus; + } + } + + return NULL; } /* Given the @iova, get relevant @slptep. @slpte_level will be the last level