kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] pci-assign: Multiple fixes and cleanups
@ 2011-11-16 20:45 Alex Williamson
  2011-11-16 20:45 ` [PATCH 1/6] pci-assign: Fix device removal Alex Williamson
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Alex Williamson @ 2011-11-16 20:45 UTC (permalink / raw)
  To: kvm; +Cc: jan.kiszka, alex.williamson, yongjie.ren

These patches are all independent.  Patch 1 & 2 fix serious
usability bugs.  Patches 3-6 are more subtle things that
Markus was able to find with Coverity.

Patch 1 fixes https://bugs.launchpad.net/qemu/+bug/875723

I also tested https://bugs.launchpad.net/qemu/+bug/877155
but I'm unable to reproduce.  An 82576 VF works just fine
in a Windows 2008 guest with this patch series.  Thanks,

Alex

---

Alex Williamson (6):
      pci-assign: Harden I/O port test
      pci-assign: Remove bogus PCIe lnkcap wmask setting
      pci-assign: Fix PCIe lnkcap
      pci-assign: Fix PCI_EXP_FLAGS_TYPE shift
      pci-assign: Fix I/O port
      pci-assign: Fix device removal


 hw/device-assignment.c |  137 ++++++++++++++++++++----------------------------
 1 files changed, 57 insertions(+), 80 deletions(-)


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/6] pci-assign: Fix device removal
  2011-11-16 20:45 [PATCH 0/6] pci-assign: Multiple fixes and cleanups Alex Williamson
@ 2011-11-16 20:45 ` Alex Williamson
  2011-11-16 20:45 ` [PATCH 2/6] pci-assign: Fix I/O port Alex Williamson
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Alex Williamson @ 2011-11-16 20:45 UTC (permalink / raw)
  To: kvm; +Cc: jan.kiszka, alex.williamson, yongjie.ren

We're destroying the memory container before we remove the
subregions it holds.  This fixes:

https://bugs.launchpad.net/qemu/+bug/875723

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/device-assignment.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index 11efd16..cde0681 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -677,10 +677,23 @@ static void free_assigned_device(AssignedDevice *dev)
                 kvm_remove_ioport_region(region->u.r_baseport, region->r_size,
                                          dev->dev.qdev.hotplugged);
             }
+            memory_region_del_subregion(&region->container,
+                                        &region->real_iomem);
+            memory_region_destroy(&region->real_iomem);
+            memory_region_destroy(&region->container);
         } else if (pci_region->type & IORESOURCE_MEM) {
             if (region->u.r_virtbase) {
                 memory_region_del_subregion(&region->container,
                                             &region->real_iomem);
+
+                /* Remove MSI-X table subregion */
+                if (pci_region->base_addr <= dev->msix_table_addr &&
+                    pci_region->base_addr + pci_region->size >
+                    dev->msix_table_addr) {
+                    memory_region_del_subregion(&region->container,
+                                                &dev->mmio);
+                }
+
                 memory_region_destroy(&region->real_iomem);
                 memory_region_destroy(&region->container);
                 if (munmap(region->u.r_virtbase,


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/6] pci-assign: Fix I/O port
  2011-11-16 20:45 [PATCH 0/6] pci-assign: Multiple fixes and cleanups Alex Williamson
  2011-11-16 20:45 ` [PATCH 1/6] pci-assign: Fix device removal Alex Williamson
@ 2011-11-16 20:45 ` Alex Williamson
  2011-11-16 20:45 ` [PATCH 3/6] pci-assign: Fix PCI_EXP_FLAGS_TYPE shift Alex Williamson
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Alex Williamson @ 2011-11-16 20:45 UTC (permalink / raw)
  To: kvm; +Cc: jan.kiszka, alex.williamson, yongjie.ren

The old_portio structure seems broken.  Throw it away and
switch to the new style.  This was hitting an assert when
trying to make use of I/O port regions.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/device-assignment.c |  103 ++++++++++++++++--------------------------------
 1 files changed, 35 insertions(+), 68 deletions(-)

diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index cde0681..571a097 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -65,100 +65,76 @@ static void assigned_dev_load_option_rom(AssignedDevice *dev);
 
 static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev);
 
