From a1da2f06db53c614045e0957423503778ede0d0a Mon Sep 17 00:00:00 2001 From: Marcel Apfelbaum Date: Wed, 14 Sep 2016 08:01:24 +0200 Subject: [PATCH 05/18] virtio-pci: reduce modern_mem_bar size RH-Author: Marcel Apfelbaum Message-id: <1473840085-24716-2-git-send-email-marcel@redhat.com> Patchwork-id: 72307 O-Subject: [RHEL-7.3 qemu-kvm PATCH V2 1/2] virtio-pci: reduce modern_mem_bar size Bugzilla: 1365613 RH-Acked-by: Laszlo Ersek RH-Acked-by: Maxime Coquelin RH-Acked-by: Gerd Hoffmann Currently each VQ Notification Virtio Capability is allocated on a different page. The idea is to enable split drivers within guests, however there are no known plans to do that. The allocation will result in a 8MB BAR, more than various guest firmwares pre-allocates for PCI Bridges hotplug process. Reserve 4 bytes per VQ by default and add a new parameter "page-per-vq" to be used with split drivers. Signed-off-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin (cherry picked from commit d9997d89a4a09a330a056929d06d4b7b0b7a8239) Signed-off-by: Marcel Apfelbaum Conflicts: hw/virtio/virtio-pci.c - Missing commit: 9f06e71a56 (virtio-pci: convert to ioeventfd callbacks) include/hw/compat.h - Don't backport upstream machines HW_COMPAT stuff, put it in RHEL 7.2 machine. Signed-off-by: Marcel Apfelbaum Signed-off-by: Miroslav Rezanina --- hw/virtio/virtio-pci.c | 22 +++++++++++++++------- hw/virtio/virtio-pci.h | 5 +++++ include/hw/compat.h | 5 +++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index abc1221..e28216b 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -264,6 +264,12 @@ static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f) #define QEMU_VIRTIO_PCI_QUEUE_MEM_MULT 0x1000 +static inline int virtio_pci_queue_mem_mult(struct VirtIOPCIProxy *proxy) +{ + return (proxy->flags & VIRTIO_PCI_FLAG_PAGE_PER_VQ) ? + QEMU_VIRTIO_PCI_QUEUE_MEM_MULT : 4; +} + static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy, int n, bool assign, bool set_handler) { @@ -277,7 +283,7 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy, MemoryRegion *modern_mr = &proxy->notify.mr; MemoryRegion *modern_notify_mr = &proxy->notify_pio.mr; MemoryRegion *legacy_mr = &proxy->bar; - hwaddr modern_addr = QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * + hwaddr modern_addr = virtio_pci_queue_mem_mult(proxy) * virtio_get_queue_index(vq); hwaddr legacy_addr = VIRTIO_PCI_QUEUE_NOTIFY; int r = 0; @@ -1418,7 +1424,8 @@ static void virtio_pci_notify_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { VirtIODevice *vdev = opaque; - unsigned queue = addr / QEMU_VIRTIO_PCI_QUEUE_MEM_MULT; + VirtIOPCIProxy *proxy = VIRTIO_PCI(DEVICE(vdev)->parent_bus->parent); + unsigned queue = addr / virtio_pci_queue_mem_mult(proxy); if (queue < VIRTIO_QUEUE_MAX) { virtio_queue_notify(vdev, queue); @@ -1687,7 +1694,7 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) struct virtio_pci_notify_cap notify = { .cap.cap_len = sizeof notify, .notify_off_multiplier = - cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT), + cpu_to_le32(virtio_pci_queue_mem_mult(proxy)), }; struct virtio_pci_cfg_cap cfg = { .cap.cap_len = sizeof cfg, @@ -1819,8 +1826,7 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) proxy->device.type = VIRTIO_PCI_CAP_DEVICE_CFG; proxy->notify.offset = 0x3000; - proxy->notify.size = - QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX; + proxy->notify.size = virtio_pci_queue_mem_mult(proxy) * VIRTIO_QUEUE_MAX; proxy->notify.type = VIRTIO_PCI_CAP_NOTIFY_CFG; proxy->notify_pio.offset = 0x0; @@ -1829,8 +1835,8 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) /* subclasses can enforce modern, so do this unconditionally */ memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci", - 2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * - VIRTIO_QUEUE_MAX); + /* PCI BAR regions must be powers of 2 */ + pow2ceil(proxy->notify.offset + proxy->notify.size)); memory_region_init_alias(&proxy->modern_cfg, OBJECT(proxy), @@ -1916,6 +1922,8 @@ static Property virtio_pci_properties[] = { VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT, false), DEFINE_PROP_BIT("x-disable-pcie", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT, false), + DEFINE_PROP_BIT("page-per-vq", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 4e976b3..5527ff0 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -64,6 +64,7 @@ enum { VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT, VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT, VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT, + VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT, }; /* Need to activate work-arounds for buggy guests at vmstate load. */ @@ -84,6 +85,10 @@ enum { #define VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY \ (1 << VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT) +/* page per vq flag to be used by split drivers within guests */ +#define VIRTIO_PCI_FLAG_PAGE_PER_VQ \ + (1 << VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT) + typedef struct { MSIMessage msg; int virq; diff --git a/include/hw/compat.h b/include/hw/compat.h index b0a76c2..a71e534 100644 --- a/include/hw/compat.h +++ b/include/hw/compat.h @@ -208,5 +208,10 @@ .driver = TYPE_PCI_DEVICE,\ .property = "x-pcie-lnksta-dllla",\ .value = "off",\ + },{ /* HW_COMPAT_RHEL7_2 */ \ + .driver = "virtio-pci",\ + .property = "page-per-vq",\ + .value = "on",\ }, + #endif /* HW_COMPAT_H */ -- 1.8.3.1