This patch makes offsets for virtio config space and MSI-X dynamic.

The change should fix the wrong usage of MSI-X space as virtio
config space.

Signed-off-by: Sasha Levin <[email protected]>
---
 tools/kvm/virtio/net.c |   78 +++++++++++++++++++++++++++++++++++-------------
 1 files changed, 57 insertions(+), 21 deletions(-)

diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c
index 96858b7..aa4536b 100644
--- a/tools/kvm/virtio/net.c
+++ b/tools/kvm/virtio/net.c
@@ -65,6 +65,7 @@ struct net_dev {
        u32                             gsis[VIRTIO_NET_NUM_QUEUES];
        u32                             msix_io_block;
        int                             compat_id;
+       bool                            msix_enabled;
 
        pthread_t                       io_rx_thread;
        pthread_mutex_t                 io_rx_lock;
@@ -176,17 +177,67 @@ static void *virtio_net_tx_thread(void *p)
 
 }
 
+static bool virtio_net_pci_io_device_specific_out(struct kvm *kvm, void *data,
+                                                       unsigned long offset, 
int size)
+{
+       u8 *config_space = (u8 *)&ndev.config;
+       int type;
+       u32 config_offset;
+
+       type = virtio__get_dev_specific_field(offset - 20, ndev.msix_enabled, 
0, &config_offset);
+       if (type == VIRTIO_PCI_O_MSIX) {
+               if (offset == VIRTIO_MSI_CONFIG_VECTOR) {
+                       ndev.config_vector      = ioport__read16(data);
+               } else {
+                       u32 gsi;
+                       u32 vec;
+
+                       vec = ndev.vq_vector[ndev.queue_selector] = 
ioport__read16(data);
+
+                       gsi = irq__add_msix_route(kvm,
+                                                 
pci_header.msix.table[vec].low,
+                                                 
pci_header.msix.table[vec].high,
+                                                 
pci_header.msix.table[vec].data);
+
+                       ndev.gsis[ndev.queue_selector] = gsi;
+               }
+               return true;
+       }
+
+       if (size != 1)
+               return false;
+
+       if ((config_offset) > sizeof(struct virtio_net_config))
+               pr_error("config offset is too big: %u", config_offset);
+
+       config_space[config_offset] = *(u8 *)data;
+
+       return true;
+}
+
 static bool virtio_net_pci_io_device_specific_in(void *data, unsigned long 
offset, int size)
 {
        u8 *config_space = (u8 *)&ndev.config;
+       int type;
+       u32 config_offset;
+
+       type = virtio__get_dev_specific_field(offset - 20, ndev.msix_enabled, 
0, &config_offset);
+       if (type == VIRTIO_PCI_O_MSIX) {
+               if (offset == VIRTIO_MSI_CONFIG_VECTOR)
+                       ioport__write16(data, ndev.config_vector);
+               else
+                       ioport__write16(data, 
ndev.vq_vector[ndev.queue_selector]);
+
+               return true;
+       }
 
        if (size != 1)
                return false;
 
-       if ((offset - VIRTIO_MSI_CONFIG_VECTOR) > sizeof(struct 
virtio_net_config))
-               pr_error("config offset is too big: %li", offset - 
VIRTIO_MSI_CONFIG_VECTOR);
+       if ((config_offset) > sizeof(struct virtio_net_config))
+               pr_error("config offset is too big: %u", config_offset);
 
-       ioport__write8(data, config_space[offset - VIRTIO_MSI_CONFIG_VECTOR]);
+       ioport__write8(data, config_space[config_offset]);
 
        return true;
 }
@@ -290,25 +341,8 @@ static bool virtio_net_pci_io_out(struct ioport *ioport, 
struct kvm *kvm, u16 po
        case VIRTIO_PCI_STATUS:
                ndev.status             = ioport__read8(data);
                break;
-       case VIRTIO_MSI_CONFIG_VECTOR:
-               ndev.config_vector      = ioport__read16(data);
-               break;
-       case VIRTIO_MSI_QUEUE_VECTOR: {
-               u32 gsi;
-               u32 vec;
-
-               vec = ndev.vq_vector[ndev.queue_selector] = 
ioport__read16(data);
-
-               gsi = irq__add_msix_route(kvm,
-                                         pci_header.msix.table[vec].low,
-                                         pci_header.msix.table[vec].high,
-                                         pci_header.msix.table[vec].data);
-
-               ndev.gsis[ndev.queue_selector] = gsi;
-               break;
-       }
        default:
-               ret                     = false;
+               ret = virtio_net_pci_io_device_specific_out(kvm, data, offset, 
size);
        };
 
        mutex_unlock(&ndev.mutex);
@@ -333,6 +367,8 @@ static void callback_mmio(u64 addr, u8 *data, u32 len, u8 
is_write, void *ptr)
                memcpy(table + addr - ndev.msix_io_block, data, len);
        else
                memcpy(data, table + addr - ndev.msix_io_block, len);
+
+       ndev.msix_enabled = 1;
 }
 
 static bool virtio_net__tap_init(const struct virtio_net_parameters *params)
-- 
1.7.6

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to