qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/3] virtio: pci cfg access
@ 2015-07-03  9:37 Gerd Hoffmann
  2015-07-03  9:37 ` [Qemu-devel] [PATCH 1/3] virtio: uninline _vp_{read,write} Gerd Hoffmann
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Gerd Hoffmann @ 2015-07-03  9:37 UTC (permalink / raw)
  To: seabios; +Cc: Paolo Bonzini, Gerd Hoffmann, qemu-devel, Michael S. Tsirkin

  Hi,

As discussed this implements virtio regions access via pci cfg space
window.  Used in case bars are mapped above 4G.  Patch #3 is for
testing and not intended to be merged.

cheers,
  Gerd

Gerd Hoffmann (3):
  virtio: uninline _vp_{read,write}
  virtio: pci cfg access
  [testing] map 64bit bars high unconditionally.

 src/fw/pciinit.c    |   2 +-
 src/hw/virtio-pci.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++++---
 src/hw/virtio-pci.h |  92 ++++-----------------
 3 files changed, 227 insertions(+), 91 deletions(-)

-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 1/3] virtio: uninline _vp_{read,write}
  2015-07-03  9:37 [Qemu-devel] [PATCH 0/3] virtio: pci cfg access Gerd Hoffmann
@ 2015-07-03  9:37 ` Gerd Hoffmann
  2015-07-03  9:37 ` [Qemu-devel] [PATCH 2/3] virtio: pci cfg access Gerd Hoffmann
  2015-07-03  9:37 ` [Qemu-devel] [PATCH 3/3] [testing] map 64bit bars high unconditionally Gerd Hoffmann
  2 siblings, 0 replies; 4+ messages in thread
From: Gerd Hoffmann @ 2015-07-03  9:37 UTC (permalink / raw)
  To: seabios; +Cc: Paolo Bonzini, Gerd Hoffmann, qemu-devel, Michael S. Tsirkin

Next patch makes it larger, and I don't think it makes sense to
continue inlining it.  Uninline and move from header to c file.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 src/hw/virtio-pci.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/hw/virtio-pci.h | 79 ++---------------------------------------------------
 2 files changed, 80 insertions(+), 77 deletions(-)

diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c
index 6df5194..769710a 100644
--- a/src/hw/virtio-pci.c
+++ b/src/hw/virtio-pci.c
@@ -24,6 +24,84 @@
 #include "virtio-pci.h"
 #include "virtio-ring.h"
 