-static uint32_t assigned_dev_ioport_rw(AssignedDevRegion *dev_region,
-                                       uint32_t addr, int len, uint32_t *val)
+static uint64_t assigned_dev_ioport_rw(AssignedDevRegion *dev_region,
+                                       target_phys_addr_t addr, int size,
+                                       uint64_t *data)
 {
-    uint32_t ret = 0;
-    uint32_t offset = addr;
+    uint64_t val = 0;
     int fd = dev_region->region->resource_fd;
 
     if (fd >= 0) {
-        if (val) {
-            DEBUG("pwrite val=%x, len=%d, e_phys=%x, offset=%x\n",
-                  *val, len, addr, offset);
-            if (pwrite(fd, val, len, offset) != len) {
+        if (data) {
+            DEBUG("pwrite data=%x, size=%d, e_phys=%x, addr=%x\n",
+                  *data, size, addr, addr);
+            if (pwrite(fd, data, size, addr) != size) {
                 fprintf(stderr, "%s - pwrite failed %s\n",
                         __func__, strerror(errno));
             }
         } else {
-            if (pread(fd, &ret, len, offset) != len) {
+            if (pread(fd, &val, size, addr) != size) {
                 fprintf(stderr, "%s - pread failed %s\n",
                         __func__, strerror(errno));
-                ret = (1UL << (len * 8)) - 1;
+                val = (1UL << (size * 8)) - 1;
             }
-            DEBUG("pread ret=%x, len=%d, e_phys=%x, offset=%x\n",
-                  ret, len, addr, offset);
+            DEBUG("pread val=%x, size=%d, e_phys=%x, addr=%x\n",
+                  val, size, addr, addr);
         }
     } else {
-        uint32_t port = offset + dev_region->u.r_baseport;
+        uint32_t port = addr + dev_region->u.r_baseport;
 
-        if (val) {
-            DEBUG("out val=%x, len=%d, e_phys=%x, host=%x\n",
-                  *val, len, addr, port);
-            switch (len) {
+        if (data) {
+            DEBUG("out data=%x, size=%d, e_phys=%x, host=%x\n",
+                  *data, size, addr, port);
+            switch (size) {
                 case 1:
-                    outb(*val, port);
+                    outb(*data, port);
                     break;
                 case 2:
-                    outw(*val, port);
+                    outw(*data, port);
                     break;
                 case 4:
-                    outl(*val, port);
+                    outl(*data, port);
                     break;
             }
         } else {
-            switch (len) {
+            switch (size) {
                 case 1:
-                    ret = inb(port);
+                    val = inb(port);
                     break;
                 case 2:
-                    ret = inw(port);
+                    val = inw(port);
                     break;
                 case 4:
-                    ret = inl(port);
+                    val = inl(port);
                     break;
             }
-            DEBUG("in val=%x, len=%d, e_phys=%x, host=%x\n",
-                  ret, len, addr, port);
+            DEBUG("in data=%x, size=%d, e_phys=%x, host=%x\n",
+                  val, size, addr, port);
         }
     }
-    return ret;
-}
-
-static void assigned_dev_ioport_writeb(void *opaque, uint32_t addr,
-                                       uint32_t value)
-{
-    assigned_dev_ioport_rw(opaque, addr, 1, &value);
-    return;
-}
-
-static void assigned_dev_ioport_writew(void *opaque, uint32_t addr,
-                                       uint32_t value)
-{
-    assigned_dev_ioport_rw(opaque, addr, 2, &value);
-    return;
-}
-
-static void assigned_dev_ioport_writel(void *opaque, uint32_t addr,
-                       uint32_t value)
-{
-    assigned_dev_ioport_rw(opaque, addr, 4, &value);
-    return;
-}
-
-static uint32_t assigned_dev_ioport_readb(void *opaque, uint32_t addr)
-{
-    return assigned_dev_ioport_rw(opaque, addr, 1, NULL);
+    return val;
 }
 
-static uint32_t assigned_dev_ioport_readw(void *opaque, uint32_t addr)
+static void assigned_dev_ioport_write(void *opaque, target_phys_addr_t addr,
+                                      uint64_t data, unsigned size)
 {
-    return assigned_dev_ioport_rw(opaque, addr, 2, NULL);
+    assigned_dev_ioport_rw(opaque, addr, size, &data);
 }
 
-static uint32_t assigned_dev_ioport_readl(void *opaque, uint32_t addr)
+static uint64_t assigned_dev_ioport_read(void *opaque,
+                                         target_phys_addr_t addr, unsigned size)
 {
-    return assigned_dev_ioport_rw(opaque, addr, 4, NULL);
+    return assigned_dev_ioport_rw(opaque, addr, size, NULL);
 }
 
 static uint32_t slow_bar_readb(void *opaque, target_phys_addr_t addr)
@@ -258,18 +234,9 @@ static void assigned_dev_iomem_setup(PCIDevice *pci_dev, int region_num,
     }
 }
 
-static const MemoryRegionPortio assigned_dev_old_portio[] = {
-    { 0x10000, 1, .read = assigned_dev_ioport_readb, },
-    { 0x10000, 2, .read = assigned_dev_ioport_readw, },
-    { 0x10000, 4, .read = assigned_dev_ioport_readl, },
-    { 0x10000, 1, .write = assigned_dev_ioport_writeb, },
-    { 0x10000, 2, .write = assigned_dev_ioport_writew, },
-    { 0x10000, 4, .write = assigned_dev_ioport_writel, },
-    PORTIO_END_OF_LIST()
-};
-
 static const MemoryRegionOps assigned_dev_ioport_ops = {
-    .old_portio = assigned_dev_old_portio,
+    .read = assigned_dev_ioport_read,
+    .write = assigned_dev_ioport_write,
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/6] pci-assign: Fix PCI_EXP_FLAGS_TYPE shift
  2011-11-16 20:45 [PATCH 0/6] pci-assign: Multiple fixes and cleanups Alex Williamson
  2011-11-16 20:45 ` [PATCH 1/6] pci-assign: Fix device removal Alex Williamson
  2011-11-16 20:45 ` [PATCH 2/6] pci-assign: Fix I/O port Alex Williamson
@ 2011-11-16 20:45 ` Alex Williamson
  2011-11-16 20:46 ` [PATCH 4/6] pci-assign: Fix PCIe lnkcap Alex Williamson
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Alex Williamson @ 2011-11-16 20:45 UTC (permalink / raw)
  To: kvm; +Cc: jan.kiszka, alex.williamson, yongjie.ren

Coverity found that we're doing (uint16_t)type & 0xf0 >> 8.
This is obviously always 0x0, so our attempt to filter out
some device types thinks everything is an endpoint.  Fix
shift amount.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/device-assignment.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index 571a097..ec302d2 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -1294,7 +1294,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
         assigned_dev_setup_cap_read(dev, pos, size);
 
         type = pci_get_word(pci_dev->config + pos + PCI_EXP_FLAGS);
-        type = (type & PCI_EXP_FLAGS_TYPE) >> 8;
+        type = (type & PCI_EXP_FLAGS_TYPE) >> 4;
         if (type != PCI_EXP_TYPE_ENDPOINT &&
             type != PCI_EXP_TYPE_LEG_END && type != PCI_EXP_TYPE_RC_END) {
             fprintf(stderr,


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/6] pci-assign: Fix PCIe lnkcap
  2011-11-16 20:45 [PATCH 0/6] pci-assign: Multiple fixes and cleanups Alex Williamson
                   ` (2 preceding siblings ...)
  2011-11-16 20:45 ` [PATCH 3/6] pci-assign: Fix PCI_EXP_FLAGS_TYPE shift Alex Williamson
@ 2011-11-16 20:46 ` Alex Williamson
  2011-11-16 20:46 ` [PATCH 5/6] pci-assign: Remove bogus PCIe lnkcap wmask setting Alex Williamson
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Alex Williamson @ 2011-11-16 20:46 UTC (permalink / raw)
  To: kvm; +Cc: jan.kiszka, alex.williamson, yongjie.ren

Another Coverity found issue, lnkcap is a 32bit register and
we're masking bits 16 & 17.  Fix to uin32_t.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/device-assignment.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index ec302d2..dd92ce0 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -1240,8 +1240,8 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
 
     if ((pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_EXP, 0))) {
         uint8_t version, size = 0;
-        uint16_t type, devctl, lnkcap, lnksta;
-        uint32_t devcap;
+        uint16_t type, devctl, lnksta;
+        uint32_t devcap, lnkcap;
 
         version = pci_get_byte(pci_dev->config + pos + PCI_EXP_FLAGS);
         version &= PCI_EXP_FLAGS_VERS;
@@ -1326,11 +1326,11 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
         pci_set_word(pci_dev->config + pos + PCI_EXP_DEVSTA, 0);
 
         /* Link capabilities, expose links and latencues, clear reporting */
-        lnkcap = pci_get_word(pci_dev->config + pos + PCI_EXP_LNKCAP);
+        lnkcap = pci_get_long(pci_dev->config + pos + PCI_EXP_LNKCAP);
         lnkcap &= (PCI_EXP_LNKCAP_SLS | PCI_EXP_LNKCAP_MLW |
                    PCI_EXP_LNKCAP_ASPMS | PCI_EXP_LNKCAP_L0SEL |
                    PCI_EXP_LNKCAP_L1EL);
-        pci_set_word(pci_dev->config + pos + PCI_EXP_LNKCAP, lnkcap);
+        pci_set_long(pci_dev->config + pos + PCI_EXP_LNKCAP, lnkcap);
         pci_set_word(pci_dev->wmask + pos + PCI_EXP_LNKCAP,
                      PCI_EXP_LNKCTL_ASPMC | PCI_EXP_LNKCTL_RCB |
                      PCI_EXP_LNKCTL_CCC | PCI_EXP_LNKCTL_ES |


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/6] pci-assign: Remove bogus PCIe lnkcap wmask setting
  2011-11-16 20:45 [PATCH 0/6] pci-assign: Multiple fixes and cleanups Alex Williamson
                   ` (3 preceding siblings ...)
  2011-11-16 20:46 ` [PATCH 4/6] pci-assign: Fix PCIe lnkcap Alex Williamson
@ 2011-11-16 20:46 ` Alex Williamson
  2011-11-16 20:46 ` [PATCH 6/6] pci-assign: Harden I/O port test Alex Williamson
  2011-11-17  9:26 ` [PATCH 0/6] pci-assign: Multiple fixes and cleanups Avi Kivity
  6 siblings, 0 replies; 8+ messages in thread
From: Alex Williamson @ 2011-11-16 20:46 UTC (permalink / raw)
  To: kvm; +Cc: jan.kiszka, alex.williamson, yongjie.ren

All the fields of lnkcap are read-only and this is setting it
with mask values from LNKCTL.  Just below it, we indicate
link control is read only, so this appears to be a stray
chunk left in from development.  Trivial comment fix while
we're here.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/device-assignment.c |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index dd92ce0..0160de7 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -1312,7 +1312,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
         pci_set_long(pci_dev->config + pos + PCI_EXP_DEVCAP, devcap);
 
         /* device control: clear all error reporting enable bits, leaving
-         *                 leaving only a few host values.  Note, these are
+         *                 only a few host values.  Note, these are
          *                 all writable, but not passed to hw.
          */
         devctl = pci_get_word(pci_dev->config + pos + PCI_EXP_DEVCTL);
@@ -1331,10 +1331,6 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
                    PCI_EXP_LNKCAP_ASPMS | PCI_EXP_LNKCAP_L0SEL |
                    PCI_EXP_LNKCAP_L1EL);
         pci_set_long(pci_dev->config + pos + PCI_EXP_LNKCAP, lnkcap);
-        pci_set_word(pci_dev->wmask + pos + PCI_EXP_LNKCAP,
-                     PCI_EXP_LNKCTL_ASPMC | PCI_EXP_LNKCTL_RCB |
-                     PCI_EXP_LNKCTL_CCC | PCI_EXP_LNKCTL_ES |
-                     PCI_EXP_LNKCTL_CLKREQ_EN | PCI_EXP_LNKCTL_HAWD);
 
         /* Link control, pass existing read-only copy.  Should be writable? */
 


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 6/6] pci-assign: Harden I/O port test
  2011-11-16 20:45 [PATCH 0/6] pci-assign: Multiple fixes and cleanups Alex Williamson
                   ` (4 preceding siblings ...)
  2011-11-16 20:46 ` [PATCH 5/6] pci-assign: Remove bogus PCIe lnkcap wmask setting Alex Williamson
@ 2011-11-16 20:46 ` Alex Williamson
  2011-11-17  9:26 ` [PATCH 0/6] pci-assign: Multiple fixes and cleanups Avi Kivity
  6 siblings, 0 replies; 8+ messages in thread
From: Alex Williamson @ 2011-11-16 20:46 UTC (permalink / raw)
  To: kvm; +Cc: jan.kiszka, alex.williamson, yongjie.ren

Markus Armbruster points out that we're missing a < 0 check
from pread while trying to probe for pci-sysfs io-port
resource support.  We don't expect a short read, but we
should harden the test to abort if we get one so we're not
potentially looking at a stale errno.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 hw/device-assignment.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index 0160de7..7e6f972 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -434,8 +434,9 @@ static int assigned_dev_register_regions(PCIRegion *io_regions,
              * kernels return EIO.  New kernels only allow 1/2/4 byte reads
              * so should return EINVAL for a 3 byte read */
             ret = pread(pci_dev->v_addrs[i].region->resource_fd, &val, 3, 0);
-            if (ret == 3) {
-                fprintf(stderr, "I/O port resource supports 3 byte read?!\n");
+            if (ret >= 0) {
+                fprintf(stderr, "Unexpected return from I/O port read: %d\n",
+                        ret);
                 abort();
             } else if (errno != EINVAL) {
                 fprintf(stderr, "Using raw in/out ioport access (sysfs - %s)\n",


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/6] pci-assign: Multiple fixes and cleanups
  2011-11-16 20:45 [PATCH 0/6] pci-assign: Multiple fixes and cleanups Alex Williamson
                   ` (5 preceding siblings ...)
  2011-11-16 20:46 ` [PATCH 6/6] pci-assign: Harden I/O port test Alex Williamson
@ 2011-11-17  9:26 ` Avi Kivity
  6 siblings, 0 replies; 8+ messages in thread
From: Avi Kivity @ 2011-11-17  9:26 UTC (permalink / raw)
  To: Alex Williamson; +Cc: kvm, jan.kiszka, yongjie.ren

On 11/16/2011 10:45 PM, Alex Williamson wrote:
> These patches are all independent.  Patch 1 & 2 fix serious
> usability bugs.  Patches 3-6 are more subtle things that
> Markus was able to find with Coverity.
>
> Patch 1 fixes https://bugs.launchpad.net/qemu/+bug/875723
>
> I also tested https://bugs.launchpad.net/qemu/+bug/877155
> but I'm unable to reproduce.  An 82576 VF works just fine
> in a Windows 2008 guest with this patch series.  Thanks,
>

Applied, thanks.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-11-17  9:27 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-16 20:45 [PATCH 0/6] pci-assign: Multiple fixes and cleanups Alex Williamson
2011-11-16 20:45 ` [PATCH 1/6] pci-assign: Fix device removal Alex Williamson
2011-11-16 20:45 ` [PATCH 2/6] pci-assign: Fix I/O port Alex Williamson
2011-11-16 20:45 ` [PATCH 3/6] pci-assign: Fix PCI_EXP_FLAGS_TYPE shift Alex Williamson
2011-11-16 20:46 ` [PATCH 4/6] pci-assign: Fix PCIe lnkcap Alex Williamson
2011-11-16 20:46 ` [PATCH 5/6] pci-assign: Remove bogus PCIe lnkcap wmask setting Alex Williamson
2011-11-16 20:46 ` [PATCH 6/6] pci-assign: Harden I/O port test Alex Williamson
2011-11-17  9:26 ` [PATCH 0/6] pci-assign: Multiple fixes and cleanups Avi Kivity

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).