qemu: move virtio-pci.o to near pci.o
Subsystems (3)
A message that is not in the archive (sent off-list or not yet received): [email protected]
Michael S. Tsirkin
maintainerPATCH 1/3 qemu: move virtio-pci.o to near pci.o
virtio-pci depends, and will always depend, on pci.c so it makes sense to keep it in the same makefile, (unlike the rest of virtio files which should eventually
be moved out to Makefile.hw).
--- Makefile.hw | 2 +- Makefile.target | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
Makefile.hw +1 -1
@@ -16,7 +16,7 @@ CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE CPPFLAGS+=-I$(SRC_PATH)/fpu obj-y = -obj-y += virtio.o virtio-pci.o +obj-y += virtio.o obj-y += fw_cfg.o obj-y += watchdog.o obj-y += nand.o ecc.o
Makefile.target +1 -1
@@ -538,7 +538,7 @@ obj-y = vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o \ gdbstub.o gdbstub-xml.o msix.o ioport.o # virtio has to be here due to weird dependency between PCI and virtio-net. # need to fix this properly -obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o +obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o obj-$(CONFIG_KVM) += kvm.o kvm-all.o LIBS+=-lz
Signature · 1 line
1.6.2.5
Michael S. Tsirkin
maintainerPATCH 1/3 qemu: move virtio-pci.o to near pci.o
In reply to a message not in the archivevirtio-pci depends, and will always depend, on pci.c so it makes sense to keep it in the same makefile, (unlike the rest of virtio files which should eventually
be moved out to Makefile.hw).
--- Makefile.hw | 2 +- Makefile.target | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
Makefile.hw +1 -1
@@ -16,7 +16,7 @@ CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE CPPFLAGS+=-I$(SRC_PATH)/fpu obj-y = -obj-y += virtio.o virtio-pci.o +obj-y += virtio.o obj-y += fw_cfg.o obj-y += watchdog.o obj-y += nand.o ecc.o
Makefile.target +1 -1
@@ -538,7 +538,7 @@ obj-y = vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o \ gdbstub.o gdbstub-xml.o msix.o ioport.o # virtio has to be here due to weird dependency between PCI and virtio-net. # need to fix this properly -obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o +obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o obj-$(CONFIG_KVM) += kvm.o kvm-all.o LIBS+=-lz
Signature · 1 line
1.6.2.5
Michael S. Tsirkin
maintainerPATCH 2/3 qemu/virtio: move features to an inline function
In reply to a message not in the archivedevices should have the final say over which virtio features they support. E.g. indirect entries may or may not make sense in the context of virtio-console. Move the common bits from virtio-pci to an inline function and let each device call it.
No functional changes.
--- hw/virtio-balloon.c | 2 +- hw/virtio-blk.c | 2 +- hw/virtio-console.c | 2 +- hw/virtio-net.c | 2 +- hw/virtio-pci.c | 3 --- hw/virtio.h | 10 ++++++++++ 6 files changed, 14 insertions(+), 7 deletions(-)
hw/virtio-balloon.c +1 -1
@@ -127,7 +127,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,static uint32_t virtio_balloon_get_features (VirtIODevice *vdev) { -return 0 ; +return virtio_common_features (); }static ram_addr_t virtio_balloon_to_target (void *opaque,ram_addr_t target)
hw/virtio-blk.c +1 -1
@@ -364,7 +364,7 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev)if (strcmp (s->serial_str,"0" )) features |=1 <<VIRTIO_BLK_F_IDENTIFY ; -return features; +return features |virtio_common_features (); }static void virtio_blk_save (QEMUFile *f,void *opaque)
hw/virtio-console.c +1 -1
@@ -53,7 +53,7 @@ static void virtio_console_handle_input(VirtIODevice *vdev, VirtQueue *vq)static uint32_t virtio_console_get_features (VirtIODevice *vdev) { -return 0 ; +return virtio_common_features (); }static int vcon_can_read (void *opaque)
hw/virtio-net.c +1 -1
@@ -154,7 +154,7 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) }#endif -return features; +return features |virtio_common_features (); }static uint32_t virtio_net_bad_features (VirtIODevice *vdev)
hw/virtio-pci.c +0 -3
@@ -232,9 +232,6 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)switch (addr) {case VIRTIO_PCI_HOST_FEATURES : ret = vdev->get_features (vdev); - ret |= (1 <<VIRTIO_F_NOTIFY_ON_EMPTY ); - ret |= (1 <<VIRTIO_RING_F_INDIRECT_DESC ); - ret |= (1 <<VIRTIO_F_BAD_FEATURE );break ;case VIRTIO_PCI_GUEST_FEATURES : ret = vdev->features;
hw/virtio.h +10 -0
@@ -166,4 +166,14 @@ VirtIODevice *virtio_net_init(DeviceState *dev);VirtIODevice *virtio_console_init (DeviceState *dev);VirtIODevice *virtio_balloon_init (DeviceState *dev); +static inline uint32_t virtio_common_features (void ) +{ +uint32_t features =0 ; + features |= (1 <<VIRTIO_F_NOTIFY_ON_EMPTY ); + features |= (1 <<VIRTIO_RING_F_INDIRECT_DESC ); + features |= (1 <<VIRTIO_F_BAD_FEATURE ); + +return features; +} +#endif
Signature · 1 line
1.6.2.5
Michael S. Tsirkin
maintainerPATCH 2/3 qemu/virtio: move features to an inline function
In reply to a message not in the archivedevices should have the final say over which virtio features they support. E.g. indirect entries may or may not make sense in the context of virtio-console. Move the common bits from virtio-pci to an inline function and let each device call it.
No functional changes.
--- hw/virtio-balloon.c | 2 +- hw/virtio-blk.c | 2 +- hw/virtio-console.c | 2 +- hw/virtio-net.c | 2 +- hw/virtio-pci.c | 3 --- hw/virtio.h | 10 ++++++++++ 6 files changed, 14 insertions(+), 7 deletions(-)
hw/virtio-balloon.c +1 -1
@@ -127,7 +127,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,static uint32_t virtio_balloon_get_features (VirtIODevice *vdev) { -return 0 ; +return virtio_common_features (); }static ram_addr_t virtio_balloon_to_target (void *opaque,ram_addr_t target)
hw/virtio-blk.c +1 -1
@@ -364,7 +364,7 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev)if (strcmp (s->serial_str,"0" )) features |=1 <<VIRTIO_BLK_F_IDENTIFY ; -return features; +return features |virtio_common_features (); }static void virtio_blk_save (QEMUFile *f,void *opaque)
hw/virtio-console.c +1 -1
@@ -53,7 +53,7 @@ static void virtio_console_handle_input(VirtIODevice *vdev, VirtQueue *vq)static uint32_t virtio_console_get_features (VirtIODevice *vdev) { -return 0 ; +return virtio_common_features (); }static int vcon_can_read (void *opaque)
hw/virtio-net.c +1 -1
@@ -154,7 +154,7 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) }#endif -return features; +return features |virtio_common_features (); }static uint32_t virtio_net_bad_features (VirtIODevice *vdev)
hw/virtio-pci.c +0 -3
@@ -232,9 +232,6 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)switch (addr) {case VIRTIO_PCI_HOST_FEATURES : ret = vdev->get_features (vdev); - ret |= (1 <<VIRTIO_F_NOTIFY_ON_EMPTY ); - ret |= (1 <<VIRTIO_RING_F_INDIRECT_DESC ); - ret |= (1 <<VIRTIO_F_BAD_FEATURE );break ;case VIRTIO_PCI_GUEST_FEATURES : ret = vdev->features;
hw/virtio.h +10 -0
@@ -166,4 +166,14 @@ VirtIODevice *virtio_net_init(DeviceState *dev);VirtIODevice *virtio_console_init (DeviceState *dev);VirtIODevice *virtio_balloon_init (DeviceState *dev); +static inline uint32_t virtio_common_features (void ) +{ +uint32_t features =0 ; + features |= (1 <<VIRTIO_F_NOTIFY_ON_EMPTY ); + features |= (1 <<VIRTIO_RING_F_INDIRECT_DESC ); + features |= (1 <<VIRTIO_F_BAD_FEATURE ); + +return features; +} +#endif
Signature · 1 line
1.6.2.5
Michael S. Tsirkin
maintainerPATCH 3/3 qemu-kvm: vhost-net implementation
In reply to a message not in the archiveThis adds support for vhost-net virtio kernel backend. To enable (assuming device eth2):
1. enable promisc mode or program guest mac in device eth2
2. disable tso, gso, lro on the card
3. add vhost=eth0 to -net flag
4. run with CAP_NET_ADMIN priviledge (e.g. root)
This patch is RFC, but works without issues for me.
It still needs to be split up, tested and benchmarked properly, but posting it here in case people want to test drive the kernel bits I posted.
--- Makefile.target | 3 +- hw/vhost_net.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/vhost_net.h | 30 +++++++++ hw/virtio-net.c | 32 ++++++++++- hw/virtio-pci.c | 40 ++++++++++++ hw/virtio.c | 19 ------ hw/virtio.h | 28 ++++++++- net.c | 8 ++- net.h | 1 + qemu-kvm.c | 8 --- qemu-kvm.h | 9 +++ 11 files changed, 325 insertions(+), 34 deletions(-) create mode 100644 hw/vhost_net.c create mode 100644 hw/vhost_net.h
Makefile.target +2 -1
@@ -538,7 +538,8 @@ obj-y = vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o \ gdbstub.o gdbstub-xml.o msix.o ioport.o # virtio has to be here due to weird dependency between PCI and virtio-net. # need to fix this properly -obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o +obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o \ + vhost_net.o obj-$(CONFIG_KVM) += kvm.o kvm-all.o LIBS+=-lz
hw/vhost_net.c new file +181 -0
181 lines not on this page · raw message
hw/vhost_net.h new file +30 -0
@@ -0,0 +1,30 @@ +#ifndef VHOST_NET_H +#define VHOST_NET_H + +#include "hw/virtio.h" + +struct vhost_virtqueue { +int kick; +int call; +void *desc; +void *avail; +void *used; +}; + +struct vhost_dev { +int control; +struct vhost_virtqueue *vqs; +int nvqs; +}; + +struct vhost_net { +struct vhost_dev dev; +struct vhost_virtqueue vqs[2 ]; +int sock; +}; + +int vhost_net_init (struct vhost_net *net, +VirtIODevice *dev, +char *vhost_device); + +#endif
hw/virtio-net.c +31 -1
@@ -19,6 +19,8 @@#include "qemu-kvm.h" #endif +#include "vhost_net.h" +#define TAP_VNET_HDR #define VIRTIO_NET_VM_VERSION 10
@@ -56,6 +58,8 @@ typedef struct VirtIONetuint8_t *macs; } mac_table;uint32_t *vlans; +char *vhost_device; +struct vhost_net vhost; } VirtIONet;/* TODO
@@ -134,9 +138,12 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) (1 <<VIRTIO_NET_F_CTRL_RX ) | (1 <<VIRTIO_NET_F_CTRL_VLAN ) | (1 <<VIRTIO_NET_F_CTRL_RX_EXTRA ); +VirtIONet *n =to_virtio_net (vdev); + +if (n->vhost_device) +return 1 <<VIRTIO_NET_F_MAC ;#ifdef TAP_VNET_HDR -VirtIONet *n =to_virtio_net (vdev);VLANClientState *host = n->vc->vlan->first_client;if (tap_has_vnet_hdr (host)) {
@@ -175,6 +182,9 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev)static void virtio_net_set_features (VirtIODevice *vdev,uint32_t features) {VirtIONet *n =to_virtio_net (vdev); +/* vhost net supports no features */ +if (n->vhost_device) +return ;#ifdef TAP_VNET_HDR VLANClientState *host = n->vc->vlan->first_client;#endif
@@ -351,6 +361,9 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)static int do_virtio_net_can_receive (VirtIONet *n,int bufsize) { +if (n->vhost_device) +return 0 ; +if (!virtio_queue_ready (n->rx_vq) || !(n->vdev.status &VIRTIO_CONFIG_S_DRIVER_OK ))return 0 ;
@@ -411,6 +424,7 @@ static int iov_fill(struct iovec *iov, int iovcnt, const void *buf, int count)while (offset < count && i < iovcnt) {int len =MIN (iov[i].iov_len, count - offset);memcpy (iov[i].iov_base, buf + offset, len); + offset += len; i++; }
@@ -611,6 +625,8 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)#else int has_vnet_hdr =0 ;#endif +if (n->vhost_device) +return ;if (!(n->vdev.status &VIRTIO_CONFIG_S_DRIVER_OK ))return ;
@@ -823,6 +839,18 @@ static void virtio_net_cleanup(VLANClientState *vc)virtio_cleanup (&n->vdev); } +static void virtio_net_driver_ok (VirtIODevice *vdev) +{ +VirtIONet *n =to_virtio_net (vdev); +int r; + + r =vhost_net_init (&n->vhost, vdev, n->vhost_device); +if (r) { +fprintf (stderr,"\nvhost_net_init returned %d\n" , r); +exit (-r); + } +} +VirtIODevice *virtio_net_init (DeviceState *dev) {VirtIONet *n;
@@ -838,6 +866,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev) n->vdev.set_features = virtio_net_set_features; n->vdev.bad_features = virtio_net_bad_features; n->vdev.reset = virtio_net_reset; + n->vdev.driver_ok = virtio_net_driver_ok; n->rx_vq =virtio_add_queue (&n->vdev,256 , virtio_net_handle_rx); n->tx_vq =virtio_add_queue (&n->vdev,256 , virtio_net_handle_tx); n->ctrl_vq =virtio_add_queue (&n->vdev,64 , virtio_net_handle_ctrl);
@@ -864,6 +893,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev) n->vdev.nvectors =3 ; else n->vdev.nvectors = dev->nd->nvectors; + n->vhost_device = dev->nd->vhost_device;register_savevm ("virtio-net" , virtio_net_id++,VIRTIO_NET_VM_VERSION , virtio_net_save, virtio_net_load, n);
hw/virtio-pci.c +40 -0
@@ -15,10 +15,12 @@#include <inttypes.h> +#include <linux/kvm.h> #include "virtio.h" #include "pci.h" //#include "sysemu.h" #include "msix.h" +#include "qemu-kvm.h" /* from Linux's linux/virtio_pci.h */
@@ -201,6 +203,8 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) vdev->status = val &0xFF ;if (vdev->status ==0 )virtio_pci_reset (proxy); +if ((val &VIRTIO_CONFIG_S_DRIVER_OK ) && vdev->driver_ok) + vdev->driver_ok (vdev);break ;case VIRTIO_MSI_CONFIG_VECTOR :msix_vector_unuse (&proxy->pci_dev, vdev->config_vector);
@@ -367,12 +371,48 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,msix_write_config (pci_dev, address, val, len); } +static int virtio_pci_irqfd (void * opaque,uint16_t vector,int fd) +{ +VirtIOPCIProxy *proxy = opaque; +struct kvm_irqfd call = { }; +int r; + +if (vector >= proxy->pci_dev.msix_entries_nr) +return -EINVAL ; +if (!proxy->pci_dev.msix_entry_used[vector]) +return -ENOENT ; + call.fd = fd; + call.gsi = proxy->pci_dev.msix_irq_entries[vector].gsi; + r =kvm_vm_ioctl (kvm_state,KVM_IRQFD , &call); +if (r <0 ) +return r; +return 0 ; +} + +static int virtio_pci_queuefd (void * opaque,int n,int fd) +{ +VirtIOPCIProxy *proxy = opaque; +struct kvm_ioeventfd kick = { + .datamatch = n, + .addr = proxy->addr +VIRTIO_PCI_QUEUE_NOTIFY , + .len =2 , + .flags =KVM_IOEVENTFD_FLAG_DATAMATCH |KVM_IOEVENTFD_FLAG_PIO , + .fd = fd, + }; +int r =kvm_vm_ioctl (kvm_state,KVM_IOEVENTFD , &kick); +if (r <0 ) +return r; +return 0 ; +} +static const VirtIOBindings virtio_pci_bindings = { .notify = virtio_pci_notify, .save_config = virtio_pci_save_config, .load_config = virtio_pci_load_config, .save_queue = virtio_pci_save_queue, .load_queue = virtio_pci_load_queue, + .irqfd = virtio_pci_irqfd, + .queuefd = virtio_pci_queuefd, }; static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
hw/virtio.c +0 -19
@@ -54,24 +54,6 @@ typedef struct VRingUsedVRingUsedElem ring[0 ]; } VRingUsed; -typedef struct VRing -{ -unsigned int num; -target_phys_addr_t desc; -target_phys_addr_t avail; -target_phys_addr_t used; -}VRing ; - -struct VirtQueue -{ -VRing vring; -target_phys_addr_t pa; -uint16_t last_avail_idx; -int inuse; -uint16_t vector; -void (*handle_output)(VirtIODevice *vdev,VirtQueue *vq); -}; -#define VIRTIO_PCI_QUEUE_MAX 16/* virt queue functions */
@@ -401,7 +383,6 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) sg->iov_base =cpu_physical_memory_map (vring_desc_addr (desc_pa, i), &len, is_write); -if (sg->iov_base ==NULL || len != sg->iov_len) {fprintf (stderr,"virtio: trying to map MMIO memory\n" );exit (1 );
hw/virtio.h +25 -3
@@ -53,15 +53,34 @@struct VirtQueue ; +typedef struct VRing +{ +unsigned int num; +target_phys_addr_t desc; +target_phys_addr_t avail; +target_phys_addr_t used; +}VRing ; + +typedef struct VirtQueue VirtQueue ; +struct VirtIODevice ; +typedef struct VirtIODevice VirtIODevice ; + +struct VirtQueue +{ +VRing vring; +target_phys_addr_t pa; +uint16_t last_avail_idx; +int inuse; +uint16_t vector; +void (*handle_output)(VirtIODevice *vdev,VirtQueue *vq); +}; +static inline target_phys_addr_t vring_align (target_phys_addr_t addr,unsigned long align) {return (addr + align -1 ) & ~(align -1 ); } -typedef struct VirtQueue VirtQueue ; -typedef struct VirtIODevice VirtIODevice ; -#define VIRTQUEUE_MAX_SIZE 1024 typedef struct VirtQueueElement
@@ -80,6 +99,8 @@ typedef struct {void (*save_queue)(void * opaque,int n,QEMUFile *f);int (*load_config)(void * opaque,QEMUFile *f);int (*load_queue)(void * opaque,int n,QEMUFile *f); +int (*irqfd)(void * opaque,uint16_t vector,int fd); +int (*queuefd)(void * opaque,int n,int fd); } VirtIOBindings;#define VIRTIO_PCI_QUEUE_MAX 16
@@ -103,6 +124,7 @@ struct VirtIODevicevoid (*get_config)(VirtIODevice *vdev,uint8_t *config);void (*set_config)(VirtIODevice *vdev,const uint8_t *config);void (*reset)(VirtIODevice *vdev); +void (*driver_ok)(VirtIODevice *vdev);VirtQueue *vq;const VirtIOBindings *binding;void *binding_opaque;
net.c +6 -2
@@ -1903,7 +1903,7 @@ static TAPState *net_tap_init(VLANState *vlan, const char *model,typedef struct RAWState {VLANClientState *vc;int fd; -uint8_t buf[4096 ]; +uint8_t buf[65000 ];int promisc; }RAWState ;
@@ -2745,7 +2745,8 @@ int net_client_init(Monitor *mon, const char *device, const char *p) }if (!strcmp (device,"nic" )) {static const char *const nic_params[] = { -"vlan" ,"name" ,"macaddr" ,"model" ,"addr" ,"vectors" ,NULL +"vlan" ,"name" ,"macaddr" ,"model" ,"addr" ,"vectors" , +"vhost" ,NULL };NICInfo *nd;uint8_t *macaddr;
@@ -2777,6 +2778,9 @@ int net_client_init(Monitor *mon, const char *device, const char *p) goto out; } } +if (get_param_value (buf,sizeof (buf),"vhost" , p)) { + nd->vhost_device =strdup (buf); + }if (get_param_value (buf,sizeof (buf),"model" , p)) { nd->model =strdup (buf); }
net.h +1 -0
@@ -109,6 +109,7 @@ struct NICInfo {int used;int bootable;int nvectors; +char *vhost_device; };extern int nb_nics;
qemu-kvm.c +0 -8
@@ -136,14 +136,6 @@ static inline void clear_gsi(kvm_context_t kvm, unsigned int gsi)DPRINTF ("Invalid GSI %d\n" ); } -struct slot_info { -unsigned long phys_addr; -unsigned long len; -unsigned long userspace_addr; -unsigned flags; -int logging_count; -}; -struct slot_info slots[KVM_MAX_NUM_MEM_REGIONS ];static void init_slots (void )
qemu-kvm.h +9 -0
@@ -1211,6 +1211,15 @@ int kvm_ioctl(KVMState *s, int type, ...);int kvm_vm_ioctl (KVMState *s,int type, ...);int kvm_check_extension (KVMState *s,unsigned int ext); +struct slot_info { +unsigned long phys_addr; +unsigned long len; +unsigned long userspace_addr; +unsigned flags; +int logging_count; +}; + +extern struct slot_info slots[KVM_MAX_NUM_MEM_REGIONS ];#endif #endif
Signature · 1 line
1.6.2.5
Michael S. Tsirkin
maintainerPATCH 3/3 qemu-kvm: vhost-net implementation
In reply to a message not in the archiveThis adds support for vhost-net virtio kernel backend. To enable (assuming device eth2):
1. enable promisc mode or program guest mac in device eth2
2. disable tso, gso, lro on the card
3. add vhost=eth0 to -net flag
4. run with CAP_NET_ADMIN priviledge (e.g. root)
This patch is RFC, but works without issues for me.
It still needs to be split up, tested and benchmarked properly, but posting it here in case people want to test drive the kernel bits I posted.
--- Makefile.target | 3 +- hw/vhost_net.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/vhost_net.h | 30 +++++++++ hw/virtio-net.c | 32 ++++++++++- hw/virtio-pci.c | 40 ++++++++++++ hw/virtio.c | 19 ------ hw/virtio.h | 28 ++++++++- net.c | 8 ++- net.h | 1 + qemu-kvm.c | 8 --- qemu-kvm.h | 9 +++ 11 files changed, 325 insertions(+), 34 deletions(-) create mode 100644 hw/vhost_net.c create mode 100644 hw/vhost_net.h
Makefile.target +2 -1
@@ -538,7 +538,8 @@ obj-y = vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o \ gdbstub.o gdbstub-xml.o msix.o ioport.o # virtio has to be here due to weird dependency between PCI and virtio-net. # need to fix this properly -obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o +obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o \ + vhost_net.o obj-$(CONFIG_KVM) += kvm.o kvm-all.o LIBS+=-lz
hw/vhost_net.c new file +181 -0
181 lines not on this page · raw message
hw/vhost_net.h new file +30 -0
@@ -0,0 +1,30 @@ +#ifndef VHOST_NET_H +#define VHOST_NET_H + +#include "hw/virtio.h" + +struct vhost_virtqueue { +int kick; +int call; +void *desc; +void *avail; +void *used; +}; + +struct vhost_dev { +int control; +struct vhost_virtqueue *vqs; +int nvqs; +}; + +struct vhost_net { +struct vhost_dev dev; +struct vhost_virtqueue vqs[2 ]; +int sock; +}; + +int vhost_net_init (struct vhost_net *net, +VirtIODevice *dev, +char *vhost_device); + +#endif
hw/virtio-net.c +31 -1
@@ -19,6 +19,8 @@#include "qemu-kvm.h" #endif +#include "vhost_net.h" +#define TAP_VNET_HDR #define VIRTIO_NET_VM_VERSION 10
@@ -56,6 +58,8 @@ typedef struct VirtIONetuint8_t *macs; } mac_table;uint32_t *vlans; +char *vhost_device; +struct vhost_net vhost; } VirtIONet;/* TODO
@@ -134,9 +138,12 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) (1 <<VIRTIO_NET_F_CTRL_RX ) | (1 <<VIRTIO_NET_F_CTRL_VLAN ) | (1 <<VIRTIO_NET_F_CTRL_RX_EXTRA ); +VirtIONet *n =to_virtio_net (vdev); + +if (n->vhost_device) +return 1 <<VIRTIO_NET_F_MAC ;#ifdef TAP_VNET_HDR -VirtIONet *n =to_virtio_net (vdev);VLANClientState *host = n->vc->vlan->first_client;if (tap_has_vnet_hdr (host)) {
@@ -175,6 +182,9 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev)static void virtio_net_set_features (VirtIODevice *vdev,uint32_t features) {VirtIONet *n =to_virtio_net (vdev); +/* vhost net supports no features */ +if (n->vhost_device) +return ;#ifdef TAP_VNET_HDR VLANClientState *host = n->vc->vlan->first_client;#endif
@@ -351,6 +361,9 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)static int do_virtio_net_can_receive (VirtIONet *n,int bufsize) { +if (n->vhost_device) +return 0 ; +if (!virtio_queue_ready (n->rx_vq) || !(n->vdev.status &VIRTIO_CONFIG_S_DRIVER_OK ))return 0 ;
@@ -411,6 +424,7 @@ static int iov_fill(struct iovec *iov, int iovcnt, const void *buf, int count)while (offset < count && i < iovcnt) {int len =MIN (iov[i].iov_len, count - offset);memcpy (iov[i].iov_base, buf + offset, len); + offset += len; i++; }
@@ -611,6 +625,8 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)#else int has_vnet_hdr =0 ;#endif +if (n->vhost_device) +return ;if (!(n->vdev.status &VIRTIO_CONFIG_S_DRIVER_OK ))return ;
@@ -823,6 +839,18 @@ static void virtio_net_cleanup(VLANClientState *vc)virtio_cleanup (&n->vdev); } +static void virtio_net_driver_ok (VirtIODevice *vdev) +{ +VirtIONet *n =to_virtio_net (vdev); +int r; + + r =vhost_net_init (&n->vhost, vdev, n->vhost_device); +if (r) { +fprintf (stderr,"\nvhost_net_init returned %d\n" , r); +exit (-r); + } +} +VirtIODevice *virtio_net_init (DeviceState *dev) {VirtIONet *n;
@@ -838,6 +866,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev) n->vdev.set_features = virtio_net_set_features; n->vdev.bad_features = virtio_net_bad_features; n->vdev.reset = virtio_net_reset; + n->vdev.driver_ok = virtio_net_driver_ok; n->rx_vq =virtio_add_queue (&n->vdev,256 , virtio_net_handle_rx); n->tx_vq =virtio_add_queue (&n->vdev,256 , virtio_net_handle_tx); n->ctrl_vq =virtio_add_queue (&n->vdev,64 , virtio_net_handle_ctrl);
@@ -864,6 +893,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev) n->vdev.nvectors =3 ; else n->vdev.nvectors = dev->nd->nvectors; + n->vhost_device = dev->nd->vhost_device;register_savevm ("virtio-net" , virtio_net_id++,VIRTIO_NET_VM_VERSION , virtio_net_save, virtio_net_load, n);
hw/virtio-pci.c +40 -0
@@ -15,10 +15,12 @@#include <inttypes.h> +#include <linux/kvm.h> #include "virtio.h" #include "pci.h" //#include "sysemu.h" #include "msix.h" +#include "qemu-kvm.h" /* from Linux's linux/virtio_pci.h */
@@ -201,6 +203,8 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) vdev->status = val &0xFF ;if (vdev->status ==0 )virtio_pci_reset (proxy); +if ((val &VIRTIO_CONFIG_S_DRIVER_OK ) && vdev->driver_ok) + vdev->driver_ok (vdev);break ;case VIRTIO_MSI_CONFIG_VECTOR :msix_vector_unuse (&proxy->pci_dev, vdev->config_vector);
@@ -367,12 +371,48 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,msix_write_config (pci_dev, address, val, len); } +static int virtio_pci_irqfd (void * opaque,uint16_t vector,int fd) +{ +VirtIOPCIProxy *proxy = opaque; +struct kvm_irqfd call = { }; +int r; + +if (vector >= proxy->pci_dev.msix_entries_nr) +return -EINVAL ; +if (!proxy->pci_dev.msix_entry_used[vector]) +return -ENOENT ; + call.fd = fd; + call.gsi = proxy->pci_dev.msix_irq_entries[vector].gsi; + r =kvm_vm_ioctl (kvm_state,KVM_IRQFD , &call); +if (r <0 ) +return r; +return 0 ; +} + +static int virtio_pci_queuefd (void * opaque,int n,int fd) +{ +VirtIOPCIProxy *proxy = opaque; +struct kvm_ioeventfd kick = { + .datamatch = n, + .addr = proxy->addr +VIRTIO_PCI_QUEUE_NOTIFY , + .len =2 , + .flags =KVM_IOEVENTFD_FLAG_DATAMATCH |KVM_IOEVENTFD_FLAG_PIO , + .fd = fd, + }; +int r =kvm_vm_ioctl (kvm_state,KVM_IOEVENTFD , &kick); +if (r <0 ) +return r; +return 0 ; +} +static const VirtIOBindings virtio_pci_bindings = { .notify = virtio_pci_notify, .save_config = virtio_pci_save_config, .load_config = virtio_pci_load_config, .save_queue = virtio_pci_save_queue, .load_queue = virtio_pci_load_queue, + .irqfd = virtio_pci_irqfd, + .queuefd = virtio_pci_queuefd, }; static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
hw/virtio.c +0 -19
@@ -54,24 +54,6 @@ typedef struct VRingUsedVRingUsedElem ring[0 ]; } VRingUsed; -typedef struct VRing -{ -unsigned int num; -target_phys_addr_t desc; -target_phys_addr_t avail; -target_phys_addr_t used; -}VRing ; - -struct VirtQueue -{ -VRing vring; -target_phys_addr_t pa; -uint16_t last_avail_idx; -int inuse; -uint16_t vector; -void (*handle_output)(VirtIODevice *vdev,VirtQueue *vq); -}; -#define VIRTIO_PCI_QUEUE_MAX 16/* virt queue functions */
@@ -401,7 +383,6 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) sg->iov_base =cpu_physical_memory_map (vring_desc_addr (desc_pa, i), &len, is_write); -if (sg->iov_base ==NULL || len != sg->iov_len) {fprintf (stderr,"virtio: trying to map MMIO memory\n" );exit (1 );
hw/virtio.h +25 -3
@@ -53,15 +53,34 @@struct VirtQueue ; +typedef struct VRing +{ +unsigned int num; +target_phys_addr_t desc; +target_phys_addr_t avail; +target_phys_addr_t used; +}VRing ; + +typedef struct VirtQueue VirtQueue ; +struct VirtIODevice ; +typedef struct VirtIODevice VirtIODevice ; + +struct VirtQueue +{ +VRing vring; +target_phys_addr_t pa; +uint16_t last_avail_idx; +int inuse; +uint16_t vector; +void (*handle_output)(VirtIODevice *vdev,VirtQueue *vq); +}; +static inline target_phys_addr_t vring_align (target_phys_addr_t addr,unsigned long align) {return (addr + align -1 ) & ~(align -1 ); } -typedef struct VirtQueue VirtQueue ; -typedef struct VirtIODevice VirtIODevice ; -#define VIRTQUEUE_MAX_SIZE 1024 typedef struct VirtQueueElement
@@ -80,6 +99,8 @@ typedef struct {void (*save_queue)(void * opaque,int n,QEMUFile *f);int (*load_config)(void * opaque,QEMUFile *f);int (*load_queue)(void * opaque,int n,QEMUFile *f); +int (*irqfd)(void * opaque,uint16_t vector,int fd); +int (*queuefd)(void * opaque,int n,int fd); } VirtIOBindings;#define VIRTIO_PCI_QUEUE_MAX 16
@@ -103,6 +124,7 @@ struct VirtIODevicevoid (*get_config)(VirtIODevice *vdev,uint8_t *config);void (*set_config)(VirtIODevice *vdev,const uint8_t *config);void (*reset)(VirtIODevice *vdev); +void (*driver_ok)(VirtIODevice *vdev);VirtQueue *vq;const VirtIOBindings *binding;void *binding_opaque;
net.c +6 -2
@@ -1903,7 +1903,7 @@ static TAPState *net_tap_init(VLANState *vlan, const char *model,typedef struct RAWState {VLANClientState *vc;int fd; -uint8_t buf[4096 ]; +uint8_t buf[65000 ];int promisc; }RAWState ;
@@ -2745,7 +2745,8 @@ int net_client_init(Monitor *mon, const char *device, const char *p) }if (!strcmp (device,"nic" )) {static const char *const nic_params[] = { -"vlan" ,"name" ,"macaddr" ,"model" ,"addr" ,"vectors" ,NULL +"vlan" ,"name" ,"macaddr" ,"model" ,"addr" ,"vectors" , +"vhost" ,NULL };NICInfo *nd;uint8_t *macaddr;
@@ -2777,6 +2778,9 @@ int net_client_init(Monitor *mon, const char *device, const char *p) goto out; } } +if (get_param_value (buf,sizeof (buf),"vhost" , p)) { + nd->vhost_device =strdup (buf); + }if (get_param_value (buf,sizeof (buf),"model" , p)) { nd->model =strdup (buf); }
net.h +1 -0
@@ -109,6 +109,7 @@ struct NICInfo {int used;int bootable;int nvectors; +char *vhost_device; };extern int nb_nics;
qemu-kvm.c +0 -8
@@ -136,14 +136,6 @@ static inline void clear_gsi(kvm_context_t kvm, unsigned int gsi)DPRINTF ("Invalid GSI %d\n" ); } -struct slot_info { -unsigned long phys_addr; -unsigned long len; -unsigned long userspace_addr; -unsigned flags; -int logging_count; -}; -struct slot_info slots[KVM_MAX_NUM_MEM_REGIONS ];static void init_slots (void )
qemu-kvm.h +9 -0
@@ -1211,6 +1211,15 @@ int kvm_ioctl(KVMState *s, int type, ...);int kvm_vm_ioctl (KVMState *s,int type, ...);int kvm_check_extension (KVMState *s,unsigned int ext); +struct slot_info { +unsigned long phys_addr; +unsigned long len; +unsigned long userspace_addr; +unsigned flags; +int logging_count; +}; + +extern struct slot_info slots[KVM_MAX_NUM_MEM_REGIONS ];#endif #endif
Signature · 1 line
1.6.2.5