+u64 _vp_read(struct vp_cap *cap, u32 offset, u8 size)
+{
+    u32 addr = cap->addr + offset;
+    u64 var;
+
+    if (cap->is_io) {
+        switch (size) {
+        case 8:
+            var = inl(addr);
+            var |= (u64)inl(addr+4) << 32;
+            break;
+        case 4:
+            var = inl(addr);
+            break;
+        case 2:
+            var = inw(addr);
+            break;
+        case 1:
+            var = inb(addr);
+            break;
+        default:
+            var = 0;
+        }
+    } else {
+        switch (size) {
+        case 8:
+            var = readl((void*)addr);
+            var |= (u64)readl((void*)(addr+4)) << 32;
+            break;
+        case 4:
+            var = readl((void*)addr);
+            break;
+        case 2:
+            var = readw((void*)addr);
+            break;
+        case 1:
+            var = readb((void*)addr);
+            break;
+        default:
+            var = 0;
+        }
+    }
+    dprintf(9, "vp read   %x (%d) -> 0x%llx\n", addr, size, var);
+    return var;
+}
+
+void _vp_write(struct vp_cap *cap, u32 offset, u8 size, u64 var)
+{
+    u32 addr = cap->addr + offset;
+
+    dprintf(9, "vp write  %x (%d) <- 0x%llx\n", addr, size, var);
+    if (cap->is_io) {
+        switch (size) {
+        case 4:
+            outl(var, addr);
+            break;
+        case 2:
+            outw(var, addr);
+            break;
+        case 1:
+            outb(var, addr);
+            break;
+        }
+    } else {
+        switch (size) {
+        case 4:
+            writel((void*)addr, var);
+            break;
+        case 2:
+            writew((void*)addr, var);
+            break;
+        case 1:
+            writeb((void*)addr, var);
+            break;
+        }
+    }
+}
+
 u64 vp_get_features(struct vp_device *vp)
 {
     u32 f0, f1;
diff --git a/src/hw/virtio-pci.h b/src/hw/virtio-pci.h
index b11c355..8d4ebe3 100644
--- a/src/hw/virtio-pci.h
+++ b/src/hw/virtio-pci.h
@@ -98,83 +98,8 @@ struct vp_device {
     u8 use_modern;
 };
 
-static inline u64 _vp_read(struct vp_cap *cap, u32 offset, u8 size)
-{
-    u32 addr = cap->addr + offset;
-    u64 var;
-
-    if (cap->is_io) {
-        switch (size) {
-        case 8:
-            var = inl(addr);
-            var |= (u64)inl(addr+4) << 32;
-            break;
-        case 4:
-            var = inl(addr);
-            break;
-        case 2:
-            var = inw(addr);
-            break;
-        case 1:
-            var = inb(addr);
-            break;
-        default:
-            var = 0;
-        }
-    } else {
-        switch (size) {
-        case 8:
-            var = readl((void*)addr);
-            var |= (u64)readl((void*)(addr+4)) << 32;
-            break;
-        case 4:
-            var = readl((void*)addr);
-            break;
-        case 2:
-            var = readw((void*)addr);
-            break;
-        case 1:
-            var = readb((void*)addr);
-            break;
-        default:
-            var = 0;
-        }
-    }
-    dprintf(9, "vp read   %x (%d) -> 0x%llx\n", addr, size, var);
-    return var;
-}
-
-static inline void _vp_write(struct vp_cap *cap, u32 offset, u8 size, u64 var)
-{
-    u32 addr = cap->addr + offset;
-
-    dprintf(9, "vp write  %x (%d) <- 0x%llx\n", addr, size, var);
-    if (cap->is_io) {
-        switch (size) {
-        case 4:
-            outl(var, addr);
-            break;
-        case 2:
-            outw(var, addr);
-            break;
-        case 1:
-            outb(var, addr);
-            break;
-        }
-    } else {
-        switch (size) {
-        case 4:
-            writel((void*)addr, var);
-            break;
-        case 2:
-            writew((void*)addr, var);
-            break;
-        case 1:
-            writeb((void*)addr, var);
-            break;
-        }
-    }
-}
+u64 _vp_read(struct vp_cap *cap, u32 offset, u8 size);
+void _vp_write(struct vp_cap *cap, u32 offset, u8 size, u64 var);
 
 #define vp_read(_cap, _struct, _field)        \
     _vp_read(_cap, offsetof(_struct, _field), \
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 2/3] virtio: pci cfg access
  2015-07-03  9:37 [Qemu-devel] [PATCH 0/3] virtio: pci cfg access Gerd Hoffmann
  2015-07-03  9:37 ` [Qemu-devel] [PATCH 1/3] virtio: uninline _vp_{read,write} Gerd Hoffmann
@ 2015-07-03  9:37 ` Gerd Hoffmann
  2015-07-03  9:37 ` [Qemu-devel] [PATCH 3/3] [testing] map 64bit bars high unconditionally Gerd Hoffmann
  2 siblings, 0 replies; 4+ messages in thread
From: Gerd Hoffmann @ 2015-07-03  9:37 UTC (permalink / raw)
  To: seabios; +Cc: Paolo Bonzini, Gerd Hoffmann, qemu-devel, Michael S. Tsirkin

virtio regions can also be accessed using a window in pci cfg space.
Add support for it.  Enable it in case the virtio regions are mapped
high (above 4g), so direct mmio access doesn't work for us even in
32bit mode.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 src/hw/virtio-pci.c | 164 +++++++++++++++++++++++++++++++++++++++++++++-------
 src/hw/virtio-pci.h |  13 ++++-
 2 files changed, 155 insertions(+), 22 deletions(-)

diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c
index 769710a..55a766f 100644
--- a/src/hw/virtio-pci.c
+++ b/src/hw/virtio-pci.c
@@ -27,9 +27,10 @@
 u64 _vp_read(struct vp_cap *cap, u32 offset, u8 size)
 {
     u32 addr = cap->addr + offset;
-    u64 var;
+    u64 var = 0;
 
-    if (cap->is_io) {
+    switch (cap->mode) {
+    case VP_ACCESS_IO:
         switch (size) {
         case 8:
             var = inl(addr);
@@ -44,10 +45,10 @@ u64 _vp_read(struct vp_cap *cap, u32 offset, u8 size)
         case 1:
             var = inb(addr);
             break;
-        default:
-            var = 0;
         }
-    } else {
+        break;
+
+    case VP_ACCESS_MMIO:
         switch (size) {
         case 8:
             var = readl((void*)addr);
@@ -62,9 +63,43 @@ u64 _vp_read(struct vp_cap *cap, u32 offset, u8 size)
         case 1:
             var = readb((void*)addr);
             break;
-        default:
-            var = 0;
         }
+        break;
+
+    case VP_ACCESS_PCICFG:
+        pci_config_writeb(cap->bdf, cap->cfg +
+                          offsetof(struct virtio_pci_cfg_cap, cap.bar),
+                          cap->bar);
+        pci_config_writel(cap->bdf, cap->cfg +
+                          offsetof(struct virtio_pci_cfg_cap, cap.offset),
+                          addr);
+        pci_config_writel(cap->bdf, cap->cfg +
+                          offsetof(struct virtio_pci_cfg_cap, cap.length),
+                          (size > 4) ? 4 : size);
+        switch (size) {
+        case 8:
+            var = pci_config_readl(cap->bdf, cap->cfg +
+                                   offsetof(struct virtio_pci_cfg_cap, pci_cfg_data));
+            pci_config_writel(cap->bdf, cap->cfg +
+                              offsetof(struct virtio_pci_cfg_cap, cap.offset),
+                              addr + 4);
+            var |= (u64)pci_config_readl(cap->bdf, cap->cfg +
+                                         offsetof(struct virtio_pci_cfg_cap, pci_cfg_data)) << 32;
+            break;
+        case 4:
+            var = pci_config_readl(cap->bdf, cap->cfg +
+                                   offsetof(struct virtio_pci_cfg_cap, pci_cfg_data));
+            break;
+        case 2:
+            var = pci_config_readw(cap->bdf, cap->cfg +
+                                   offsetof(struct virtio_pci_cfg_cap, pci_cfg_data));
+            break;
+        case 1:
+            var = pci_config_readb(cap->bdf, cap->cfg +
+                                   offsetof(struct virtio_pci_cfg_cap, pci_cfg_data));
+            break;
+        }
+
     }
     dprintf(9, "vp read   %x (%d) -> 0x%llx\n", addr, size, var);
     return var;
@@ -75,7 +110,8 @@ void _vp_write(struct vp_cap *cap, u32 offset, u8 size, u64 var)
     u32 addr = cap->addr + offset;
 
     dprintf(9, "vp write  %x (%d) <- 0x%llx\n", addr, size, var);
-    if (cap->is_io) {
+    switch (cap->mode) {
+    case VP_ACCESS_IO:
         switch (size) {
         case 4:
             outl(var, addr);
@@ -87,7 +123,9 @@ void _vp_write(struct vp_cap *cap, u32 offset, u8 size, u64 var)
             outb(var, addr);
             break;
         }
-    } else {
+        break;
+
+    case VP_ACCESS_MMIO:
         switch (size) {
         case 4:
             writel((void*)addr, var);
@@ -99,6 +137,36 @@ void _vp_write(struct vp_cap *cap, u32 offset, u8 size, u64 var)
             writeb((void*)addr, var);
             break;
         }
+        break;
+
+    case VP_ACCESS_PCICFG:
+        pci_config_writeb(cap->bdf, cap->cfg +
+                          offsetof(struct virtio_pci_cfg_cap, cap.bar),
+                          cap->bar);
+        pci_config_writel(cap->bdf, cap->cfg +
+                          offsetof(struct virtio_pci_cfg_cap, cap.offset),
+                          addr);
+        pci_config_writel(cap->bdf, cap->cfg +
+                          offsetof(struct virtio_pci_cfg_cap, cap.length),
+                          size);
+        switch (size) {
+        case 4:
+            pci_config_writel(cap->bdf, cap->cfg +
+                              offsetof(struct virtio_pci_cfg_cap, pci_cfg_data),
+                              var);
+            break;
+        case 2:
+            pci_config_writew(cap->bdf, cap->cfg +
+                              offsetof(struct virtio_pci_cfg_cap, pci_cfg_data),
+                              var);
+            break;
+        case 1:
+            pci_config_writeb(cap->bdf, cap->cfg +
+                              offsetof(struct virtio_pci_cfg_cap, pci_cfg_data),
+                              var);
+            break;
+        }
+
     }
 }
 
@@ -181,10 +249,26 @@ void vp_notify(struct vp_device *vp, struct vring_virtqueue *vq)
         u32 addr = vp->notify.addr +
             vq->queue_notify_off *
             vp->notify_off_multiplier;
-        if (vp->notify.is_io) {
+        switch (vp->notify.mode) {
+        case VP_ACCESS_IO:
             outw(vq->queue_index, addr);
-        } else {
+            break;
+        case VP_ACCESS_MMIO:
             writew((void*)addr, vq->queue_index);
+            break;
+        case VP_ACCESS_PCICFG:
+            pci_config_writeb(vp->notify.bdf, vp->notify.cfg +
+                              offsetof(struct virtio_pci_cfg_cap, cap.bar),
+                              vp->notify.bar);
+            pci_config_writel(vp->notify.bdf, vp->notify.cfg +
+                              offsetof(struct virtio_pci_cfg_cap, cap.offset),
+                              addr);
+            pci_config_writel(vp->notify.bdf, vp->notify.cfg +
+                              offsetof(struct virtio_pci_cfg_cap, cap.length),
+                              2);
+            pci_config_writew(vp->notify.bdf, vp->notify.cfg +
+                              offsetof(struct virtio_pci_cfg_cap, pci_cfg_data),
+                              vq->queue_index);
         }
         dprintf(9, "vp notify %x (%d) -- 0x%x\n",
                 addr, 2, vq->queue_index);
@@ -286,7 +370,9 @@ void vp_init_simple(struct vp_device *vp, struct pci_device *pci)
 {
     u8 cap = pci_find_capability(pci, PCI_CAP_ID_VNDR, 0);
     struct vp_cap *vp_cap;
-    u32 addr, offset, mul;
+    const char *mode;
+    u32 offset, base, mul;
+    u64 addr;
     u8 type;
 
     memset(vp, 0, sizeof(*vp));
@@ -308,6 +394,20 @@ void vp_init_simple(struct vp_device *vp, struct pci_device *pci)
         case VIRTIO_PCI_CAP_DEVICE_CFG:
             vp_cap = &vp->device;
             break;
+        case VIRTIO_PCI_CAP_PCI_CFG:
+            vp->common.cfg = cap;
+            vp->common.bdf = pci->bdf;
+            vp->notify.cfg = cap;
+            vp->notify.bdf = pci->bdf;
+            vp->isr.cfg = cap;
+            vp->isr.bdf = pci->bdf;
+            vp->device.cfg = cap;
+            vp->device.bdf = pci->bdf;
+            vp_cap = NULL;
+            dprintf(1, "pci dev %x:%x virtio cap at 0x%x type %d [pci cfg access]\n",
+                    pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
+                    cap, type);
+            break;
         default:
             vp_cap = NULL;
             break;
@@ -318,20 +418,42 @@ void vp_init_simple(struct vp_device *vp, struct pci_device *pci)
                                            offsetof(struct virtio_pci_cap, bar));
             offset = pci_config_readl(pci->bdf, cap +
                                       offsetof(struct virtio_pci_cap, offset));
-            addr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0 + 4 * vp_cap->bar);
+            base = PCI_BASE_ADDRESS_0 + 4 * vp_cap->bar;
+            addr = pci_config_readl(pci->bdf, base);
             if (addr & PCI_BASE_ADDRESS_SPACE_IO) {
-                vp_cap->is_io = 1;
                 addr &= PCI_BASE_ADDRESS_IO_MASK;
+                vp_cap->mode = VP_ACCESS_IO;
+            } else if ((addr & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+                       PCI_BASE_ADDRESS_MEM_TYPE_64) {
+                addr &= PCI_BASE_ADDRESS_MEM_MASK;
+                addr |= (u64)pci_config_readl(pci->bdf, base + 4) << 32;
+                vp_cap->mode = (addr > 0xffffffffll) ?
+                    VP_ACCESS_PCICFG : VP_ACCESS_MMIO;
             } else {
-                vp_cap->is_io = 0;
                 addr &= PCI_BASE_ADDRESS_MEM_MASK;
+                vp_cap->mode = VP_ACCESS_MMIO;
             }
-            vp_cap->addr = addr + offset;
-            dprintf(3, "pci dev %x:%x virtio cap at 0x%x type %d "
-                    "bar %d at 0x%08x off +0x%04x [%s]\n",
+            switch (vp_cap->mode) {
+            case VP_ACCESS_IO:
+                mode = "io";
+                vp_cap->addr = addr + offset; // io addr
+                break;
+            case VP_ACCESS_MMIO:
+                mode = "mmio";
+                vp_cap->addr = addr + offset; // mem addr
+                break;
+            case VP_ACCESS_PCICFG:
+                mode = "pcicfg";
+                vp_cap->addr = offset; // bar offset
+                break;
+            default:
+                mode = "Huh?";
+                break;
+            }
+            dprintf(1, "pci dev %x:%x virtio cap at 0x%x type %d "
+                    "bar %d at 0x%08llx off +0x%04x [%s]\n",
                     pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
-                    vp_cap->cap, type, vp_cap->bar, addr, offset,
-                    vp_cap->is_io ? "io" : "mmio");
+                    vp_cap->cap, type, vp_cap->bar, addr, offset, mode);
         }
 
         cap = pci_find_capability(pci, PCI_CAP_ID_VNDR, cap);
@@ -347,7 +469,7 @@ void vp_init_simple(struct vp_device *vp, struct pci_device *pci)
         vp->legacy.bar = 0;
         vp->legacy.addr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) &
             PCI_BASE_ADDRESS_IO_MASK;
-        vp->legacy.is_io = 1;
+        vp->legacy.mode = VP_ACCESS_IO;
     }
 
     vp_reset(vp);
diff --git a/src/hw/virtio-pci.h b/src/hw/virtio-pci.h
index 8d4ebe3..5ab2ec8 100644
--- a/src/hw/virtio-pci.h
+++ b/src/hw/virtio-pci.h
@@ -54,6 +54,11 @@ struct virtio_pci_notify_cap {
     u32 notify_off_multiplier;   /* Multiplier for queue_notify_off. */
 };
 
+struct virtio_pci_cfg_cap {
+    struct virtio_pci_cap cap;
+    u8 pci_cfg_data[4]; /* Data for BAR access. */
+};
+
 typedef struct virtio_pci_common_cfg {
     /* About the whole device. */
     u32 device_feature_select;   /* read-write */
@@ -85,11 +90,17 @@ typedef struct virtio_pci_isr {
 
 /* --- driver structs ----------------------------------------------- */
 
+#define VP_ACCESS_IO       1
+#define VP_ACCESS_MMIO     2
+#define VP_ACCESS_PCICFG   3
+
 struct vp_cap {
     u32 addr;
+    u16 bdf;
     u8 cap;
+    u8 cfg;
     u8 bar;
-    u8 is_io;
+    u8 mode;
 };
 
 struct vp_device {
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 3/3] [testing] map 64bit bars high unconditionally.
  2015-07-03  9:37 [Qemu-devel] [PATCH 0/3] virtio: pci cfg access Gerd Hoffmann
  2015-07-03  9:37 ` [Qemu-devel] [PATCH 1/3] virtio: uninline _vp_{read,write} Gerd Hoffmann
  2015-07-03  9:37 ` [Qemu-devel] [PATCH 2/3] virtio: pci cfg access Gerd Hoffmann
@ 2015-07-03  9:37 ` Gerd Hoffmann
  2 siblings, 0 replies; 4+ messages in thread
From: Gerd Hoffmann @ 2015-07-03  9:37 UTC (permalink / raw)
  To: seabios; +Cc: Paolo Bonzini, Gerd Hoffmann, qemu-devel, Michael S. Tsirkin

---
 src/fw/pciinit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 45870f2..ba1c84c 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -867,7 +867,7 @@ static void pci_bios_map_devices(struct pci_bus *busses)
         panic("PCI: out of I/O address space\n");
 
     dprintf(1, "PCI: 32: %016llx - %016llx\n", pcimem_start, pcimem_end);
-    if (pci_bios_init_root_regions_mem(busses)) {
+    if (1 /* pci_bios_init_root_regions_mem(busses) */) {
         struct pci_region r64_mem, r64_pref;
         r64_mem.list.first = NULL;
         r64_pref.list.first = NULL;
-- 
1.8.3.1

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

end of thread, other threads:[~2015-07-03  9:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-03  9:37 [Qemu-devel] [PATCH 0/3] virtio: pci cfg access Gerd Hoffmann
2015-07-03  9:37 ` [Qemu-devel] [PATCH 1/3] virtio: uninline _vp_{read,write} Gerd Hoffmann
2015-07-03  9:37 ` [Qemu-devel] [PATCH 2/3] virtio: pci cfg access Gerd Hoffmann
2015-07-03  9:37 ` [Qemu-devel] [PATCH 3/3] [testing] map 64bit bars high unconditionally Gerd Hoffmann

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).