Update spec changelog
This commit is contained in:
parent
353d209a28
commit
8778212724
316
0001-vhost-net-patches-for-qemu-0.13.0-tarball.patch
Normal file
316
0001-vhost-net-patches-for-qemu-0.13.0-tarball.patch
Normal file
@ -0,0 +1,316 @@
|
||||
From 2ed38f61f1054e188838bae9244fc1c327f8cda4 Mon Sep 17 00:00:00 2001
|
||||
From: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
Date: Mon, 18 Oct 2010 16:17:00 -0200
|
||||
Subject: [PATCH 42/42] vhost-net patches for qemu-0.13.0 tarball
|
||||
|
||||
Justin,
|
||||
|
||||
Attached are the patches to fix vhost-net on the 0.13.0 tarball.
|
||||
Untested.
|
||||
|
||||
commit f76cfc6f0882f227101f21d5a5b80804710b88cb
|
||||
Author: Michael S. Tsirkin <mst@redhat.com>
|
||||
Date: Wed Oct 6 07:22:00 2010 +0200
|
||||
|
||||
vhost: fix up irqfd support
|
||||
|
||||
vhost irqfd support: case where many vqs are
|
||||
mapped to a single msix vector is currently broken.
|
||||
Fix it up.
|
||||
|
||||
Includes this patch from qemu.git:
|
||||
|
||||
virtio: change set guest notifier to per-device
|
||||
|
||||
When using irqfd with vhost-net to inject interrupts,
|
||||
a single evenfd might inject multiple interrupts.
|
||||
Implementing this is much easier with a single
|
||||
per-device callback to set guest notifiers.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/msix.c | 82 +++++++++++++++++++++++++++++++-----------------------
|
||||
hw/msix.h | 4 +-
|
||||
hw/pci.h | 3 +-
|
||||
hw/virtio-pci.c | 56 +++++++++++++++++++++++++++++++------
|
||||
4 files changed, 97 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/hw/msix.c b/hw/msix.c
|
||||
index 3dd0456..c0c6b50 100644
|
||||
--- a/hw/msix.c
|
||||
+++ b/hw/msix.c
|
||||
@@ -300,10 +300,8 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
|
||||
if (kvm_enabled() && kvm_irqchip_in_kernel()) {
|
||||
kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector));
|
||||
}
|
||||
- if (was_masked != msix_is_masked(dev, vector) &&
|
||||
- dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
|
||||
+ if (was_masked != msix_is_masked(dev, vector) && dev->msix_mask_notifier) {
|
||||
int r = dev->msix_mask_notifier(dev, vector,
|
||||
- dev->msix_mask_notifier_opaque[vector],
|
||||
msix_is_masked(dev, vector));
|
||||
assert(r >= 0);
|
||||
}
|
||||
@@ -351,9 +349,8 @@ static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
|
||||
int was_masked = msix_is_masked(dev, vector);
|
||||
dev->msix_table_page[offset] |= MSIX_VECTOR_MASK;
|
||||
if (was_masked != msix_is_masked(dev, vector) &&
|
||||
- dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
|
||||
+ dev->msix_mask_notifier) {
|
||||
r = dev->msix_mask_notifier(dev, vector,
|
||||
- dev->msix_mask_notifier_opaque[vector],
|
||||
msix_is_masked(dev, vector));
|
||||
assert(r >= 0);
|
||||
}
|
||||
@@ -379,8 +376,6 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
|
||||
sizeof *dev->msix_irq_entries);
|
||||
}
|
||||
#endif
|
||||
- dev->msix_mask_notifier_opaque =
|
||||
- qemu_mallocz(nentries * sizeof *dev->msix_mask_notifier_opaque);
|
||||
dev->msix_mask_notifier = NULL;
|
||||
dev->msix_entry_used = qemu_mallocz(MSIX_MAX_ENTRIES *
|
||||
sizeof *dev->msix_entry_used);
|
||||
@@ -444,8 +439,6 @@ int msix_uninit(PCIDevice *dev)
|
||||
dev->msix_entry_used = NULL;
|
||||
qemu_free(dev->msix_irq_entries);
|
||||
dev->msix_irq_entries = NULL;
|
||||
- qemu_free(dev->msix_mask_notifier_opaque);
|
||||
- dev->msix_mask_notifier_opaque = NULL;
|
||||
dev->cap_present &= ~QEMU_PCI_CAP_MSIX;
|
||||
return 0;
|
||||
}
|
||||
@@ -590,46 +583,65 @@ void msix_unuse_all_vectors(PCIDevice *dev)
|
||||
msix_free_irq_entries(dev);
|
||||
}
|
||||
|
||||
-int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque)
|
||||
+/* Invoke the notifier if vector entry is used and unmasked. */
|
||||
+static int msix_notify_if_unmasked(PCIDevice *dev, unsigned vector, int masked)
|
||||
{
|
||||
- int r = 0;
|
||||
- if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
|
||||
+ assert(dev->msix_mask_notifier);
|
||||
+ if (!dev->msix_entry_used[vector] || msix_is_masked(dev, vector)) {
|
||||
return 0;
|
||||
+ }
|
||||
+ return dev->msix_mask_notifier(dev, vector, masked);
|
||||
+}
|
||||
|
||||
- assert(dev->msix_mask_notifier);
|
||||
- assert(opaque);
|
||||
- assert(!dev->msix_mask_notifier_opaque[vector]);
|
||||
+static int msix_set_mask_notifier_for_vector(PCIDevice *dev, unsigned vector)
|
||||
+{
|
||||
+ /* Notifier has been set. Invoke it on unmasked vectors. */
|
||||
+ return msix_notify_if_unmasked(dev, vector, 0);
|
||||
+}
|
||||
+
|
||||
+static int msix_unset_mask_notifier_for_vector(PCIDevice *dev, unsigned vector)
|
||||
+{
|
||||
+ /* Notifier will be unset. Invoke it to mask unmasked entries. */
|
||||
+ return msix_notify_if_unmasked(dev, vector, 1);
|
||||
+}
|
||||
|
||||
- /* Unmask the new notifier unless vector is masked. */
|
||||
- if (!msix_is_masked(dev, vector)) {
|
||||
- r = dev->msix_mask_notifier(dev, vector, opaque, false);
|
||||
+int msix_set_mask_notifier(PCIDevice *dev, msix_mask_notifier_func f)
|
||||
+{
|
||||
+ int r, n;
|
||||
+ assert(!dev->msix_mask_notifier);
|
||||
+ dev->msix_mask_notifier = f;
|
||||
+ for (n = 0; n < dev->msix_entries_nr; ++n) {
|
||||
+ r = msix_set_mask_notifier_for_vector(dev, n);
|
||||
if (r < 0) {
|
||||
- return r;
|
||||
+ goto undo;
|
||||
}
|
||||
}
|
||||
- dev->msix_mask_notifier_opaque[vector] = opaque;
|
||||
+ return 0;
|
||||
+
|
||||
+undo:
|
||||
+ while (--n >= 0) {
|
||||
+ msix_unset_mask_notifier_for_vector(dev, n);
|
||||
+ }
|
||||
+ dev->msix_mask_notifier = NULL;
|
||||
return r;
|
||||
}
|
||||
|
||||
-int msix_unset_mask_notifier(PCIDevice *dev, unsigned vector)
|
||||
+int msix_unset_mask_notifier(PCIDevice *dev)
|
||||
{
|
||||
- int r = 0;
|
||||
- void *opaque;
|
||||
- if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
|
||||
- return 0;
|
||||
-
|
||||
- opaque = dev->msix_mask_notifier_opaque[vector];
|
||||
-
|
||||
+ int r, n;
|
||||
assert(dev->msix_mask_notifier);
|
||||
- assert(opaque);
|
||||
-
|
||||
- /* Mask the old notifier unless it is already masked. */
|
||||
- if (!msix_is_masked(dev, vector)) {
|
||||
- r = dev->msix_mask_notifier(dev, vector, opaque, true);
|
||||
+ for (n = 0; n < dev->msix_entries_nr; ++n) {
|
||||
+ r = msix_unset_mask_notifier_for_vector(dev, n);
|
||||
if (r < 0) {
|
||||
- return r;
|
||||
+ goto undo;
|
||||
}
|
||||
}
|
||||
- dev->msix_mask_notifier_opaque[vector] = NULL;
|
||||
+ dev->msix_mask_notifier = NULL;
|
||||
+ return 0;
|
||||
+
|
||||
+undo:
|
||||
+ while (--n >= 0) {
|
||||
+ msix_set_mask_notifier_for_vector(dev, n);
|
||||
+ }
|
||||
return r;
|
||||
}
|
||||
diff --git a/hw/msix.h b/hw/msix.h
|
||||
index 6b21ffb..5a81df5 100644
|
||||
--- a/hw/msix.h
|
||||
+++ b/hw/msix.h
|
||||
@@ -33,6 +33,6 @@ void msix_reset(PCIDevice *dev);
|
||||
|
||||
extern int msix_supported;
|
||||
|
||||
-int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque);
|
||||
-int msix_unset_mask_notifier(PCIDevice *dev, unsigned vector);
|
||||
+int msix_set_mask_notifier(PCIDevice *dev, msix_mask_notifier_func);
|
||||
+int msix_unset_mask_notifier(PCIDevice *dev);
|
||||
#endif
|
||||
diff --git a/hw/pci.h b/hw/pci.h
|
||||
index ccb99d0..a40dc14 100644
|
||||
--- a/hw/pci.h
|
||||
+++ b/hw/pci.h
|
||||
@@ -131,7 +131,7 @@ enum {
|
||||
#define PCI_CAPABILITY_CONFIG_MSIX_LENGTH 0x10
|
||||
|
||||
typedef int (*msix_mask_notifier_func)(PCIDevice *, unsigned vector,
|
||||
- void *opaque, int masked);
|
||||
+ int masked);
|
||||
|
||||
struct PCIDevice {
|
||||
DeviceState qdev;
|
||||
@@ -198,7 +198,6 @@ struct PCIDevice {
|
||||
|
||||
struct kvm_irq_routing_entry *msix_irq_entries;
|
||||
|
||||
- void **msix_mask_notifier_opaque;
|
||||
msix_mask_notifier_func msix_mask_notifier;
|
||||
|
||||
/* Device capability configuration space */
|
||||
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
|
||||
index 83b7871..72bc80e 100644
|
||||
--- a/hw/virtio-pci.c
|
||||
+++ b/hw/virtio-pci.c
|
||||
@@ -427,11 +427,10 @@ static void virtio_pci_guest_notifier_read(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
-static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
|
||||
- void *opaque, int masked)
|
||||
+static int virtio_pci_mask_vq(PCIDevice *dev, unsigned vector,
|
||||
+ VirtQueue *vq, int masked)
|
||||
{
|
||||
#ifdef CONFIG_KVM
|
||||
- VirtQueue *vq = opaque;
|
||||
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
|
||||
int r = kvm_set_irqfd(dev->msix_irq_entries[vector].gsi,
|
||||
event_notifier_get_fd(notifier),
|
||||
@@ -452,6 +451,34 @@ static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
|
||||
#endif
|
||||
}
|
||||
|
||||
+static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
|
||||
+ int masked)
|
||||
+{
|
||||
+ VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
|
||||
+ VirtIODevice *vdev = proxy->vdev;
|
||||
+ int r, n;
|
||||
+
|
||||
+ for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
|
||||
+ if (!virtio_queue_get_num(vdev, n)) {
|
||||
+ break;
|
||||
+ }
|
||||
+ if (virtio_queue_vector(vdev, n) != vector) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ r = virtio_pci_mask_vq(dev, vector, virtio_get_queue(vdev, n), masked);
|
||||
+ if (r < 0) {
|
||||
+ goto undo;
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+undo:
|
||||
+ while (--n >= 0) {
|
||||
+ virtio_pci_mask_vq(dev, vector, virtio_get_queue(vdev, n), !masked);
|
||||
+ }
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
|
||||
{
|
||||
VirtIOPCIProxy *proxy = opaque;
|
||||
@@ -465,11 +492,7 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
|
||||
}
|
||||
qemu_set_fd_handler(event_notifier_get_fd(notifier),
|
||||
virtio_pci_guest_notifier_read, NULL, vq);
|
||||
- msix_set_mask_notifier(&proxy->pci_dev,
|
||||
- virtio_queue_vector(proxy->vdev, n), vq);
|
||||
} else {
|
||||
- msix_unset_mask_notifier(&proxy->pci_dev,
|
||||
- virtio_queue_vector(proxy->vdev, n));
|
||||
qemu_set_fd_handler(event_notifier_get_fd(notifier),
|
||||
NULL, NULL, NULL);
|
||||
/* Test and clear notifier before closing it,
|
||||
@@ -487,6 +510,13 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
|
||||
VirtIODevice *vdev = proxy->vdev;
|
||||
int r, n;
|
||||
|
||||
+ /* Must unset mask notifier while guest notifier
|
||||
+ * is still assigned */
|
||||
+ if (!assign) {
|
||||
+ r = msix_unset_mask_notifier(&proxy->pci_dev);
|
||||
+ assert(r >= 0);
|
||||
+ }
|
||||
+
|
||||
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
|
||||
if (!virtio_queue_get_num(vdev, n)) {
|
||||
break;
|
||||
@@ -498,6 +528,16 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Must set mask notifier after guest notifier
|
||||
+ * has been assigned */
|
||||
+ if (assign) {
|
||||
+ r = msix_set_mask_notifier(&proxy->pci_dev,
|
||||
+ virtio_pci_mask_notifier);
|
||||
+ if (r < 0) {
|
||||
+ goto assign_error;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
|
||||
assign_error:
|
||||
@@ -583,8 +623,6 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
|
||||
|
||||
proxy->pci_dev.config_write = virtio_write_config;
|
||||
|
||||
- proxy->pci_dev.msix_mask_notifier = virtio_pci_mask_notifier;
|
||||
-
|
||||
size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
|
||||
if (size & (size-1))
|
||||
size = 1 << qemu_fls(size);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,43 +0,0 @@
|
||||
From af483cb870ad81dce8e10215e0add284fcc38da4 Mon Sep 17 00:00:00 2001
|
||||
From: Michael S. Tsirkin <mst@redhat.com>
|
||||
Date: Wed, 24 Feb 2010 21:09:45 +0200
|
||||
Subject: [PATCH] msix: migration fix
|
||||
|
||||
Be careful to match mask/unmask callbacks from msix.
|
||||
Fixes crash during migration.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/msix.c | 16 +++++++++++++---
|
||||
1 files changed, 13 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/msix.c b/hw/msix.c
|
||||
index 3fcf3a1..fafaf09 100644
|
||||
--- a/hw/msix.c
|
||||
+++ b/hw/msix.c
|
||||
@@ -614,9 +614,19 @@ int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque)
|
||||
if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
|
||||
return 0;
|
||||
|
||||
- if (dev->msix_mask_notifier)
|
||||
- r = dev->msix_mask_notifier(dev, vector, opaque,
|
||||
- msix_is_masked(dev, vector));
|
||||
+ if (dev->msix_mask_notifier && !msix_is_masked(dev, vector)) {
|
||||
+ /* Mask previous notifier if any */
|
||||
+ if (dev->msix_mask_notifier_opaque[vector]) {
|
||||
+ r = dev->msix_mask_notifier(dev, vector,
|
||||
+ dev->msix_mask_notifier_opaque[vector],
|
||||
+ 1);
|
||||
+ assert(r >= 0);
|
||||
+ }
|
||||
+ /* Unmask new notifier, assumed to be masked at start */
|
||||
+ if (opaque) {
|
||||
+ r = dev->msix_mask_notifier(dev, vector, opaque, 0);
|
||||
+ }
|
||||
+ }
|
||||
if (r >= 0)
|
||||
dev->msix_mask_notifier_opaque[vector] = opaque;
|
||||
return r;
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,28 +0,0 @@
|
||||
From c96adfe57a5a7ceed488fd6f198a762dd84c1d9c Mon Sep 17 00:00:00 2001
|
||||
From: Michael S. Tsirkin <mst@redhat.com>
|
||||
Date: Wed, 24 Feb 2010 21:09:48 +0200
|
||||
Subject: [PATCH] vhost: logging thinko fix
|
||||
|
||||
Fix logging: set it to requested value.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/vhost.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/hw/vhost.c b/hw/vhost.c
|
||||
index e5c1ead..3c54596 100644
|
||||
--- a/hw/vhost.c
|
||||
+++ b/hw/vhost.c
|
||||
@@ -310,7 +310,7 @@ static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
|
||||
{
|
||||
uint64_t features = dev->acked_features;
|
||||
int r;
|
||||
- if (dev->log_enabled) {
|
||||
+ if (enable_log) {
|
||||
features |= 0x1 << VHOST_F_LOG_ALL;
|
||||
}
|
||||
r = ioctl(dev->control, VHOST_SET_FEATURES, &features);
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,72 +0,0 @@
|
||||
From 575c00a2880177295a116d43132566143af69a0b Mon Sep 17 00:00:00 2001
|
||||
From: Michael S. Tsirkin <mst@redhat.com>
|
||||
Date: Wed, 24 Feb 2010 21:09:51 +0200
|
||||
Subject: [PATCH] vhost: move vhost_set_vq_addr
|
||||
|
||||
Move function in file: we'll add another
|
||||
call site in the following patch.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/vhost.c | 38 +++++++++++++++++++-------------------
|
||||
1 files changed, 19 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/hw/vhost.c b/hw/vhost.c
|
||||
index 3c54596..54386e1 100644
|
||||
--- a/hw/vhost.c
|
||||
+++ b/hw/vhost.c
|
||||
@@ -306,6 +306,25 @@ static void vhost_client_set_memory(CPUPhysMemoryClient *client,
|
||||
}
|
||||
}
|
||||
|
||||
+static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
|
||||
+ struct vhost_virtqueue *vq,
|
||||
+ unsigned idx, bool enable_log)
|
||||
+{
|
||||
+ struct vhost_vring_addr addr = {
|
||||
+ .index = idx,
|
||||
+ .desc_user_addr = (u_int64_t)(unsigned long)vq->desc,
|
||||
+ .avail_user_addr = (u_int64_t)(unsigned long)vq->avail,
|
||||
+ .used_user_addr = (u_int64_t)(unsigned long)vq->used,
|
||||
+ .log_guest_addr = vq->used_phys,
|
||||
+ .flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0,
|
||||
+ };
|
||||
+ int r = ioctl(dev->control, VHOST_SET_VRING_ADDR, &addr);
|
||||
+ if (r < 0) {
|
||||
+ return -errno;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
|
||||
{
|
||||
uint64_t features = dev->acked_features;
|
||||
@@ -350,25 +369,6 @@ static int vhost_client_migration_log(struct CPUPhysMemoryClient *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
|
||||
- struct vhost_virtqueue *vq,
|
||||
- unsigned idx, bool enable_log)
|
||||
-{
|
||||
- struct vhost_vring_addr addr = {
|
||||
- .index = idx,
|
||||
- .desc_user_addr = (u_int64_t)(unsigned long)vq->desc,
|
||||
- .avail_user_addr = (u_int64_t)(unsigned long)vq->avail,
|
||||
- .used_user_addr = (u_int64_t)(unsigned long)vq->used,
|
||||
- .log_guest_addr = vq->used_phys,
|
||||
- .flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0,
|
||||
- };
|
||||
- int r = ioctl(dev->control, VHOST_SET_VRING_ADDR, &addr);
|
||||
- if (r < 0) {
|
||||
- return -errno;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int vhost_virtqueue_init(struct vhost_dev *dev,
|
||||
struct VirtIODevice *vdev,
|
||||
struct vhost_virtqueue *vq,
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,70 +0,0 @@
|
||||
From ac48d782f3b91b2e9962ded5f8a55bd3929a82a5 Mon Sep 17 00:00:00 2001
|
||||
From: Michael S. Tsirkin <mst@redhat.com>
|
||||
Date: Wed, 24 Feb 2010 21:09:54 +0200
|
||||
Subject: [PATCH] vhost: used addr migration fix
|
||||
|
||||
Enable used buffer logging when migration starts.
|
||||
Fixed 'id XX is not a head' message after migration.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/vhost.c | 29 +++++++++++++++++++++++++++--
|
||||
1 files changed, 27 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/vhost.c b/hw/vhost.c
|
||||
index 54386e1..48034ba 100644
|
||||
--- a/hw/vhost.c
|
||||
+++ b/hw/vhost.c
|
||||
@@ -325,7 +325,7 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
|
||||
+static int vhost_dev_set_features(struct vhost_dev *dev, bool enable_log)
|
||||
{
|
||||
uint64_t features = dev->acked_features;
|
||||
int r;
|
||||
@@ -336,6 +336,31 @@ static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
|
||||
return r < 0 ? -errno : 0;
|
||||
}
|
||||
|
||||
+static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
|
||||
+{
|
||||
+ int r, t, i;
|
||||
+ r = vhost_dev_set_features(dev, enable_log);
|
||||
+ if (r < 0)
|
||||
+ goto err_features;
|
||||
+ for (i = 0; i < dev->nvqs; ++i) {
|
||||
+ r = vhost_virtqueue_set_addr(dev, dev->vqs + i, i,
|
||||
+ enable_log);
|
||||
+ if (r < 0)
|
||||
+ goto err_vq;
|
||||
+ }
|
||||
+ return 0;
|
||||
+err_vq:
|
||||
+ for (; i >= 0; --i) {
|
||||
+ t = vhost_virtqueue_set_addr(dev, dev->vqs + i, i,
|
||||
+ dev->log_enabled);
|
||||
+ assert(t >= 0);
|
||||
+ }
|
||||
+ t = vhost_dev_set_features(dev, dev->log_enabled);
|
||||
+ assert(t >= 0);
|
||||
+err_features:
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
static int vhost_client_migration_log(struct CPUPhysMemoryClient *client,
|
||||
int enable)
|
||||
{
|
||||
@@ -544,7 +569,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
- r = vhost_dev_set_log(hdev, hdev->log_enabled);
|
||||
+ r = vhost_dev_set_features(hdev, hdev->log_enabled);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
r = ioctl(hdev->control, VHOST_SET_MEM_TABLE, hdev->mem);
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,37 +0,0 @@
|
||||
From 91c827f000a94908b043b5de68eb0cd4fb6ff83d Mon Sep 17 00:00:00 2001
|
||||
From: Michael S. Tsirkin <mst@redhat.com>
|
||||
Date: Wed, 24 Feb 2010 21:09:58 +0200
|
||||
Subject: [PATCH] vhost: fix used logging size math
|
||||
|
||||
Must include used header as well, not only ring
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/vhost.c | 4 +++-
|
||||
1 files changed, 3 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/hw/vhost.c b/hw/vhost.c
|
||||
index 48034ba..7391bd1 100644
|
||||
--- a/hw/vhost.c
|
||||
+++ b/hw/vhost.c
|
||||
@@ -62,7 +62,8 @@ static int vhost_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,
|
||||
}
|
||||
for (i = 0; i < dev->nvqs; ++i) {
|
||||
struct vhost_virtqueue *vq = dev->vqs + i;
|
||||
- unsigned size = sizeof(struct vring_used_elem) * vq->num;
|
||||
+ unsigned size = offsetof(struct vring_used, ring) +
|
||||
+ sizeof(struct vring_used_elem) * vq->num;
|
||||
vhost_dev_sync_region(dev, start_addr, end_addr, vq->used_phys,
|
||||
range_get_last(vq->used_phys, size));
|
||||
}
|
||||
@@ -230,6 +231,7 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev)
|
||||
for (i = 0; i < dev->nvqs; ++i) {
|
||||
struct vhost_virtqueue *vq = dev->vqs + i;
|
||||
uint64_t last = vq->used_phys +
|
||||
+ offsetof(struct vring_used, ring) +
|
||||
sizeof(struct vring_used_elem) * vq->num - 1;
|
||||
log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,26 +0,0 @@
|
||||
From b4654f7911adb1352c2c47c76f650e8419a20b91 Mon Sep 17 00:00:00 2001
|
||||
From: Michael S. Tsirkin <mst@redhat.com>
|
||||
Date: Wed, 24 Feb 2010 21:10:01 +0200
|
||||
Subject: [PATCH] vhost: logging mistake enable, not disable log
|
||||
|
||||
Correctly pass log enable value from memory client to vhost device.
|
||||
---
|
||||
hw/vhost.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/hw/vhost.c b/hw/vhost.c
|
||||
index 7391bd1..019afc2 100644
|
||||
--- a/hw/vhost.c
|
||||
+++ b/hw/vhost.c
|
||||
@@ -387,7 +387,7 @@ static int vhost_client_migration_log(struct CPUPhysMemoryClient *client,
|
||||
dev->log_size = 0;
|
||||
} else {
|
||||
vhost_dev_log_resize(dev, vhost_get_log_size(dev));
|
||||
- r = vhost_dev_set_log(dev, false);
|
||||
+ r = vhost_dev_set_log(dev, true);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,38 +0,0 @@
|
||||
From d42430f94c77a653da486e6f96f6695818f3e81b Mon Sep 17 00:00:00 2001
|
||||
From: Michael S. Tsirkin <mst@redhat.com>
|
||||
Date: Wed, 24 Feb 2010 21:10:04 +0200
|
||||
Subject: [PATCH] vhost: fix log base
|
||||
|
||||
LOG_BASE ioctl gets a pointer to a 64 bit value, not
|
||||
a pointer cast to 64 bit value.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/vhost.c | 5 +++--
|
||||
1 files changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/vhost.c b/hw/vhost.c
|
||||
index 019afc2..b63eafa 100644
|
||||
--- a/hw/vhost.c
|
||||
+++ b/hw/vhost.c
|
||||
@@ -241,14 +241,15 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev)
|
||||
static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
|
||||
{
|
||||
vhost_log_chunk_t *log;
|
||||
+ uint64_t log_base;
|
||||
int r;
|
||||
if (size) {
|
||||
log = qemu_mallocz(size * sizeof *log);
|
||||
} else {
|
||||
log = NULL;
|
||||
}
|
||||
- r = ioctl(dev->control, VHOST_SET_LOG_BASE,
|
||||
- (uint64_t)(unsigned long)log);
|
||||
+ log_base = (uint64_t)(unsigned long)log;
|
||||
+ r = ioctl(dev->control, VHOST_SET_LOG_BASE, &log_base);
|
||||
assert(r >= 0);
|
||||
vhost_client_sync_dirty_bitmap(&dev->client, 0,
|
||||
(target_phys_addr_t)~0x0ull);
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,62 +0,0 @@
|
||||
From 9aa404a57823c9fbf2bf2e0189d31a2b0d8bf3b9 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Thu, 25 Feb 2010 18:41:13 +0530
|
||||
Subject: [PATCH] pc: Add a Fedora-13 machine type that contains backports from upstream
|
||||
|
||||
We have a few features backported from the upstream 0.13 machine type
|
||||
in the repo here.
|
||||
|
||||
Add a 'fedora-13' machine type and use that by default so that users can
|
||||
fall back to a released upstream machine type if desired.
|
||||
|
||||
The fedora-13 machine type has the new multiport-supported virtio-serial
|
||||
and vhost-net patches as of now not present in the 0.12 machine type.
|
||||
|
||||
This is based on upstream commit
|
||||
d76fa62dba54a156ca0f5e79eb33756c9015e02c
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
hw/pc.c | 19 +++++++++++++++++--
|
||||
1 files changed, 17 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/pc.c b/hw/pc.c
|
||||
index 56be728..26c65c1 100644
|
||||
--- a/hw/pc.c
|
||||
+++ b/hw/pc.c
|
||||
@@ -1327,11 +1327,9 @@ void cmos_set_s3_resume(void)
|
||||
|
||||
static QEMUMachine pc_machine = {
|
||||
.name = "pc-0.12",
|
||||
- .alias = "pc",
|
||||
.desc = "Standard PC",
|
||||
.init = pc_init_pci,
|
||||
.max_cpus = 255,
|
||||
- .is_default = 1,
|
||||
};
|
||||
|
||||
static QEMUMachine pc_machine_v0_11 = {
|
||||
@@ -1416,3 +1414,20 @@ static void pc_machine_init(void)
|
||||
}
|
||||
|
||||
machine_init(pc_machine_init);
|
||||
+
|
||||
+/* Fedora machine types */
|
||||
+static QEMUMachine pc_machine_f13 = {
|
||||
+ .name = "fedora-13",
|
||||
+ .alias = "pc",
|
||||
+ .desc = "Standard PC",
|
||||
+ .init = pc_init_pci,
|
||||
+ .max_cpus = 255,
|
||||
+ .is_default = 1,
|
||||
+};
|
||||
+
|
||||
+static void fedora_machine_init(void)
|
||||
+{
|
||||
+ qemu_register_machine(&pc_machine_f13);
|
||||
+}
|
||||
+
|
||||
+machine_init(fedora_machine_init);
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,72 +0,0 @@
|
||||
From f32e21e2828cf7a8aba2fb27945dc46ca2debe09 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Thu, 25 Feb 2010 18:41:14 +0530
|
||||
Subject: [PATCH] pc: Add backward compatibility options for virtio-serial
|
||||
|
||||
virtio-serial-pci can support multiple ports in the current F-13
|
||||
version that will become upstream version 0.13. Add compatibility options
|
||||
for the 0.12, 0.11 and 0.10 pc machine types.
|
||||
|
||||
Based on upstream commit 8bfbde6d35c82cc376681289dae2de5e18a087a4
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
hw/pc.c | 28 ++++++++++++++++++++++++++++
|
||||
1 files changed, 28 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/pc.c b/hw/pc.c
|
||||
index 26c65c1..90bbfe8 100644
|
||||
--- a/hw/pc.c
|
||||
+++ b/hw/pc.c
|
||||
@@ -1330,6 +1330,18 @@ static QEMUMachine pc_machine = {
|
||||
.desc = "Standard PC",
|
||||
.init = pc_init_pci,
|
||||
.max_cpus = 255,
|
||||
+ .compat_props = (GlobalProperty[]) {
|
||||
+ {
|
||||
+ .driver = "virtio-serial-pci",
|
||||
+ .property = "max_nr_ports",
|
||||
+ .value = stringify(1),
|
||||
+ },{
|
||||
+ .driver = "virtio-serial-pci",
|
||||
+ .property = "vectors",
|
||||
+ .value = stringify(0),
|
||||
+ },
|
||||
+ { /* end of list */ }
|
||||
+ }
|
||||
};
|
||||
|
||||
static QEMUMachine pc_machine_v0_11 = {
|
||||
@@ -1351,6 +1363,14 @@ static QEMUMachine pc_machine_v0_11 = {
|
||||
.property = "ver",
|
||||
.value = "0.11",
|
||||
},{
|
||||
+ .driver = "virtio-serial-pci",
|
||||
+ .property = "max_nr_ports",
|
||||
+ .value = stringify(1),
|
||||
+ },{
|
||||
+ .driver = "virtio-serial-pci",
|
||||
+ .property = "vectors",
|
||||
+ .value = stringify(0),
|
||||
+ },{
|
||||
.driver = "PCI",
|
||||
.property = "rombar",
|
||||
.value = stringify(0),
|
||||
@@ -1374,6 +1394,14 @@ static QEMUMachine pc_machine_v0_10 = {
|
||||
.property = "class",
|
||||
.value = stringify(PCI_CLASS_DISPLAY_OTHER),
|
||||
},{
|
||||
+ .driver = "virtio-serial-pci",
|
||||
+ .property = "max_nr_ports",
|
||||
+ .value = stringify(1),
|
||||
+ },{
|
||||
+ .driver = "virtio-serial-pci",
|
||||
+ .property = "vectors",
|
||||
+ .value = stringify(0),
|
||||
+ },{
|
||||
.driver = "virtio-net-pci",
|
||||
.property = "vectors",
|
||||
.value = stringify(0),
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,39 +0,0 @@
|
||||
From e3b132568eef8491decbe30639a9814bdd2d82c0 Mon Sep 17 00:00:00 2001
|
||||
From: Michael S. Tsirkin <mst@redhat.com>
|
||||
Date: Thu, 25 Feb 2010 18:41:15 +0530
|
||||
Subject: [PATCH] virtio-serial: don't set MULTIPORT for 1 port dev
|
||||
|
||||
Since commit 98b19252cf1bd97c54bc4613f3537c5ec0aae263, all
|
||||
serial devices declare MULTIPORT feature.
|
||||
To allow 0.12 compatibility, we should clear this when
|
||||
max_nr_ports is 1.
|
||||
|
||||
Upsream commit: ee4d45be0d791eb8bb0f767cd0f17ea8f697281b
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
hw/virtio-serial-bus.c | 6 ++++--
|
||||
1 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
|
||||
index ab456ea..d0e0219 100644
|
||||
--- a/hw/virtio-serial-bus.c
|
||||
+++ b/hw/virtio-serial-bus.c
|
||||
@@ -335,8 +335,10 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
|
||||
|
||||
static uint32_t get_features(VirtIODevice *vdev, uint32_t features)
|
||||
{
|
||||
- features |= (1 << VIRTIO_CONSOLE_F_MULTIPORT);
|
||||
-
|
||||
+ VirtIOSerial *vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
|
||||
+ if (vser->bus->max_nr_ports > 1) {
|
||||
+ features |= (1 << VIRTIO_CONSOLE_F_MULTIPORT);
|
||||
+ }
|
||||
return features;
|
||||
}
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,44 +0,0 @@
|
||||
From 8a881734bccddf707a42ba2effff699b824d3c8f Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Thu, 25 Feb 2010 18:41:16 +0530
|
||||
Subject: [PATCH] virtio-serial: pci: Allow MSI to be disabled
|
||||
|
||||
Michael noted we don't allow disabling of MSI for the virtio-serial-pci
|
||||
device. Fix that.
|
||||
|
||||
Upstream commit: 7b665b668aa92bf0bba696f085dff87539d95529
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
CC: "Michael S. Tsirkin" <mst@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
hw/virtio-pci.c | 6 +++---
|
||||
1 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
|
||||
index 9a02682..636c8c3 100644
|
||||
--- a/hw/virtio-pci.c
|
||||
+++ b/hw/virtio-pci.c
|
||||
@@ -598,8 +598,8 @@ static int virtio_serial_init_pci(PCIDevice *pci_dev)
|
||||
if (!vdev) {
|
||||
return -1;
|
||||
}
|
||||
- vdev->nvectors = proxy->nvectors ? proxy->nvectors
|
||||
- : proxy->max_virtserial_ports + 1;
|
||||
+ vdev->nvectors = proxy->nvectors == -1 ? proxy->max_virtserial_ports + 1
|
||||
+ : proxy->nvectors;
|
||||
virtio_init_pci(proxy, vdev,
|
||||
PCI_VENDOR_ID_REDHAT_QUMRANET,
|
||||
PCI_DEVICE_ID_VIRTIO_CONSOLE,
|
||||
@@ -683,7 +683,7 @@ static PCIDeviceInfo virtio_info[] = {
|
||||
.init = virtio_serial_init_pci,
|
||||
.exit = virtio_exit_pci,
|
||||
.qdev.props = (Property[]) {
|
||||
- DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 0),
|
||||
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, -1),
|
||||
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
|
||||
DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, max_virtserial_ports,
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,100 +0,0 @@
|
||||
From a0591dc91ad795ffb47476b37730e46977a6be36 Mon Sep 17 00:00:00 2001
|
||||
From: Juan Quintela <quintela@redhat.com>
|
||||
Date: Tue, 9 Mar 2010 23:58:50 +0100
|
||||
Subject: [PATCH] migration: Clear fd also in error cases
|
||||
|
||||
Not clearing the fd and closing the file makes qemu spin using 100%CPU
|
||||
after incoming migration error.
|
||||
|
||||
See for instance bug:
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=518032
|
||||
|
||||
Signed-off-by: Juan Quintela <quintela@trasno.org>
|
||||
---
|
||||
migration-exec.c | 3 +--
|
||||
migration-fd.c | 3 +--
|
||||
migration-tcp.c | 5 ++---
|
||||
migration-unix.c | 5 ++---
|
||||
4 files changed, 6 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/migration-exec.c b/migration-exec.c
|
||||
index 87f645b..e57a55d 100644
|
||||
--- a/migration-exec.c
|
||||
+++ b/migration-exec.c
|
||||
@@ -120,12 +120,11 @@ static void exec_accept_incoming_migration(void *opaque)
|
||||
}
|
||||
qemu_announce_self();
|
||||
dprintf("successfully loaded vm state\n");
|
||||
- /* we've successfully migrated, close the fd */
|
||||
- qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
|
||||
if (autostart)
|
||||
vm_start();
|
||||
|
||||
err:
|
||||
+ qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
|
||||
qemu_fclose(f);
|
||||
}
|
||||
|
||||
diff --git a/migration-fd.c b/migration-fd.c
|
||||
index ef7edbc..7325d13 100644
|
||||
--- a/migration-fd.c
|
||||
+++ b/migration-fd.c
|
||||
@@ -113,12 +113,11 @@ static void fd_accept_incoming_migration(void *opaque)
|
||||
}
|
||||
qemu_announce_self();
|
||||
dprintf("successfully loaded vm state\n");
|
||||
- /* we've successfully migrated, close the fd */
|
||||
- qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
|
||||
if (autostart)
|
||||
vm_start();
|
||||
|
||||
err:
|
||||
+ qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
|
||||
qemu_fclose(f);
|
||||
}
|
||||
|
||||
diff --git a/migration-tcp.c b/migration-tcp.c
|
||||
index 2cfa8cb..c328e73 100644
|
||||
--- a/migration-tcp.c
|
||||
+++ b/migration-tcp.c
|
||||
@@ -170,15 +170,14 @@ static void tcp_accept_incoming_migration(void *opaque)
|
||||
qemu_announce_self();
|
||||
dprintf("successfully loaded vm state\n");
|
||||
|
||||
- /* we've successfully migrated, close the server socket */
|
||||
- qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
|
||||
- close(s);
|
||||
if (autostart)
|
||||
vm_start();
|
||||
|
||||
out_fopen:
|
||||
qemu_fclose(f);
|
||||
out:
|
||||
+ qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
|
||||
+ close(s);
|
||||
close(c);
|
||||
}
|
||||
|
||||
diff --git a/migration-unix.c b/migration-unix.c
|
||||
index a141dbb..9685c4b 100644
|
||||
--- a/migration-unix.c
|
||||
+++ b/migration-unix.c
|
||||
@@ -176,13 +176,12 @@ static void unix_accept_incoming_migration(void *opaque)
|
||||
qemu_announce_self();
|
||||
dprintf("successfully loaded vm state\n");
|
||||
|
||||
- /* we've successfully migrated, close the server socket */
|
||||
- qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
|
||||
- close(s);
|
||||
|
||||
out_fopen:
|
||||
qemu_fclose(f);
|
||||
out:
|
||||
+ qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
|
||||
+ close(s);
|
||||
close(c);
|
||||
}
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,61 +0,0 @@
|
||||
From 361f29d46ce4a310818e88adaef0912573847295 Mon Sep 17 00:00:00 2001
|
||||
From: Cole Robinson <crobinso@redhat.com>
|
||||
Date: Thu, 14 Jan 2010 16:19:40 +0000
|
||||
Subject: [PATCH] raw-posix: Detect CDROM via ioctl on linux
|
||||
|
||||
Current CDROM detection is hardcoded based on source file name.
|
||||
Make this smarter on linux by attempting a CDROM specific ioctl.
|
||||
|
||||
This makes '-cdrom /dev/sr0' succeed with no media present.
|
||||
|
||||
v2:
|
||||
Give ioctl check higher priority than filename check.
|
||||
|
||||
v3:
|
||||
Actually initialize 'prio' variable.
|
||||
Check for ioctl success rather than absence of specific failure.
|
||||
|
||||
v4:
|
||||
Explicitly mention that change is linux specific.
|
||||
|
||||
Signed-off-by: Cole Robinson <crobinso@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
block/raw-posix.c | 20 ++++++++++++++++++--
|
||||
1 files changed, 18 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/block/raw-posix.c b/block/raw-posix.c
|
||||
index c204cf9..1c777a1 100644
|
||||
--- a/block/raw-posix.c
|
||||
+++ b/block/raw-posix.c
|
||||
@@ -1142,9 +1142,25 @@ static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
|
||||
static int cdrom_probe_device(const char *filename)
|
||||
{
|
||||
+ int fd, ret;
|
||||
+ int prio = 0;
|
||||
+
|
||||
if (strstart(filename, "/dev/cd", NULL))
|
||||
- return 100;
|
||||
- return 0;
|
||||
+ prio = 50;
|
||||
+
|
||||
+ fd = open(filename, O_RDONLY | O_NONBLOCK);
|
||||
+ if (fd < 0) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* Attempt to detect via a CDROM specific ioctl */
|
||||
+ ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
|
||||
+ if (ret >= 0)
|
||||
+ prio = 100;
|
||||
+
|
||||
+ close(fd);
|
||||
+out:
|
||||
+ return prio;
|
||||
}
|
||||
|
||||
static int cdrom_is_inserted(BlockDriverState *bs)
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,33 +0,0 @@
|
||||
From afba60f63354fc6376e30dd51cadeda7170bcf4b Mon Sep 17 00:00:00 2001
|
||||
From: Christian Krause <chkr@plauener.de>
|
||||
Date: Sun, 24 Jan 2010 16:34:52 +0000
|
||||
Subject: [PATCH] usb-linux: increase buffer for USB control requests
|
||||
|
||||
The WLAN USB stick ZyXEL NWD271N (0586:3417) uses very large
|
||||
usb control transfers of more than 2048 bytes which won't fit
|
||||
into the buffer of the ctrl_struct. This results in an error message
|
||||
"husb: ctrl buffer too small" and a non-working device.
|
||||
Increasing the buffer size to 8192 seems to be a safe choice.
|
||||
|
||||
Signed-off-by: Christian Krause <chkr@plauener.de>
|
||||
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
|
||||
---
|
||||
usb-linux.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/usb-linux.c b/usb-linux.c
|
||||
index 5619b30..e6cd432 100644
|
||||
--- a/usb-linux.c
|
||||
+++ b/usb-linux.c
|
||||
@@ -113,7 +113,7 @@ struct ctrl_struct {
|
||||
uint16_t offset;
|
||||
uint8_t state;
|
||||
struct usb_ctrlrequest req;
|
||||
- uint8_t buffer[2048];
|
||||
+ uint8_t buffer[8192];
|
||||
};
|
||||
|
||||
struct USBAutoFilter {
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,936 +0,0 @@
|
||||
From 8fe39316da28bdff610da708148f87b21e7ba045 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Tue, 6 Apr 2010 23:36:50 +0530
|
||||
Subject: [PATCH] virtio-console patches
|
||||
|
||||
Hey Justin,
|
||||
|
||||
Attached are the kernel and qemu patches for the new abi. Rusty is ok
|
||||
with the kernel patches and Juan and Gerd are ok with the userspace
|
||||
ones.
|
||||
|
||||
The kernel one is big because of some code movement.
|
||||
|
||||
The qemu one is big because of code being moved and some fixes being
|
||||
applied to make the host less vulnerable to malicious guests.
|
||||
|
||||
There's also a patch at
|
||||
|
||||
http://lkml.org/lkml/2010/4/6/110
|
||||
|
||||
that we should apply (affects the virt-console-fix-race.patch in the
|
||||
repo).
|
||||
|
||||
Please let me know if you need any more information!
|
||||
|
||||
Thanks,
|
||||
Amit
|
||||
|
||||
Content-Disposition: attachment; filename=",qemu-virtio-serial-rollup-2.patch"
|
||||
---
|
||||
Makefile.hw | 1 +
|
||||
hw/iov.c | 70 ++++++++++
|
||||
hw/iov.h | 19 +++
|
||||
hw/virtio-balloon.c | 31 +----
|
||||
hw/virtio-console.c | 11 +-
|
||||
hw/virtio-net.c | 20 +---
|
||||
hw/virtio-serial-bus.c | 332 ++++++++++++++++++++++++++++++++++++------------
|
||||
hw/virtio-serial.h | 34 ++++--
|
||||
8 files changed, 372 insertions(+), 146 deletions(-)
|
||||
create mode 100644 hw/iov.c
|
||||
create mode 100644 hw/iov.h
|
||||
|
||||
diff --git a/Makefile.hw b/Makefile.hw
|
||||
index 43ca541..079c5d2 100644
|
||||
--- a/Makefile.hw
|
||||
+++ b/Makefile.hw
|
||||
@@ -13,6 +13,7 @@ QEMU_CFLAGS+=-I.. -I$(SRC_PATH)/fpu
|
||||
|
||||
obj-y =
|
||||
obj-y += loader.o
|
||||
+obj-y += iov.o
|
||||
obj-y += virtio.o virtio-console.o
|
||||
obj-y += fw_cfg.o
|
||||
obj-y += watchdog.o
|
||||
diff --git a/hw/iov.c b/hw/iov.c
|
||||
new file mode 100644
|
||||
index 0000000..588cd04
|
||||
--- /dev/null
|
||||
+++ b/hw/iov.c
|
||||
@@ -0,0 +1,70 @@
|
||||
+/*
|
||||
+ * Helpers for getting linearized buffers from iov / filling buffers into iovs
|
||||
+ *
|
||||
+ * Copyright IBM, Corp. 2007, 2008
|
||||
+ * Copyright (C) 2010 Red Hat, Inc.
|
||||
+ *
|
||||
+ * Author(s):
|
||||
+ * Anthony Liguori <aliguori@us.ibm.com>
|
||||
+ * Amit Shah <amit.shah@redhat.com>
|
||||
+ *
|
||||
+ * This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
+ * the COPYING file in the top-level directory.
|
||||
+ */
|
||||
+
|
||||
+#include "iov.h"
|
||||
+
|
||||
+size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
|
||||
+ const void *buf, size_t size)
|
||||
+{
|
||||
+ size_t offset;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ offset = 0;
|
||||
+ for (i = 0; offset < size && i < iovcnt; i++) {
|
||||
+ size_t len;
|
||||
+
|
||||
+ len = MIN(iov[i].iov_len, size - offset);
|
||||
+
|
||||
+ memcpy(iov[i].iov_base, buf + offset, len);
|
||||
+ offset += len;
|
||||
+ }
|
||||
+ return offset;
|
||||
+}
|
||||
+
|
||||
+size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
|
||||
+ void *buf, size_t offset, size_t size)
|
||||
+{
|
||||
+ uint8_t *ptr;
|
||||
+ size_t iov_off, buf_off;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ ptr = buf;
|
||||
+ iov_off = 0;
|
||||
+ buf_off = 0;
|
||||
+ for (i = 0; i < iovcnt && size; i++) {
|
||||
+ if (offset < (iov_off + iov[i].iov_len)) {
|
||||
+ size_t len = MIN((iov_off + iov[i].iov_len) - offset , size);
|
||||
+
|
||||
+ memcpy(ptr + buf_off, iov[i].iov_base + (offset - iov_off), len);
|
||||
+
|
||||
+ buf_off += len;
|
||||
+ offset += len;
|
||||
+ size -= len;
|
||||
+ }
|
||||
+ iov_off += iov[i].iov_len;
|
||||
+ }
|
||||
+ return buf_off;
|
||||
+}
|
||||
+
|
||||
+size_t iov_size(const struct iovec *iov, const unsigned int iovcnt)
|
||||
+{
|
||||
+ size_t len;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ len = 0;
|
||||
+ for (i = 0; i < iovcnt; i++) {
|
||||
+ len += iov[i].iov_len;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
diff --git a/hw/iov.h b/hw/iov.h
|
||||
new file mode 100644
|
||||
index 0000000..60a8547
|
||||
--- /dev/null
|
||||
+++ b/hw/iov.h
|
||||
@@ -0,0 +1,19 @@
|
||||
+/*
|
||||
+ * Helpers for getting linearized buffers from iov / filling buffers into iovs
|
||||
+ *
|
||||
+ * Copyright (C) 2010 Red Hat, Inc.
|
||||
+ *
|
||||
+ * Author(s):
|
||||
+ * Amit Shah <amit.shah@redhat.com>
|
||||
+ *
|
||||
+ * This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
+ * the COPYING file in the top-level directory.
|
||||
+ */
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+
|
||||
+size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
|
||||
+ const void *buf, size_t size);
|
||||
+size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
|
||||
+ void *buf, size_t offset, size_t size);
|
||||
+size_t iov_size(const struct iovec *iov, const unsigned int iovcnt);
|
||||
diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
|
||||
index 242c6c8..10e2647 100644
|
||||
--- a/hw/virtio-balloon.c
|
||||
+++ b/hw/virtio-balloon.c
|
||||
@@ -11,6 +11,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
+#include "iov.h"
|
||||
#include "qemu-common.h"
|
||||
#include "virtio.h"
|
||||
#include "pc.h"
|
||||
@@ -47,33 +48,6 @@ static void balloon_page(void *addr, int deflate)
|
||||
#endif
|
||||
}
|
||||
|
||||
-/* FIXME: once we do a virtio refactoring, this will get subsumed into common
|
||||
- * code */
|
||||
-static size_t memcpy_from_iovector(void *data, size_t offset, size_t size,
|
||||
- struct iovec *iov, int iovlen)
|
||||
-{
|
||||
- int i;
|
||||
- uint8_t *ptr = data;
|
||||
- size_t iov_off = 0;
|
||||
- size_t data_off = 0;
|
||||
-
|
||||
- for (i = 0; i < iovlen && size; i++) {
|
||||
- if (offset < (iov_off + iov[i].iov_len)) {
|
||||
- size_t len = MIN((iov_off + iov[i].iov_len) - offset , size);
|
||||
-
|
||||
- memcpy(ptr + data_off, iov[i].iov_base + (offset - iov_off), len);
|
||||
-
|
||||
- data_off += len;
|
||||
- offset += len;
|
||||
- size -= len;
|
||||
- }
|
||||
-
|
||||
- iov_off += iov[i].iov_len;
|
||||
- }
|
||||
-
|
||||
- return data_off;
|
||||
-}
|
||||
-
|
||||
static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtIOBalloon *s = to_virtio_balloon(vdev);
|
||||
@@ -83,8 +57,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
size_t offset = 0;
|
||||
uint32_t pfn;
|
||||
|
||||
- while (memcpy_from_iovector(&pfn, offset, 4,
|
||||
- elem.out_sg, elem.out_num) == 4) {
|
||||
+ while (iov_to_buf(elem.out_sg, elem.out_num, &pfn, offset, 4) == 4) {
|
||||
ram_addr_t pa;
|
||||
ram_addr_t addr;
|
||||
|
||||
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
|
||||
index bd44ec6..caea11f 100644
|
||||
--- a/hw/virtio-console.c
|
||||
+++ b/hw/virtio-console.c
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Virtio Console and Generic Serial Port Devices
|
||||
*
|
||||
- * Copyright Red Hat, Inc. 2009
|
||||
+ * Copyright Red Hat, Inc. 2009, 2010
|
||||
*
|
||||
* Authors:
|
||||
* Amit Shah <amit.shah@redhat.com>
|
||||
@@ -20,14 +20,11 @@ typedef struct VirtConsole {
|
||||
|
||||
|
||||
/* Callback function that's called when the guest sends us data */
|
||||
-static size_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
|
||||
+static void flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
|
||||
{
|
||||
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||
- ssize_t ret;
|
||||
|
||||
- ret = qemu_chr_write(vcon->chr, buf, len);
|
||||
-
|
||||
- return ret < 0 ? 0 : ret;
|
||||
+ qemu_chr_write(vcon->chr, buf, len);
|
||||
}
|
||||
|
||||
/* Readiness of the guest to accept data on a port */
|
||||
@@ -99,6 +96,7 @@ static VirtIOSerialPortInfo virtconsole_info = {
|
||||
.exit = virtconsole_exitfn,
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_PROP_UINT8("is_console", VirtConsole, port.is_console, 1),
|
||||
+ DEFINE_PROP_UINT32("nr", VirtConsole, port.id, VIRTIO_CONSOLE_BAD_ID),
|
||||
DEFINE_PROP_CHR("chardev", VirtConsole, chr),
|
||||
DEFINE_PROP_STRING("name", VirtConsole, port.name),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
@@ -133,6 +131,7 @@ static VirtIOSerialPortInfo virtserialport_info = {
|
||||
.init = virtserialport_initfn,
|
||||
.exit = virtconsole_exitfn,
|
||||
.qdev.props = (Property[]) {
|
||||
+ DEFINE_PROP_UINT32("nr", VirtConsole, port.id, VIRTIO_CONSOLE_BAD_ID),
|
||||
DEFINE_PROP_CHR("chardev", VirtConsole, chr),
|
||||
DEFINE_PROP_STRING("name", VirtConsole, port.name),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
|
||||
index f8e228f..320e99f 100644
|
||||
--- a/hw/virtio-net.c
|
||||
+++ b/hw/virtio-net.c
|
||||
@@ -11,6 +11,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
+#include "iov.h"
|
||||
#include "virtio.h"
|
||||
#include "net.h"
|
||||
#include "net/checksum.h"
|
||||
@@ -436,21 +437,6 @@ static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
|
||||
}
|
||||
}
|
||||
|
||||
-static int iov_fill(struct iovec *iov, int iovcnt, const void *buf, int count)
|
||||
-{
|
||||
- int offset, i;
|
||||
-
|
||||
- offset = i = 0;
|
||||
- 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++;
|
||||
- }
|
||||
-
|
||||
- return offset;
|
||||
-}
|
||||
-
|
||||
static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt,
|
||||
const void *buf, size_t size, size_t hdr_len)
|
||||
{
|
||||
@@ -586,8 +572,8 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
|
||||
}
|
||||
|
||||
/* copy in packet. ugh */
|
||||
- len = iov_fill(sg, elem.in_num,
|
||||
- buf + offset, size - offset);
|
||||
+ len = iov_from_buf(sg, elem.in_num,
|
||||
+ buf + offset, size - offset);
|
||||
total += len;
|
||||
|
||||
/* signal other side */
|
||||
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
|
||||
index d0e0219..6245f6e 100644
|
||||
--- a/hw/virtio-serial-bus.c
|
||||
+++ b/hw/virtio-serial-bus.c
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A bus for connecting virtio serial and console ports
|
||||
*
|
||||
- * Copyright (C) 2009 Red Hat, Inc.
|
||||
+ * Copyright (C) 2009, 2010 Red Hat, Inc.
|
||||
*
|
||||
* Author(s):
|
||||
* Amit Shah <amit.shah@redhat.com>
|
||||
@@ -15,6 +15,7 @@
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
+#include "iov.h"
|
||||
#include "monitor.h"
|
||||
#include "qemu-queue.h"
|
||||
#include "sysbus.h"
|
||||
@@ -41,6 +42,10 @@ struct VirtIOSerial {
|
||||
VirtIOSerialBus *bus;
|
||||
|
||||
QTAILQ_HEAD(, VirtIOSerialPort) ports;
|
||||
+
|
||||
+ /* bitmap for identifying active ports */
|
||||
+ uint32_t *ports_map;
|
||||
+
|
||||
struct virtio_console_config config;
|
||||
};
|
||||
|
||||
@@ -48,6 +53,10 @@ static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id)
|
||||
{
|
||||
VirtIOSerialPort *port;
|
||||
|
||||
+ if (id == VIRTIO_CONSOLE_BAD_ID) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
QTAILQ_FOREACH(port, &vser->ports, next) {
|
||||
if (port->id == id)
|
||||
return port;
|
||||
@@ -76,30 +85,25 @@ static size_t write_to_port(VirtIOSerialPort *port,
|
||||
{
|
||||
VirtQueueElement elem;
|
||||
VirtQueue *vq;
|
||||
- size_t offset = 0;
|
||||
- size_t len = 0;
|
||||
+ size_t offset;
|
||||
|
||||
vq = port->ivq;
|
||||
if (!virtio_queue_ready(vq)) {
|
||||
return 0;
|
||||
}
|
||||
- if (!size) {
|
||||
- return 0;
|
||||
- }
|
||||
|
||||
+ offset = 0;
|
||||
while (offset < size) {
|
||||
- int i;
|
||||
+ size_t len;
|
||||
|
||||
if (!virtqueue_pop(vq, &elem)) {
|
||||
break;
|
||||
}
|
||||
|
||||
- for (i = 0; offset < size && i < elem.in_num; i++) {
|
||||
- len = MIN(elem.in_sg[i].iov_len, size - offset);
|
||||
+ len = iov_from_buf(elem.in_sg, elem.in_num,
|
||||
+ buf + offset, size - offset);
|
||||
+ offset += len;
|
||||
|
||||
- memcpy(elem.in_sg[i].iov_base, buf + offset, len);
|
||||
- offset += len;
|
||||
- }
|
||||
virtqueue_push(vq, &elem, len);
|
||||
}
|
||||
|
||||
@@ -107,6 +111,29 @@ static size_t write_to_port(VirtIOSerialPort *port,
|
||||
return offset;
|
||||
}
|
||||
|
||||
+static void flush_queued_data(VirtIOSerialPort *port, bool discard)
|
||||
+{
|
||||
+ VirtQueue *vq;
|
||||
+ VirtQueueElement elem;
|
||||
+
|
||||
+ vq = port->ovq;
|
||||
+ while (virtqueue_pop(vq, &elem)) {
|
||||
+ uint8_t *buf;
|
||||
+ size_t ret, buf_size;
|
||||
+
|
||||
+ if (!discard) {
|
||||
+ buf_size = iov_size(elem.out_sg, elem.out_num);
|
||||
+ buf = qemu_malloc(buf_size);
|
||||
+ ret = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, buf_size);
|
||||
+
|
||||
+ port->info->have_data(port, buf, ret);
|
||||
+ qemu_free(buf);
|
||||
+ }
|
||||
+ virtqueue_push(vq, &elem, 0);
|
||||
+ }
|
||||
+ virtio_notify(&port->vser->vdev, vq);
|
||||
+}
|
||||
+
|
||||
static size_t send_control_msg(VirtIOSerialPort *port, void *buf, size_t len)
|
||||
{
|
||||
VirtQueueElement elem;
|
||||
@@ -158,6 +185,13 @@ int virtio_serial_open(VirtIOSerialPort *port)
|
||||
int virtio_serial_close(VirtIOSerialPort *port)
|
||||
{
|
||||
port->host_connected = false;
|
||||
+ /*
|
||||
+ * If there's any data the guest sent which the app didn't
|
||||
+ * consume, discard it and reset the throttling flag.
|
||||
+ */
|
||||
+ flush_queued_data(port, true);
|
||||
+ port->throttled = false;
|
||||
+
|
||||
send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
|
||||
|
||||
return 0;
|
||||
@@ -199,8 +233,23 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
|
||||
+{
|
||||
+ if (!port) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (throttle) {
|
||||
+ port->throttled = true;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ port->throttled = false;
|
||||
+ flush_queued_data(port, false);
|
||||
+}
|
||||
+
|
||||
/* Guest wants to notify us of some event */
|
||||
-static void handle_control_message(VirtIOSerial *vser, void *buf)
|
||||
+static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
|
||||
{
|
||||
struct VirtIOSerialPort *port;
|
||||
struct virtio_console_control cpkt, *gcpkt;
|
||||
@@ -208,15 +257,41 @@ static void handle_control_message(VirtIOSerial *vser, void *buf)
|
||||
size_t buffer_len;
|
||||
|
||||
gcpkt = buf;
|
||||
- port = find_port_by_id(vser, ldl_p(&gcpkt->id));
|
||||
- if (!port)
|
||||
+
|
||||
+ if (len < sizeof(cpkt)) {
|
||||
+ /* The guest sent an invalid control packet */
|
||||
return;
|
||||
+ }
|
||||
|
||||
cpkt.event = lduw_p(&gcpkt->event);
|
||||
cpkt.value = lduw_p(&gcpkt->value);
|
||||
|
||||
+ port = find_port_by_id(vser, ldl_p(&gcpkt->id));
|
||||
+ if (!port && cpkt.event != VIRTIO_CONSOLE_DEVICE_READY)
|
||||
+ return;
|
||||
+
|
||||
switch(cpkt.event) {
|
||||
+ case VIRTIO_CONSOLE_DEVICE_READY:
|
||||
+ if (!cpkt.value) {
|
||||
+ qemu_error("virtio-serial-bus: Guest failure in adding device %s\n",
|
||||
+ vser->bus->qbus.name);
|
||||
+ break;
|
||||
+ }
|
||||
+ /*
|
||||
+ * The device is up, we can now tell the device about all the
|
||||
+ * ports we have here.
|
||||
+ */
|
||||
+ QTAILQ_FOREACH(port, &vser->ports, next) {
|
||||
+ send_control_event(port, VIRTIO_CONSOLE_PORT_ADD, 1);
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
case VIRTIO_CONSOLE_PORT_READY:
|
||||
+ if (!cpkt.value) {
|
||||
+ qemu_error("virtio-serial-bus: Guest failure in adding port %u for device %s\n",
|
||||
+ port->id, vser->bus->qbus.name);
|
||||
+ break;
|
||||
+ }
|
||||
/*
|
||||
* Now that we know the guest asked for the port name, we're
|
||||
* sure the guest has initialised whatever state is necessary
|
||||
@@ -281,12 +356,35 @@ static void control_out(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtQueueElement elem;
|
||||
VirtIOSerial *vser;
|
||||
+ uint8_t *buf;
|
||||
+ size_t len;
|
||||
|
||||
vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
|
||||
|
||||
+ len = 0;
|
||||
+ buf = NULL;
|
||||
while (virtqueue_pop(vq, &elem)) {
|
||||
- handle_control_message(vser, elem.out_sg[0].iov_base);
|
||||
- virtqueue_push(vq, &elem, elem.out_sg[0].iov_len);
|
||||
+ size_t cur_len, copied;
|
||||
+
|
||||
+ cur_len = iov_size(elem.out_sg, elem.out_num);
|
||||
+ /*
|
||||
+ * Allocate a new buf only if we didn't have one previously or
|
||||
+ * if the size of the buf differs
|
||||
+ */
|
||||
+ if (cur_len > len) {
|
||||
+ if (len) {
|
||||
+ qemu_free(buf);
|
||||
+ }
|
||||
+ buf = qemu_malloc(cur_len);
|
||||
+ len = cur_len;
|
||||
+ }
|
||||
+ copied = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, len);
|
||||
+
|
||||
+ handle_control_message(vser, buf, copied);
|
||||
+ virtqueue_push(vq, &elem, 0);
|
||||
+ }
|
||||
+ if (len) {
|
||||
+ qemu_free(buf);
|
||||
}
|
||||
virtio_notify(vdev, vq);
|
||||
}
|
||||
@@ -295,38 +393,22 @@ static void control_out(VirtIODevice *vdev, VirtQueue *vq)
|
||||
static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtIOSerial *vser;
|
||||
- VirtQueueElement elem;
|
||||
+ VirtIOSerialPort *port;
|
||||
+ bool discard;
|
||||
|
||||
vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
|
||||
+ port = find_port_by_vq(vser, vq);
|
||||
|
||||
- while (virtqueue_pop(vq, &elem)) {
|
||||
- VirtIOSerialPort *port;
|
||||
- size_t ret;
|
||||
-
|
||||
- port = find_port_by_vq(vser, vq);
|
||||
- if (!port) {
|
||||
- ret = 0;
|
||||
- goto next_buf;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * A port may not have any handler registered for consuming the
|
||||
- * data that the guest sends or it may not have a chardev associated
|
||||
- * with it. Just ignore the data in that case.
|
||||
- */
|
||||
- if (!port->info->have_data) {
|
||||
- ret = 0;
|
||||
- goto next_buf;
|
||||
- }
|
||||
-
|
||||
- /* The guest always sends only one sg */
|
||||
- ret = port->info->have_data(port, elem.out_sg[0].iov_base,
|
||||
- elem.out_sg[0].iov_len);
|
||||
+ discard = false;
|
||||
+ if (!port || !port->host_connected || !port->info->have_data) {
|
||||
+ discard = true;
|
||||
+ }
|
||||
|
||||
- next_buf:
|
||||
- virtqueue_push(vq, &elem, ret);
|
||||
+ if (!discard && port->throttled) {
|
||||
+ return;
|
||||
}
|
||||
- virtio_notify(vdev, vq);
|
||||
+
|
||||
+ flush_queued_data(port, discard);
|
||||
}
|
||||
|
||||
static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
|
||||
@@ -335,7 +417,10 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
|
||||
|
||||
static uint32_t get_features(VirtIODevice *vdev, uint32_t features)
|
||||
{
|
||||
- VirtIOSerial *vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
|
||||
+ VirtIOSerial *vser;
|
||||
+
|
||||
+ vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
|
||||
+
|
||||
if (vser->bus->max_nr_ports > 1) {
|
||||
features |= (1 << VIRTIO_CONSOLE_F_MULTIPORT);
|
||||
}
|
||||
@@ -370,14 +455,20 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
|
||||
/* The config space */
|
||||
qemu_put_be16s(f, &s->config.cols);
|
||||
qemu_put_be16s(f, &s->config.rows);
|
||||
- qemu_put_be32s(f, &s->config.nr_ports);
|
||||
|
||||
- /* Items in struct VirtIOSerial */
|
||||
+ qemu_put_be32s(f, &s->config.max_nr_ports);
|
||||
+
|
||||
+ /* The ports map */
|
||||
+
|
||||
+ qemu_put_buffer(f, (uint8_t *)s->ports_map,
|
||||
+ sizeof(uint32_t) * (s->config.max_nr_ports + 31) / 32);
|
||||
+
|
||||
+ /* Ports */
|
||||
|
||||
- /* Do this because we might have hot-unplugged some ports */
|
||||
nr_active_ports = 0;
|
||||
- QTAILQ_FOREACH(port, &s->ports, next)
|
||||
+ QTAILQ_FOREACH(port, &s->ports, next) {
|
||||
nr_active_ports++;
|
||||
+ }
|
||||
|
||||
qemu_put_be32s(f, &nr_active_ports);
|
||||
|
||||
@@ -385,13 +476,9 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
|
||||
* Items in struct VirtIOSerialPort.
|
||||
*/
|
||||
QTAILQ_FOREACH(port, &s->ports, next) {
|
||||
- /*
|
||||
- * We put the port number because we may not have an active
|
||||
- * port at id 0 that's reserved for a console port, or in case
|
||||
- * of ports that might have gotten unplugged
|
||||
- */
|
||||
qemu_put_be32s(f, &port->id);
|
||||
qemu_put_byte(f, port->guest_connected);
|
||||
+ qemu_put_byte(f, port->host_connected);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,7 +486,8 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
VirtIOSerial *s = opaque;
|
||||
VirtIOSerialPort *port;
|
||||
- uint32_t nr_active_ports;
|
||||
+ size_t ports_map_size;
|
||||
+ uint32_t max_nr_ports, nr_active_ports, *ports_map;
|
||||
unsigned int i;
|
||||
|
||||
if (version_id > 2) {
|
||||
@@ -416,22 +504,50 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
|
||||
/* The config space */
|
||||
qemu_get_be16s(f, &s->config.cols);
|
||||
qemu_get_be16s(f, &s->config.rows);
|
||||
- s->config.nr_ports = qemu_get_be32(f);
|
||||
|
||||
- /* Items in struct VirtIOSerial */
|
||||
+ qemu_get_be32s(f, &max_nr_ports);
|
||||
+ if (max_nr_ports > s->config.max_nr_ports) {
|
||||
+ /* Source could have had more ports than us. Fail migration. */
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ ports_map_size = sizeof(uint32_t) * (max_nr_ports + 31) / 32;
|
||||
+ ports_map = qemu_malloc(ports_map_size);
|
||||
+ qemu_get_buffer(f, (uint8_t *)ports_map, ports_map_size);
|
||||
+
|
||||
+ for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
|
||||
+ if (ports_map[i] != s->ports_map[i]) {
|
||||
+ /*
|
||||
+ * Ports active on source and destination don't
|
||||
+ * match. Fail migration.
|
||||
+ */
|
||||
+ qemu_free(ports_map);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ }
|
||||
+ qemu_free(ports_map);
|
||||
|
||||
qemu_get_be32s(f, &nr_active_ports);
|
||||
|
||||
/* Items in struct VirtIOSerialPort */
|
||||
for (i = 0; i < nr_active_ports; i++) {
|
||||
uint32_t id;
|
||||
+ bool host_connected;
|
||||
|
||||
id = qemu_get_be32(f);
|
||||
port = find_port_by_id(s, id);
|
||||
|
||||
port->guest_connected = qemu_get_byte(f);
|
||||
+ host_connected = qemu_get_byte(f);
|
||||
+ if (host_connected != port->host_connected) {
|
||||
+ /*
|
||||
+ * We have to let the guest know of the host connection
|
||||
+ * status change
|
||||
+ */
|
||||
+ send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN,
|
||||
+ port->host_connected);
|
||||
+ }
|
||||
}
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -466,6 +582,54 @@ static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
|
||||
indent, "", port->host_connected);
|
||||
}
|
||||
|
||||
+/* This function is only used if a port id is not provided by the user */
|
||||
+static uint32_t find_free_port_id(VirtIOSerial *vser)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < (vser->config.max_nr_ports + 31) / 32; i++) {
|
||||
+ uint32_t map, bit;
|
||||
+
|
||||
+ map = vser->ports_map[i];
|
||||
+ bit = ffs(~map);
|
||||
+ if (bit) {
|
||||
+ return (bit - 1) + i * 32;
|
||||
+ }
|
||||
+ }
|
||||
+ return VIRTIO_CONSOLE_BAD_ID;
|
||||
+}
|
||||
+
|
||||
+static void mark_port_added(VirtIOSerial *vser, uint32_t port_id)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ i = port_id / 32;
|
||||
+ vser->ports_map[i] |= 1U << (port_id % 32);
|
||||
+}
|
||||
+
|
||||
+static void add_port(VirtIOSerial *vser, uint32_t port_id)
|
||||
+{
|
||||
+ mark_port_added(vser, port_id);
|
||||
+
|
||||
+ send_control_event(find_port_by_id(vser, port_id),
|
||||
+ VIRTIO_CONSOLE_PORT_ADD, 1);
|
||||
+}
|
||||
+
|
||||
+static void remove_port(VirtIOSerial *vser, uint32_t port_id)
|
||||
+{
|
||||
+ VirtIOSerialPort *port;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ i = port_id / 32;
|
||||
+ vser->ports_map[i] &= ~(1U << (port_id % 32));
|
||||
+
|
||||
+ port = find_port_by_id(vser, port_id);
|
||||
+ /* Flush out any unconsumed buffers first */
|
||||
+ flush_queued_data(port, true);
|
||||
+
|
||||
+ send_control_event(port, VIRTIO_CONSOLE_PORT_REMOVE, 1);
|
||||
+}
|
||||
+
|
||||
static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
|
||||
{
|
||||
VirtIOSerialDevice *dev = DO_UPCAST(VirtIOSerialDevice, qdev, qdev);
|
||||
@@ -484,19 +648,36 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
|
||||
*/
|
||||
plugging_port0 = port->is_console && !find_port_by_id(port->vser, 0);
|
||||
|
||||
- if (port->vser->config.nr_ports == bus->max_nr_ports && !plugging_port0) {
|
||||
- qemu_error("virtio-serial-bus: Maximum device limit reached\n");
|
||||
+ if (find_port_by_id(port->vser, port->id)) {
|
||||
+ qemu_error("virtio-serial-bus: A port already exists at id %u\n",
|
||||
+ port->id);
|
||||
return -1;
|
||||
}
|
||||
- dev->info = info;
|
||||
|
||||
+ if (port->id == VIRTIO_CONSOLE_BAD_ID) {
|
||||
+ if (plugging_port0) {
|
||||
+ port->id = 0;
|
||||
+ } else {
|
||||
+ port->id = find_free_port_id(port->vser);
|
||||
+ if (port->id == VIRTIO_CONSOLE_BAD_ID) {
|
||||
+ qemu_error("virtio-serial-bus: Maximum port limit for this device reached\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (port->id >= port->vser->config.max_nr_ports) {
|
||||
+ qemu_error("virtio-serial-bus: Out-of-range port id specified, max. allowed: %u\n",
|
||||
+ port->vser->config.max_nr_ports - 1);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ dev->info = info;
|
||||
ret = info->init(dev);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
- port->id = plugging_port0 ? 0 : port->vser->config.nr_ports++;
|
||||
-
|
||||
if (!use_multiport(port->vser)) {
|
||||
/*
|
||||
* Allow writes to guest in this case; we have no way of
|
||||
@@ -509,6 +690,8 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
|
||||
port->ivq = port->vser->ivqs[port->id];
|
||||
port->ovq = port->vser->ovqs[port->id];
|
||||
|
||||
+ add_port(port->vser, port->id);
|
||||
+
|
||||
/* Send an update to the guest about this new port added */
|
||||
virtio_notify_config(&port->vser->vdev);
|
||||
|
||||
@@ -521,26 +704,8 @@ static int virtser_port_qdev_exit(DeviceState *qdev)
|
||||
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
VirtIOSerial *vser = port->vser;
|
||||
|
||||
- send_control_event(port, VIRTIO_CONSOLE_PORT_REMOVE, 1);
|
||||
+ remove_port(port->vser, port->id);
|
||||
|
||||
- /*
|
||||
- * Don't decrement nr_ports here; thus we keep a linearly
|
||||
- * increasing port id. Not utilising an id again saves us a couple
|
||||
- * of complications:
|
||||
- *
|
||||
- * - Not having to bother about sending the port id to the guest
|
||||
- * kernel on hotplug or on addition of new ports; the guest can
|
||||
- * also linearly increment the port number. This is preferable
|
||||
- * because the config space won't have the need to store a
|
||||
- * ports_map.
|
||||
- *
|
||||
- * - Extra state to be stored for all the "holes" that got created
|
||||
- * so that we keep filling in the ids from the least available
|
||||
- * index.
|
||||
- *
|
||||
- * When such a functionality is desired, a control message to add
|
||||
- * a port can be introduced.
|
||||
- */
|
||||
QTAILQ_REMOVE(&vser->ports, port, next);
|
||||
|
||||
if (port->info->exit)
|
||||
@@ -600,11 +765,12 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
|
||||
}
|
||||
|
||||
vser->config.max_nr_ports = max_nr_ports;
|
||||
+ vser->ports_map = qemu_mallocz((max_nr_ports + 31) / 32);
|
||||
/*
|
||||
* Reserve location 0 for a console port for backward compat
|
||||
* (old kernel, new qemu)
|
||||
*/
|
||||
- vser->config.nr_ports = 1;
|
||||
+ mark_port_added(vser, 0);
|
||||
|
||||
vser->vdev.get_features = get_features;
|
||||
vser->vdev.get_config = get_config;
|
||||
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
|
||||
index f297b00..a93b545 100644
|
||||
--- a/hw/virtio-serial.h
|
||||
+++ b/hw/virtio-serial.h
|
||||
@@ -2,7 +2,7 @@
|
||||
* Virtio Serial / Console Support
|
||||
*
|
||||
* Copyright IBM, Corp. 2008
|
||||
- * Copyright Red Hat, Inc. 2009
|
||||
+ * Copyright Red Hat, Inc. 2009, 2010
|
||||
*
|
||||
* Authors:
|
||||
* Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
|
||||
@@ -27,6 +27,8 @@
|
||||
/* Features supported */
|
||||
#define VIRTIO_CONSOLE_F_MULTIPORT 1
|
||||
|
||||
+#define VIRTIO_CONSOLE_BAD_ID (~(uint32_t)0)
|
||||
+
|
||||
struct virtio_console_config {
|
||||
/*
|
||||
* These two fields are used by VIRTIO_CONSOLE_F_SIZE which
|
||||
@@ -36,7 +38,6 @@ struct virtio_console_config {
|
||||
uint16_t rows;
|
||||
|
||||
uint32_t max_nr_ports;
|
||||
- uint32_t nr_ports;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct virtio_console_control {
|
||||
@@ -46,12 +47,14 @@ struct virtio_console_control {
|
||||
};
|
||||
|
||||
/* Some events for the internal messages (control packets) */
|
||||
-#define VIRTIO_CONSOLE_PORT_READY 0
|
||||
-#define VIRTIO_CONSOLE_CONSOLE_PORT 1
|
||||
-#define VIRTIO_CONSOLE_RESIZE 2
|
||||
-#define VIRTIO_CONSOLE_PORT_OPEN 3
|
||||
-#define VIRTIO_CONSOLE_PORT_NAME 4
|
||||
-#define VIRTIO_CONSOLE_PORT_REMOVE 5
|
||||
+#define VIRTIO_CONSOLE_DEVICE_READY 0
|
||||
+#define VIRTIO_CONSOLE_PORT_ADD 1
|
||||
+#define VIRTIO_CONSOLE_PORT_REMOVE 2
|
||||
+#define VIRTIO_CONSOLE_PORT_READY 3
|
||||
+#define VIRTIO_CONSOLE_CONSOLE_PORT 4
|
||||
+#define VIRTIO_CONSOLE_RESIZE 5
|
||||
+#define VIRTIO_CONSOLE_PORT_OPEN 6
|
||||
+#define VIRTIO_CONSOLE_PORT_NAME 7
|
||||
|
||||
/* == In-qemu interface == */
|
||||
|
||||
@@ -107,6 +110,8 @@ struct VirtIOSerialPort {
|
||||
bool guest_connected;
|
||||
/* Is this device open for IO on the host? */
|
||||
bool host_connected;
|
||||
+ /* Do apps not want to receive data? */
|
||||
+ bool throttled;
|
||||
};
|
||||
|
||||
struct VirtIOSerialPortInfo {
|
||||
@@ -133,10 +138,10 @@ struct VirtIOSerialPortInfo {
|
||||
|
||||
/*
|
||||
* Guest wrote some data to the port. This data is handed over to
|
||||
- * the app via this callback. The app should return the number of
|
||||
- * bytes it successfully consumed.
|
||||
+ * the app via this callback. The app is supposed to consume all
|
||||
+ * the data that is presented to it.
|
||||
*/
|
||||
- size_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf, size_t len);
|
||||
+ void (*have_data)(VirtIOSerialPort *port, const uint8_t *buf, size_t len);
|
||||
};
|
||||
|
||||
/* Interface to the virtio-serial bus */
|
||||
@@ -170,4 +175,11 @@ ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf,
|
||||
*/
|
||||
size_t virtio_serial_guest_ready(VirtIOSerialPort *port);
|
||||
|
||||
+/*
|
||||
+ * Flow control: Ports can signal to the virtio-serial core to stop
|
||||
+ * sending data or re-start sending data, depending on the 'throttle'
|
||||
+ * value here.
|
||||
+ */
|
||||
+void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle);
|
||||
+
|
||||
#endif
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,43 +0,0 @@
|
||||
From 30397a024f57f14800975bbb4312be54cc75202b Mon Sep 17 00:00:00 2001
|
||||
From: Eduardo Habkost <ehabkost@redhat.com>
|
||||
Date: Tue, 6 Apr 2010 19:38:51 -0300
|
||||
Subject: [PATCH] net: remove NICInfo.bootable field
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=561078
|
||||
|
||||
It is just set by net_set_boot_mask() and never used. The logic for rom loading
|
||||
changed a lot since this field was introduced. It is not needed anymore.
|
||||
|
||||
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
|
||||
---
|
||||
net.c | 1 -
|
||||
net.h | 1 -
|
||||
2 files changed, 0 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/net.c b/net.c
|
||||
index de7d626..5cebb1a 100644
|
||||
--- a/net.c
|
||||
+++ b/net.c
|
||||
@@ -1204,7 +1204,6 @@ void net_set_boot_mask(int net_boot_mask)
|
||||
|
||||
for (i = 0; i < nb_nics; i++) {
|
||||
if (net_boot_mask & (1 << i)) {
|
||||
- nd_table[i].bootable = 1;
|
||||
net_boot_mask &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
diff --git a/net.h b/net.h
|
||||
index 33a1eaf..5b6e814 100644
|
||||
--- a/net.h
|
||||
+++ b/net.h
|
||||
@@ -135,7 +135,6 @@ struct NICInfo {
|
||||
VLANState *vlan;
|
||||
VLANClientState *netdev;
|
||||
int used;
|
||||
- int bootable;
|
||||
int nvectors;
|
||||
};
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,100 +0,0 @@
|
||||
From 905a4bcaf9d4ed3662b901a2820b6e6ca80dc285 Mon Sep 17 00:00:00 2001
|
||||
From: Eduardo Habkost <ehabkost@redhat.com>
|
||||
Date: Tue, 6 Apr 2010 19:38:52 -0300
|
||||
Subject: [PATCH] net: remove broken net_set_boot_mask() boot device validation
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=561078
|
||||
|
||||
There are many problems with net_set_boot_mask():
|
||||
|
||||
1) It is broken when using the device model instead of "-net nic". Example:
|
||||
$ qemu-system-x86_64 -device rtl8139,vlan=0,id=net0,mac=52:54:00:82:41:fd,bus=pci.0,addr=0x4 -net user,vlan=0,name=hostnet0 -vnc 0.0.0.0:0 -boot n
|
||||
Cannot boot from non-existent NIC
|
||||
$
|
||||
2) The mask was previously used to set which boot ROMs were supposed to be
|
||||
loaded, but this was changed long time ago. Now all ROM images are loaded,
|
||||
and SeaBIOS takes care of jumping to the right boot entry point depending on
|
||||
the boot settings.
|
||||
3) Interpretation and validation of the boot parameter letters is done on
|
||||
the machine type code. Examples: PC accepts only a,b,c,d,n as valid boot
|
||||
device letters. mac99 accepts only a,b,c,d,e,f.
|
||||
|
||||
As a side-effect of this change, qemu-kvm won't abort anymore if using "-boot n"
|
||||
on a machine with no network devices. Checking if the requested boot device is
|
||||
valid is now a task for the BIOS or the machine-type code.
|
||||
|
||||
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
|
||||
---
|
||||
net.c | 19 -------------------
|
||||
net.h | 1 -
|
||||
vl.c | 5 +----
|
||||
3 files changed, 1 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/net.c b/net.c
|
||||
index 5cebb1a..71c0f08 100644
|
||||
--- a/net.c
|
||||
+++ b/net.c
|
||||
@@ -1195,25 +1195,6 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
|
||||
qemu_del_vlan_client(vc);
|
||||
}
|
||||
|
||||
-void net_set_boot_mask(int net_boot_mask)
|
||||
-{
|
||||
- int i;
|
||||
-
|
||||
- /* Only the first four NICs may be bootable */
|
||||
- net_boot_mask = net_boot_mask & 0xF;
|
||||
-
|
||||
- for (i = 0; i < nb_nics; i++) {
|
||||
- if (net_boot_mask & (1 << i)) {
|
||||
- net_boot_mask &= ~(1 << i);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (net_boot_mask) {
|
||||
- fprintf(stderr, "Cannot boot from non-existent NIC\n");
|
||||
- exit(1);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
void do_info_network(Monitor *mon)
|
||||
{
|
||||
VLANState *vlan;
|
||||
diff --git a/net.h b/net.h
|
||||
index 5b6e814..2b2ee4c 100644
|
||||
--- a/net.h
|
||||
+++ b/net.h
|
||||
@@ -165,7 +165,6 @@ int net_client_parse(QemuOptsList *opts_list, const char *str);
|
||||
int net_init_clients(void);
|
||||
void net_check_clients(void);
|
||||
void net_cleanup(void);
|
||||
-void net_set_boot_mask(int boot_mask);
|
||||
void net_host_device_add(Monitor *mon, const QDict *qdict);
|
||||
void net_host_device_remove(Monitor *mon, const QDict *qdict);
|
||||
|
||||
diff --git a/vl.c b/vl.c
|
||||
index c75f891..349f945 100644
|
||||
--- a/vl.c
|
||||
+++ b/vl.c
|
||||
@@ -4922,7 +4922,7 @@ int main(int argc, char **argv, char **envp)
|
||||
const char *gdbstub_dev = NULL;
|
||||
uint32_t boot_devices_bitmap = 0;
|
||||
int i;
|
||||
- int snapshot, linux_boot, net_boot;
|
||||
+ int snapshot, linux_boot;
|
||||
const char *initrd_filename;
|
||||
const char *kernel_filename, *kernel_cmdline;
|
||||
char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */
|
||||
@@ -5961,9 +5961,6 @@ int main(int argc, char **argv, char **envp)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
- net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF;
|
||||
- net_set_boot_mask(net_boot);
|
||||
-
|
||||
/* init the bluetooth world */
|
||||
if (foreach_device_config(DEV_BT, bt_parse))
|
||||
exit(1);
|
||||
--
|
||||
1.6.6.1
|
||||
|
@ -1,63 +0,0 @@
|
||||
From dfbaa3059414b158ff7ce7a74ffff80b0fa2db9c Mon Sep 17 00:00:00 2001
|
||||
From: Eduardo Habkost <ehabkost@redhat.com>
|
||||
Date: Tue, 6 Apr 2010 19:38:53 -0300
|
||||
Subject: [PATCH] boot: remove unused boot_devices_bitmap variable
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=561078
|
||||
|
||||
In addition to removing the variable, this also renames the parse_bootdevices()
|
||||
function to validate_bootdevices(), as we don't need its return value anymore.
|
||||
|
||||
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
|
||||
---
|
||||
vl.c | 8 +++-----
|
||||
1 files changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/vl.c b/vl.c
|
||||
index 349f945..a71127c 100644
|
||||
--- a/vl.c
|
||||
+++ b/vl.c
|
||||
@@ -2517,7 +2517,7 @@ int qemu_boot_set(const char *boot_devices)
|
||||
return boot_set_handler(boot_set_opaque, boot_devices);
|
||||
}
|
||||
|
||||
-static int parse_bootdevices(char *devices)
|
||||
+static void validate_bootdevices(char *devices)
|
||||
{
|
||||
/* We just do some generic consistency checks */
|
||||
const char *p;
|
||||
@@ -2543,7 +2543,6 @@ static int parse_bootdevices(char *devices)
|
||||
}
|
||||
bitmap |= 1 << (*p - 'a');
|
||||
}
|
||||
- return bitmap;
|
||||
}
|
||||
|
||||
static void restore_boot_devices(void *opaque)
|
||||
@@ -4920,7 +4919,6 @@ static int virtcon_parse(const char *devname)
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
const char *gdbstub_dev = NULL;
|
||||
- uint32_t boot_devices_bitmap = 0;
|
||||
int i;
|
||||
int snapshot, linux_boot;
|
||||
const char *initrd_filename;
|
||||
@@ -5215,13 +5213,13 @@ int main(int argc, char **argv, char **envp)
|
||||
|
||||
if (legacy ||
|
||||
get_param_value(buf, sizeof(buf), "order", optarg)) {
|
||||
- boot_devices_bitmap = parse_bootdevices(buf);
|
||||
+ validate_bootdevices(buf);
|
||||
pstrcpy(boot_devices, sizeof(boot_devices), buf);
|
||||
}
|
||||
if (!legacy) {
|
||||
if (get_param_value(buf, sizeof(buf),
|
||||
"once", optarg)) {
|
||||
- boot_devices_bitmap |= parse_bootdevices(buf);
|
||||
+ validate_bootdevices(buf);
|
||||
standard_boot_devices = qemu_strdup(boot_devices);
|
||||
pstrcpy(boot_devices, sizeof(boot_devices), buf);
|
||||
qemu_register_reset(restore_boot_devices,
|
||||
--
|
||||
1.6.6.1
|
||||
|
6
ksm.init
6
ksm.init
@ -40,8 +40,10 @@ default_max_kernel_pages () {
|
||||
|
||||
start() {
|
||||
echo -n $"Starting $prog: "
|
||||
KSM_MAX_KERNEL_PAGES=${KSM_MAX_KERNEL_PAGES:-`default_max_kernel_pages`}
|
||||
echo $KSM_MAX_KERNEL_PAGES > /sys/kernel/mm/ksm/max_kernel_pages
|
||||
if [ -f /sys/kernel/mm/ksm/max_kernel_pages ]; then
|
||||
KSM_MAX_KERNEL_PAGES=${KSM_MAX_KERNEL_PAGES:-`default_max_kernel_pages`}
|
||||
echo $KSM_MAX_KERNEL_PAGES > /sys/kernel/mm/ksm/max_kernel_pages
|
||||
fi
|
||||
echo 1 > /sys/kernel/mm/ksm/run
|
||||
RETVAL=$?
|
||||
[ $RETVAL = 0 ] && success $"$prog startup" || failure $"$prog startup"
|
||||
|
6
ksmtuned
6
ksmtuned
@ -71,12 +71,12 @@ KSMCTL () {
|
||||
committed_memory () {
|
||||
# calculate how much memory is committed to running qemu processes
|
||||
local progname
|
||||
progname=${1:-qemu}
|
||||
ps -o vsz `pgrep $progname` | awk '{ sum += $1 }; END { print sum }'
|
||||
progname=${1:-qemu-kvm}
|
||||
ps -C "$progname" -o rsz | awk '{ sum += $1 }; END { print sum }'
|
||||
}
|
||||
|
||||
free_memory () {
|
||||
awk '/^(MemFree|Buffers|MemCached):/ {free += $2}; END {print free}' \
|
||||
awk '/^(MemFree|Buffers|Cached):/ {free += $2}; END {print free}' \
|
||||
/proc/meminfo
|
||||
}
|
||||
|
||||
|
@ -77,8 +77,14 @@ case "$1" in
|
||||
condrestart
|
||||
;;
|
||||
retune)
|
||||
kill -SIGUSR1 `cat ${pidfile}`
|
||||
pid=`cat ${pidfile} 2> /dev/null`
|
||||
RETVAL=$?
|
||||
if [ -z "$pid" ]; then
|
||||
echo $"Cannot retune, service is not running."
|
||||
else
|
||||
kill -SIGUSR1 $pid
|
||||
RETVAL=$?
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $prog {start|stop|restart|force-reload|condrestart|try-restart|status|retune|help}"
|
||||
|
37
pc-add-a-Fedora-13-machine-type-for-backward-compat.patch
Normal file
37
pc-add-a-Fedora-13-machine-type-for-backward-compat.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From: Justin M. Forbes <jforbes@redhat.com>
|
||||
Date: Thu, Aug 19 09:13:45 2010 -0500
|
||||
Subject: pc: Add a Fedora-13 machine type for backwards compatibility.
|
||||
|
||||
In Fedora 13 a fedora-13 machine type was added as default to allow
|
||||
interaction with upstream stable qemu which did not support the same
|
||||
feature set. As a result we need to support this machine type through
|
||||
the Fedora 15 release.
|
||||
|
||||
|
||||
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
|
||||
index 9e4bac8..eb1ed05 100644
|
||||
--- a/hw/pc_piix.c
|
||||
+++ b/hw/pc_piix.c
|
||||
@@ -237,6 +237,14 @@ static QEMUMachine pc_machine = {
|
||||
.is_default = 1,
|
||||
};
|
||||
|
||||
+static QEMUMachine pc_machine_f13 = {
|
||||
+ .name = "fedora-13",
|
||||
+ .desc = "Standard PC",
|
||||
+ .init = pc_init_pci,
|
||||
+ .max_cpus = 255,
|
||||
+ .is_default = 0,
|
||||
+};
|
||||
+
|
||||
static QEMUMachine pc_machine_v0_12 = {
|
||||
.name = "pc-0.12",
|
||||
.desc = "Standard PC",
|
||||
@@ -348,6 +356,7 @@ static QEMUMachine isapc_machine = {
|
||||
static void pc_machine_init(void)
|
||||
{
|
||||
qemu_register_machine(&pc_machine);
|
||||
+ qemu_register_machine(&pc_machine_f13);
|
||||
qemu_register_machine(&pc_machine_v0_12);
|
||||
qemu_register_machine(&pc_machine_v0_11);
|
||||
qemu_register_machine(&pc_machine_v0_10);
|
@ -1,44 +0,0 @@
|
||||
From 12a074387284fc530876ef709b3d344adea9b226 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Wed, 20 Jan 2010 00:36:57 +0530
|
||||
Subject: [PATCH 7/9] Move virtio-serial to Makefile.objs
|
||||
|
||||
There's nothing target-dependent in the virtio-serial code so allow it
|
||||
to be compiled just once for all the targets.
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
Makefile.hw | 2 +-
|
||||
Makefile.target | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Makefile.hw b/Makefile.hw
|
||||
index 6f4dbc4..de8a0c5 100644
|
||||
--- a/Makefile.hw
|
||||
+++ b/Makefile.hw
|
||||
@@ -13,7 +13,7 @@ QEMU_CFLAGS+=-I.. -I$(SRC_PATH)/fpu
|
||||
|
||||
obj-y =
|
||||
obj-y += loader.o
|
||||
-obj-y += virtio.o
|
||||
+obj-y += virtio.o virtio-serial.o
|
||||
obj-y += fw_cfg.o
|
||||
obj-y += watchdog.o
|
||||
obj-$(CONFIG_ECC) += ecc.o
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 234577c..0e4cfd1 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -166,7 +166,7 @@ ifdef CONFIG_SOFTMMU
|
||||
obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.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-serial.o virtio-serial-bus.o virtio-pci.o
|
||||
+obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
|
||||
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
|
||||
# MSI-X depends on kvm for interrupt injection,
|
||||
# so moved it from Makefile.hw to Makefile.target for now
|
||||
--
|
||||
1.6.2.5
|
||||
|
@ -1,199 +0,0 @@
|
||||
This adds notifiers for phys memory changes: a set of callbacks that
|
||||
vhost can register and update kernel accordingly. Down the road, kvm
|
||||
code can be switched to use these as well, instead of calling kvm code
|
||||
directly from exec.c as is done now.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
cpu-common.h | 19 ++++++++++
|
||||
exec.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 130 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/cpu-common.h b/cpu-common.h
|
||||
index 5e59564..326513d 100644
|
||||
--- a/cpu-common.h
|
||||
+++ b/cpu-common.h
|
||||
@@ -8,6 +8,7 @@
|
||||
#endif
|
||||
|
||||
#include "bswap.h"
|
||||
+#include "qemu-queue.h"
|
||||
|
||||
/* address in the RAM (different from a physical address) */
|
||||
typedef unsigned long ram_addr_t;
|
||||
@@ -62,6 +63,24 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
|
||||
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
|
||||
void cpu_unregister_map_client(void *cookie);
|
||||
|
||||
+struct CPUPhysMemoryClient;
|
||||
+typedef struct CPUPhysMemoryClient CPUPhysMemoryClient;
|
||||
+struct CPUPhysMemoryClient {
|
||||
+ void (*set_memory)(struct CPUPhysMemoryClient *client,
|
||||
+ target_phys_addr_t start_addr,
|
||||
+ ram_addr_t size,
|
||||
+ ram_addr_t phys_offset);
|
||||
+ int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client,
|
||||
+ target_phys_addr_t start_addr,
|
||||
+ target_phys_addr_t end_addr);
|
||||
+ int (*migration_log)(struct CPUPhysMemoryClient *client,
|
||||
+ int enable);
|
||||
+ QLIST_ENTRY(CPUPhysMemoryClient) list;
|
||||
+};
|
||||
+
|
||||
+void cpu_register_phys_memory_client(CPUPhysMemoryClient *);
|
||||
+void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *);
|
||||
+
|
||||
uint32_t ldub_phys(target_phys_addr_t addr);
|
||||
uint32_t lduw_phys(target_phys_addr_t addr);
|
||||
uint32_t ldl_phys(target_phys_addr_t addr);
|
||||
diff --git a/exec.c b/exec.c
|
||||
index 8f873ab..cbba15e 100644
|
||||
--- a/exec.c
|
||||
+++ b/exec.c
|
||||
@@ -1640,6 +1640,101 @@ const CPULogItem cpu_log_items[] = {
|
||||
{ 0, NULL, NULL },
|
||||
};
|
||||
|
||||
+#ifndef CONFIG_USER_ONLY
|
||||
+static QLIST_HEAD(memory_client_list, CPUPhysMemoryClient) memory_client_list
|
||||
+ = QLIST_HEAD_INITIALIZER(memory_client_list);
|
||||
+
|
||||
+static void cpu_notify_set_memory(target_phys_addr_t start_addr,
|
||||
+ ram_addr_t size,
|
||||
+ ram_addr_t phys_offset)
|
||||
+{
|
||||
+ CPUPhysMemoryClient *client;
|
||||
+ QLIST_FOREACH(client, &memory_client_list, list) {
|
||||
+ client->set_memory(client, start_addr, size, phys_offset);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int cpu_notify_sync_dirty_bitmap(target_phys_addr_t start,
|
||||
+ target_phys_addr_t end)
|
||||
+{
|
||||
+ CPUPhysMemoryClient *client;
|
||||
+ QLIST_FOREACH(client, &memory_client_list, list) {
|
||||
+ int r = client->sync_dirty_bitmap(client, start, end);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cpu_notify_migration_log(int enable)
|
||||
+{
|
||||
+ CPUPhysMemoryClient *client;
|
||||
+ QLIST_FOREACH(client, &memory_client_list, list) {
|
||||
+ int r = client->migration_log(client, enable);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void phys_page_for_each_in_l1_map(PhysPageDesc **phys_map,
|
||||
+ CPUPhysMemoryClient *client)
|
||||
+{
|
||||
+ PhysPageDesc *pd;
|
||||
+ int l1, l2;
|
||||
+
|
||||
+ for (l1 = 0; l1 < L1_SIZE; ++l1) {
|
||||
+ pd = phys_map[l1];
|
||||
+ if (!pd) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ for (l2 = 0; l2 < L2_SIZE; ++l2) {
|
||||
+ if (pd[l2].phys_offset == IO_MEM_UNASSIGNED) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ client->set_memory(client, pd[l2].region_offset,
|
||||
+ TARGET_PAGE_SIZE, pd[l2].phys_offset);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void phys_page_for_each(CPUPhysMemoryClient *client)
|
||||
+{
|
||||
+#if TARGET_PHYS_ADDR_SPACE_BITS > 32
|
||||
+
|
||||
+#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
|
||||
+#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
|
||||
+#endif
|
||||
+ void **phys_map = (void **)l1_phys_map;
|
||||
+ int l1;
|
||||
+ if (!l1_phys_map) {
|
||||
+ return;
|
||||
+ }
|
||||
+ for (l1 = 0; l1 < L1_SIZE; ++l1) {
|
||||
+ if (phys_map[l1]) {
|
||||
+ phys_page_for_each_in_l1_map(phys_map[l1], client);
|
||||
+ }
|
||||
+ }
|
||||
+#else
|
||||
+ if (!l1_phys_map) {
|
||||
+ return;
|
||||
+ }
|
||||
+ phys_page_for_each_in_l1_map(l1_phys_map, client);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+void cpu_register_phys_memory_client(CPUPhysMemoryClient *client)
|
||||
+{
|
||||
+ QLIST_INSERT_HEAD(&memory_client_list, client, list);
|
||||
+ phys_page_for_each(client);
|
||||
+}
|
||||
+
|
||||
+void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *client)
|
||||
+{
|
||||
+ QLIST_REMOVE(client, list);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static int cmp1(const char *s1, int n, const char *s2)
|
||||
{
|
||||
if (strlen(s2) != n)
|
||||
@@ -1899,10 +1994,16 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
|
||||
|
||||
int cpu_physical_memory_set_dirty_tracking(int enable)
|
||||
{
|
||||
+ int ret = 0;
|
||||
+ in_migration = enable;
|
||||
if (kvm_enabled()) {
|
||||
- return kvm_set_migration_log(enable);
|
||||
+ ret = kvm_set_migration_log(enable);
|
||||
}
|
||||
- return 0;
|
||||
+ if (ret < 0) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ ret = cpu_notify_migration_log(!!enable);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
int cpu_physical_memory_get_dirty_tracking(void)
|
||||
@@ -1915,8 +2016,13 @@ int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
- if (kvm_enabled())
|
||||
+ if (kvm_enabled()) {
|
||||
ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
|
||||
+ }
|
||||
+ if (ret < 0) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ ret = cpu_notify_sync_dirty_bitmap(start_addr, end_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2331,6 +2437,8 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
|
||||
if (kvm_enabled())
|
||||
kvm_set_phys_mem(start_addr, size, phys_offset);
|
||||
|
||||
+ cpu_notify_set_memory(start_addr, size, phys_offset);
|
||||
+
|
||||
if (phys_offset == IO_MEM_UNASSIGNED) {
|
||||
region_offset = start_addr;
|
||||
}
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,135 +0,0 @@
|
||||
From 8f4d4cb4e4e73d0533aa2cb421c14210c75f6edc Mon Sep 17 00:00:00 2001
|
||||
From: Mark McLoughlin <markmc@redhat.com>
|
||||
Date: Mon, 29 Jun 2009 14:49:03 +0100
|
||||
Subject: [PATCH] Fix linux-user build on ppc
|
||||
|
||||
kvm-87 build fails on ppc:
|
||||
|
||||
https://koji.fedoraproject.org/koji/getfile?taskID=1441042&name=build.log
|
||||
|
||||
gcc -I. -I.. -I/builddir/build/BUILD/qemu-kvm-devel-87/target-i386
|
||||
-I/builddir/build/BUILD/qemu-kvm-devel-87 -MMD -MT elfload.o -MP
|
||||
-DNEED_CPU_H -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
-D__user= -I/builddir/build/BUILD/qemu-kvm-devel-87/tcg
|
||||
-I/builddir/build/BUILD/qemu-kvm-devel-87/tcg/ppc64
|
||||
-I/builddir/build/BUILD/qemu-kvm-devel-87/fpu
|
||||
-I/builddir/build/BUILD/qemu-kvm-devel-87/linux-user
|
||||
-I/builddir/build/BUILD/qemu-kvm-devel-87/linux-user/i386 -O2 -g -pipe
|
||||
-Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector
|
||||
--param=ssp-buffer-size=4 -m64 -mminimal-toc -g -fno-strict-aliasing
|
||||
-O2 -Wall -Wundef -Wendif-labels -Wwrite-strings -Wmissing-prototypes
|
||||
-Wstrict-prototypes -Wredundant-decls -c -o elfload.o
|
||||
/builddir/build/BUILD/qemu-kvm-devel-87/linux-user/elfload.c
|
||||
/builddir/build/BUILD/qemu-kvm-devel-87/linux-user/elfload.c:214: error: conflicting types for 'elf_greg_t'
|
||||
/usr/include/asm/elf.h:123: note: previous declaration of 'elf_greg_t' was here
|
||||
/builddir/build/BUILD/qemu-kvm-devel-87/linux-user/elfload.c:220: error: conflicting types for 'elf_gregset_t'
|
||||
/usr/include/asm/elf.h:124: note: previous declaration of 'elf_gregset_t' was here
|
||||
In file included from /builddir/build/BUILD/qemu-kvm-devel-87/linux-user/elfload.c:697:
|
||||
../elf.h:457:1: warning: "R_PPC_NUM" redefined
|
||||
In file included from /usr/include/asm/sigcontext.h:13,
|
||||
from /usr/include/bits/sigcontext.h:28,
|
||||
from /usr/include/signal.h:339,
|
||||
from /builddir/build/BUILD/qemu-kvm-devel-87/linux-user/qemu.h:4,
|
||||
from /builddir/build/BUILD/qemu-kvm-devel-87/linux-user/elfload.c:16:
|
||||
/usr/include/asm/elf.h:81:1: warning: this is the location of the previous definition
|
||||
|
||||
Problem seems to be that signal.h is pulling in a bunch of ppc
|
||||
headers which expose elf_greg_t, R_PPC_* and PPC_FEATURE_*.
|
||||
|
||||
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
|
||||
Fedora-patch: qemu-fix-linux-user-build-on-ppc.patch
|
||||
---
|
||||
elf.h | 2 ++
|
||||
linux-user/elfload.c | 10 ++++++++++
|
||||
2 files changed, 12 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/elf.h b/elf.h
|
||||
index b042002..14f8aa1 100644
|
||||
--- a/elf.h
|
||||
+++ b/elf.h
|
||||
@@ -454,7 +454,9 @@ typedef struct {
|
||||
#define R_PPC_SECTOFF_HI 35
|
||||
#define R_PPC_SECTOFF_HA 36
|
||||
/* Keep this the last entry. */
|
||||
+#ifndef R_PPC_NUM
|
||||
#define R_PPC_NUM 37
|
||||
+#endif /* R_PPC_NUM */
|
||||
|
||||
/* ARM specific declarations */
|
||||
|
||||
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
|
||||
index 3a8268b..d283f73 100644
|
||||
--- a/linux-user/elfload.c
|
||||
+++ b/linux-user/elfload.c
|
||||
@@ -134,6 +134,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
|
||||
regs->rip = infop->entry;
|
||||
}
|
||||
|
||||
+#ifdef FIX_BROKEN_PPC_BUILD
|
||||
typedef target_ulong elf_greg_t;
|
||||
typedef uint32_t target_uid_t;
|
||||
typedef uint32_t target_gid_t;
|
||||
@@ -179,6 +180,7 @@ static void elf_core_copy_regs(elf_gregset_t *regs, const CPUState *env)
|
||||
(*regs)[25] = env->segs[R_FS].selector & 0xffff;
|
||||
(*regs)[26] = env->segs[R_GS].selector & 0xffff;
|
||||
}
|
||||
+#endif /* FIX_BROKEN_PPC_BUILD */
|
||||
|
||||
#else
|
||||
|
||||
@@ -211,6 +213,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
|
||||
regs->edx = 0;
|
||||
}
|
||||
|
||||
+#ifdef FIX_BROKEN_PPC_BUILD
|
||||
typedef target_ulong elf_greg_t;
|
||||
typedef uint16_t target_uid_t;
|
||||
typedef uint16_t target_gid_t;
|
||||
@@ -246,9 +249,12 @@ static void elf_core_copy_regs(elf_gregset_t *regs, const CPUState *env)
|
||||
(*regs)[15] = env->regs[R_ESP];
|
||||
(*regs)[16] = env->segs[R_SS].selector & 0xffff;
|
||||
}
|
||||
+#endif /* FIX_BROKEN_PPC_BUILD */
|
||||
#endif
|
||||
|
||||
+#ifdef FIX_BROKEN_PPC_BUILD
|
||||
#define USE_ELF_CORE_DUMP
|
||||
+#endif /* FIX_BROKEN_PPC_BUILD */
|
||||
#define ELF_EXEC_PAGESIZE 4096
|
||||
|
||||
#endif
|
||||
@@ -286,6 +292,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
|
||||
regs->ARM_r10 = infop->start_data;
|
||||
}
|
||||
|
||||
+#ifdef FIX_BROKEN_PPC_BUILD
|
||||
typedef uint32_t elf_greg_t;
|
||||
typedef uint16_t target_uid_t;
|
||||
typedef uint16_t target_gid_t;
|
||||
@@ -318,6 +325,7 @@ static void elf_core_copy_regs(elf_gregset_t *regs, const CPUState *env)
|
||||
}
|
||||
|
||||
#define USE_ELF_CORE_DUMP
|
||||
+#endif /* FIX_BROKEN_PPC_BUILD */
|
||||
#define ELF_EXEC_PAGESIZE 4096
|
||||
|
||||
enum
|
||||
@@ -421,6 +429,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
|
||||
|
||||
/* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
|
||||
See arch/powerpc/include/asm/cputable.h. */
|
||||
+#ifndef PPC_FEATURE_32
|
||||
enum {
|
||||
PPC_FEATURE_32 = 0x80000000,
|
||||
PPC_FEATURE_64 = 0x40000000,
|
||||
@@ -452,6 +461,7 @@ enum {
|
||||
PPC_FEATURE_TRUE_LE = 0x00000002,
|
||||
PPC_FEATURE_PPC_LE = 0x00000001,
|
||||
};
|
||||
+#endif /* !defined(PPC_FEATURE_32) */
|
||||
|
||||
#define ELF_HWCAP get_elf_hwcap()
|
||||
|
||||
--
|
||||
1.6.2.5
|
||||
|
@ -1,140 +0,0 @@
|
||||
From 1df18d4a961a66b9ea28ab83b409f4d9d470f148 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Thu, 8 Oct 2009 15:02:08 +0200
|
||||
Subject: [PATCH] qcow2: Bring synchronous read/write back to life
|
||||
|
||||
When the synchronous read and write functions were dropped, they were replaced
|
||||
by generic emulation functions. Unfortunately, these emulation functions don't
|
||||
provide the same semantics as the original functions did.
|
||||
|
||||
The original bdrv_read would mean that we read some data synchronously and that
|
||||
we won't be interrupted during this read. The latter assumption is no longer
|
||||
true with the emulation function which needs to use qemu_aio_poll and therefore
|
||||
allows the callback of any other concurrent AIO request to be run during the
|
||||
read. Which in turn means that (meta)data read earlier could have changed and
|
||||
be invalid now. qcow2 is not prepared to work in this way and it's just scary
|
||||
how many places there are where other requests could run.
|
||||
|
||||
I'm not sure yet where exactly it breaks, but you'll see breakage with virtio
|
||||
on qcow2 with a backing file. Providing synchronous functions again fixes the
|
||||
problem for me.
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
|
||||
Fedora-patch: qemu-fix-qcow2-backing-file-with-virtio.patch
|
||||
---
|
||||
block/qcow2-cluster.c | 6 ++--
|
||||
block/qcow2.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
block/qcow2.h | 3 ++
|
||||
3 files changed, 55 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
|
||||
index d4631c3..4d0ce16 100644
|
||||
--- a/block/qcow2-cluster.c
|
||||
+++ b/block/qcow2-cluster.c
|
||||
@@ -306,8 +306,8 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
|
||||
}
|
||||
|
||||
|
||||
-static int qcow_read(BlockDriverState *bs, int64_t sector_num,
|
||||
- uint8_t *buf, int nb_sectors)
|
||||
+int qcow2_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
|
||||
+ int nb_sectors)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int ret, index_in_cluster, n, n1;
|
||||
@@ -358,7 +358,7 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
|
||||
n = n_end - n_start;
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
- ret = qcow_read(bs, start_sect + n_start, s->cluster_data, n);
|
||||
+ ret = qcow2_read(bs, start_sect + n_start, s->cluster_data, n);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (s->crypt_method) {
|
||||
diff --git a/block/qcow2.c b/block/qcow2.c
|
||||
index dd32ea2..ced257e 100644
|
||||
--- a/block/qcow2.c
|
||||
+++ b/block/qcow2.c
|
||||
@@ -855,6 +855,51 @@ static int qcow_make_empty(BlockDriverState *bs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int qcow2_write(BlockDriverState *bs, int64_t sector_num,
|
||||
+ const uint8_t *buf, int nb_sectors)
|
||||
+{
|
||||
+ BDRVQcowState *s = bs->opaque;
|
||||
+ int ret, index_in_cluster, n;
|
||||
+ uint64_t cluster_offset;
|
||||
+ int n_end;
|
||||
+ QCowL2Meta l2meta;
|
||||
+
|
||||
+ while (nb_sectors > 0) {
|
||||
+ memset(&l2meta, 0, sizeof(l2meta));
|
||||
+
|
||||
+ index_in_cluster = sector_num & (s->cluster_sectors - 1);
|
||||
+ n_end = index_in_cluster + nb_sectors;
|
||||
+ if (s->crypt_method &&
|
||||
+ n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors)
|
||||
+ n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors;
|
||||
+ cluster_offset = qcow2_alloc_cluster_offset(bs, sector_num << 9,
|
||||
+ index_in_cluster,
|
||||
+ n_end, &n, &l2meta);
|
||||
+ if (!cluster_offset)
|
||||
+ return -1;
|
||||
+ if (s->crypt_method) {
|
||||
+ qcow2_encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
|
||||
+ &s->aes_encrypt_key);
|
||||
+ ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512,
|
||||
+ s->cluster_data, n * 512);
|
||||
+ } else {
|
||||
+ ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
|
||||
+ }
|
||||
+ if (ret != n * 512 || qcow2_alloc_cluster_link_l2(bs, cluster_offset, &l2meta) < 0) {
|
||||
+ qcow2_free_any_clusters(bs, cluster_offset, l2meta.nb_clusters);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ nb_sectors -= n;
|
||||
+ sector_num += n;
|
||||
+ buf += n * 512;
|
||||
+ if (l2meta.nb_clusters != 0) {
|
||||
+ LIST_REMOVE(&l2meta, next_in_flight);
|
||||
+ }
|
||||
+ }
|
||||
+ s->cluster_cache_offset = -1; /* disable compressed cache */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* XXX: put compressed sectors first, then all the cluster aligned
|
||||
tables to avoid losing bytes in alignment */
|
||||
static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
@@ -1037,8 +1082,10 @@ static BlockDriver bdrv_qcow2 = {
|
||||
.bdrv_set_key = qcow_set_key,
|
||||
.bdrv_make_empty = qcow_make_empty,
|
||||
|
||||
- .bdrv_aio_readv = qcow_aio_readv,
|
||||
- .bdrv_aio_writev = qcow_aio_writev,
|
||||
+ .bdrv_read = qcow2_read,
|
||||
+ .bdrv_write = qcow2_write,
|
||||
+ .bdrv_aio_readv = qcow_aio_readv,
|
||||
+ .bdrv_aio_writev = qcow_aio_writev,
|
||||
.bdrv_write_compressed = qcow_write_compressed,
|
||||
|
||||
.bdrv_snapshot_create = qcow2_snapshot_create,
|
||||
diff --git a/block/qcow2.h b/block/qcow2.h
|
||||
index 965a2f4..b41aa63 100644
|
||||
--- a/block/qcow2.h
|
||||
+++ b/block/qcow2.h
|
||||
@@ -202,6 +202,9 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
|
||||
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
|
||||
QCowL2Meta *m);
|
||||
|
||||
+int qcow2_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
|
||||
+ int nb_sectors);
|
||||
+
|
||||
/* qcow2-snapshot.c functions */
|
||||
int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
|
||||
int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id);
|
||||
--
|
||||
1.6.2.5
|
||||
|
@ -1,81 +0,0 @@
|
||||
This adds API to set ioeventfd to kvm,
|
||||
as well as stubs for non-eventfd case,
|
||||
making it possible for users to use this API
|
||||
without ifdefs.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
kvm-all.c | 20 ++++++++++++++++++++
|
||||
kvm.h | 16 ++++++++++++++++
|
||||
2 files changed, 36 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/kvm-all.c b/kvm-all.c
|
||||
index 0423fff..efdf40c 100644
|
||||
--- a/kvm-all.c
|
||||
+++ b/kvm-all.c
|
||||
@@ -1102,4 +1102,24 @@ void kvm_remove_all_breakpoints(CPUState *current_env)
|
||||
}
|
||||
#endif /* !KVM_CAP_SET_GUEST_DEBUG */
|
||||
|
||||
+#ifdef KVM_IOEVENTFD
|
||||
+int kvm_set_ioeventfd(uint16_t addr, uint16_t data, int fd, bool assigned)
|
||||
+{
|
||||
+ struct kvm_ioeventfd kick = {
|
||||
+ .datamatch = data,
|
||||
+ .addr = addr,
|
||||
+ .len = 2,
|
||||
+ .flags = KVM_IOEVENTFD_FLAG_DATAMATCH | KVM_IOEVENTFD_FLAG_PIO,
|
||||
+ .fd = fd,
|
||||
+ };
|
||||
+ int r;
|
||||
+ if (!assigned)
|
||||
+ kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
|
||||
+ r = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
#include "qemu-kvm.c"
|
||||
diff --git a/kvm.h b/kvm.h
|
||||
index 9fa4e25..e98b5c8 100644
|
||||
--- a/kvm.h
|
||||
+++ b/kvm.h
|
||||
@@ -14,6 +14,8 @@
|
||||
#ifndef QEMU_KVM_H
|
||||
#define QEMU_KVM_H
|
||||
|
||||
+#include <stdbool.h>
|
||||
+#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "qemu-queue.h"
|
||||
#include "qemu-kvm.h"
|
||||
@@ -21,6 +23,10 @@
|
||||
#ifdef KVM_UPSTREAM
|
||||
|
||||
#ifdef CONFIG_KVM
|
||||
+#include <linux/kvm.h>
|
||||
+#endif
|
||||
+
|
||||
+#ifdef CONFIG_KVM
|
||||
extern int kvm_allowed;
|
||||
|
||||
#define kvm_enabled() (kvm_allowed)
|
||||
@@ -151,4 +157,14 @@ static inline void cpu_synchronize_state(CPUState *env)
|
||||
|
||||
#endif
|
||||
|
||||
+#if defined(KVM_IOEVENTFD) && defined(CONFIG_KVM)
|
||||
+int kvm_set_ioeventfd(uint16_t addr, uint16_t data, int fd, bool assigned);
|
||||
+#else
|
||||
+static inline
|
||||
+int kvm_set_ioeventfd(uint16_t data, uint16_t addr, int fd, bool assigned)
|
||||
+{
|
||||
+ return -ENOSYS;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
#endif
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,147 +0,0 @@
|
||||
This makes it possible to build vhost support
|
||||
on systems which do not have this header.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
kvm/include/linux/vhost.h | 130 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 files changed, 130 insertions(+), 0 deletions(-)
|
||||
create mode 100644 kvm/include/linux/vhost.h
|
||||
|
||||
diff --git a/kvm/include/linux/vhost.h b/kvm/include/linux/vhost.h
|
||||
new file mode 100644
|
||||
index 0000000..165a484
|
||||
--- /dev/null
|
||||
+++ b/kvm/include/linux/vhost.h
|
||||
@@ -0,0 +1,130 @@
|
||||
+#ifndef _LINUX_VHOST_H
|
||||
+#define _LINUX_VHOST_H
|
||||
+/* Userspace interface for in-kernel virtio accelerators. */
|
||||
+
|
||||
+/* vhost is used to reduce the number of system calls involved in virtio.
|
||||
+ *
|
||||
+ * Existing virtio net code is used in the guest without modification.
|
||||
+ *
|
||||
+ * This header includes interface used by userspace hypervisor for
|
||||
+ * device configuration.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
+#include <linux/ioctl.h>
|
||||
+#include <linux/virtio_config.h>
|
||||
+#include <linux/virtio_ring.h>
|
||||
+
|
||||
+struct vhost_vring_state {
|
||||
+ unsigned int index;
|
||||
+ unsigned int num;
|
||||
+};
|
||||
+
|
||||
+struct vhost_vring_file {
|
||||
+ unsigned int index;
|
||||
+ int fd; /* Pass -1 to unbind from file. */
|
||||
+
|
||||
+};
|
||||
+
|
||||
+struct vhost_vring_addr {
|
||||
+ unsigned int index;
|
||||
+ /* Option flags. */
|
||||
+ unsigned int flags;
|
||||
+ /* Flag values: */
|
||||
+ /* Whether log address is valid. If set enables logging. */
|
||||
+#define VHOST_VRING_F_LOG 0
|
||||
+
|
||||
+ /* Start of array of descriptors (virtually contiguous) */
|
||||
+ __u64 desc_user_addr;
|
||||
+ /* Used structure address. Must be 32 bit aligned */
|
||||
+ __u64 used_user_addr;
|
||||
+ /* Available structure address. Must be 16 bit aligned */
|
||||
+ __u64 avail_user_addr;
|
||||
+ /* Logging support. */
|
||||
+ /* Log writes to used structure, at offset calculated from specified
|
||||
+ * address. Address must be 32 bit aligned. */
|
||||
+ __u64 log_guest_addr;
|
||||
+};
|
||||
+
|
||||
+struct vhost_memory_region {
|
||||
+ __u64 guest_phys_addr;
|
||||
+ __u64 memory_size; /* bytes */
|
||||
+ __u64 userspace_addr;
|
||||
+ __u64 flags_padding; /* No flags are currently specified. */
|
||||
+};
|
||||
+
|
||||
+/* All region addresses and sizes must be 4K aligned. */
|
||||
+#define VHOST_PAGE_SIZE 0x1000
|
||||
+
|
||||
+struct vhost_memory {
|
||||
+ __u32 nregions;
|
||||
+ __u32 padding;
|
||||
+ struct vhost_memory_region regions[0];
|
||||
+};
|
||||
+
|
||||
+/* ioctls */
|
||||
+
|
||||
+#define VHOST_VIRTIO 0xAF
|
||||
+
|
||||
+/* Features bitmask for forward compatibility. Transport bits are used for
|
||||
+ * vhost specific features. */
|
||||
+#define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)
|
||||
+#define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64)
|
||||
+
|
||||
+/* Set current process as the (exclusive) owner of this file descriptor. This
|
||||
+ * must be called before any other vhost command. Further calls to
|
||||
+ * VHOST_OWNER_SET fail until VHOST_OWNER_RESET is called. */
|
||||
+#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)
|
||||
+/* Give up ownership, and reset the device to default values.
|
||||
+ * Allows subsequent call to VHOST_OWNER_SET to succeed. */
|
||||
+#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
|
||||
+
|
||||
+/* Set up/modify memory layout */
|
||||
+#define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
|
||||
+
|
||||
+/* Write logging setup. */
|
||||
+/* Memory writes can optionally be logged by setting bit at an offset
|
||||
+ * (calculated from the physical address) from specified log base.
|
||||
+ * The bit is set using an atomic 32 bit operation. */
|
||||
+/* Set base address for logging. */
|
||||
+#define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
|
||||
+/* Specify an eventfd file descriptor to signal on log write. */
|
||||
+#define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
|
||||
+
|
||||
+/* Ring setup. */
|
||||
+/* Set number of descriptors in ring. This parameter can not
|
||||
+ * be modified while ring is running (bound to a device). */
|
||||
+#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)
|
||||
+/* Set addresses for the ring. */
|
||||
+#define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)
|
||||
+/* Base value where queue looks for available descriptors */
|
||||
+#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
|
||||
+/* Get accessor: reads index, writes value in num */
|
||||
+#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
|
||||
+
|
||||
+/* The following ioctls use eventfd file descriptors to signal and poll
|
||||
+ * for events. */
|
||||
+
|
||||
+/* Set eventfd to poll for added buffers */
|
||||
+#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)
|
||||
+/* Set eventfd to signal when buffers have beed used */
|
||||
+#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)
|
||||
+/* Set eventfd to signal an error */
|
||||
+#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
|
||||
+
|
||||
+/* VHOST_NET specific defines */
|
||||
+
|
||||
+/* Attach virtio net ring to a raw socket, or tap device.
|
||||
+ * The socket must be already bound to an ethernet device, this device will be
|
||||
+ * used for transmit. Pass fd -1 to unbind from the socket and the transmit
|
||||
+ * device. This can be used to stop the ring (e.g. for migration). */
|
||||
+#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
|
||||
+
|
||||
+/* Feature bits */
|
||||
+/* Log all write descriptors. Can be changed while device is active. */
|
||||
+#define VHOST_F_LOG_ALL 26
|
||||
+/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
|
||||
+#define VHOST_NET_F_VIRTIO_NET_HDR 27
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,59 +0,0 @@
|
||||
Add API to assign/deassign irqfd to kvm.
|
||||
Add stub so that users do not have to use
|
||||
ifdefs.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
kvm-all.c | 19 +++++++++++++++++++
|
||||
kvm.h | 10 ++++++++++
|
||||
2 files changed, 29 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/kvm-all.c b/kvm-all.c
|
||||
index efdf40c..b3fdf29 100644
|
||||
--- a/kvm-all.c
|
||||
+++ b/kvm-all.c
|
||||
@@ -1122,4 +1122,23 @@ int kvm_set_ioeventfd(uint16_t addr, uint16_t data, int fd, bool assigned)
|
||||
}
|
||||
#endif
|
||||
|
||||
+#if defined(KVM_IRQFD)
|
||||
+int kvm_set_irqfd(int gsi, int fd, bool assigned)
|
||||
+{
|
||||
+ struct kvm_irqfd irqfd = {
|
||||
+ .fd = fd,
|
||||
+ .gsi = gsi,
|
||||
+ .flags = assigned ? 0 : KVM_IRQFD_FLAG_DEASSIGN,
|
||||
+ };
|
||||
+ int r;
|
||||
+ if (!kvm_irqchip_in_kernel())
|
||||
+ return -ENOSYS;
|
||||
+
|
||||
+ r = kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
#include "qemu-kvm.c"
|
||||
diff --git a/kvm.h b/kvm.h
|
||||
index e98b5c8..ad8d122 100644
|
||||
--- a/kvm.h
|
||||
+++ b/kvm.h
|
||||
@@ -167,4 +167,14 @@ int kvm_set_ioeventfd(uint16_t data, uint16_t addr, int fd, bool assigned)
|
||||
}
|
||||
#endif
|
||||
|
||||
+#if defined(KVM_IRQFD) && defined(CONFIG_KVM)
|
||||
+int kvm_set_irqfd(int gsi, int fd, bool assigned);
|
||||
+#else
|
||||
+static inline
|
||||
+int kvm_set_irqfd(int gsi, int fd, bool assigned)
|
||||
+{
|
||||
+ return -ENOSYS;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
#endif
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,121 +0,0 @@
|
||||
Support per-vector callbacks for msix mask/unmask.
|
||||
Will be used for vhost net.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/msix.c | 36 +++++++++++++++++++++++++++++++++++-
|
||||
hw/msix.h | 1 +
|
||||
hw/pci.h | 6 ++++++
|
||||
3 files changed, 42 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/hw/msix.c b/hw/msix.c
|
||||
index d117bcf..3fcf3a1 100644
|
||||
--- a/hw/msix.c
|
||||
+++ b/hw/msix.c
|
||||
@@ -318,6 +318,13 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
|
||||
if (kvm_enabled() && kvm_irqchip_in_kernel()) {
|
||||
kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector));
|
||||
}
|
||||
+ if (was_masked != msix_is_masked(dev, vector) &&
|
||||
+ dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
|
||||
+ int r = dev->msix_mask_notifier(dev, vector,
|
||||
+ dev->msix_mask_notifier_opaque[vector],
|
||||
+ msix_is_masked(dev, vector));
|
||||
+ assert(r >= 0);
|
||||
+ }
|
||||
msix_handle_mask_update(dev, vector);
|
||||
}
|
||||
|
||||
@@ -356,10 +363,18 @@ void msix_mmio_map(PCIDevice *d, int region_num,
|
||||
|
||||
static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
|
||||
{
|
||||
- int vector;
|
||||
+ int vector, r;
|
||||
for (vector = 0; vector < nentries; ++vector) {
|
||||
unsigned offset = vector * MSIX_ENTRY_SIZE + MSIX_VECTOR_CTRL;
|
||||
+ int was_masked = msix_is_masked(dev, vector);
|
||||
dev->msix_table_page[offset] |= MSIX_VECTOR_MASK;
|
||||
+ if (was_masked != msix_is_masked(dev, vector) &&
|
||||
+ dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
|
||||
+ r = dev->msix_mask_notifier(dev, vector,
|
||||
+ dev->msix_mask_notifier_opaque[vector],
|
||||
+ msix_is_masked(dev, vector));
|
||||
+ assert(r >= 0);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,6 +397,9 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
|
||||
sizeof *dev->msix_irq_entries);
|
||||
}
|
||||
#endif
|
||||
+ dev->msix_mask_notifier_opaque =
|
||||
+ qemu_mallocz(nentries * sizeof *dev->msix_mask_notifier_opaque);
|
||||
+ dev->msix_mask_notifier = NULL;
|
||||
dev->msix_entry_used = qemu_mallocz(MSIX_MAX_ENTRIES *
|
||||
sizeof *dev->msix_entry_used);
|
||||
|
||||
@@ -444,6 +462,8 @@ int msix_uninit(PCIDevice *dev)
|
||||
dev->msix_entry_used = NULL;
|
||||
qemu_free(dev->msix_irq_entries);
|
||||
dev->msix_irq_entries = NULL;
|
||||
+ qemu_free(dev->msix_mask_notifier_opaque);
|
||||
+ dev->msix_mask_notifier_opaque = NULL;
|
||||
dev->cap_present &= ~QEMU_PCI_CAP_MSIX;
|
||||
return 0;
|
||||
}
|
||||
@@ -587,3 +607,17 @@ void msix_unuse_all_vectors(PCIDevice *dev)
|
||||
return;
|
||||
msix_free_irq_entries(dev);
|
||||
}
|
||||
+
|
||||
+int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque)
|
||||
+{
|
||||
+ int r = 0;
|
||||
+ if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
|
||||
+ return 0;
|
||||
+
|
||||
+ if (dev->msix_mask_notifier)
|
||||
+ r = dev->msix_mask_notifier(dev, vector, opaque,
|
||||
+ msix_is_masked(dev, vector));
|
||||
+ if (r >= 0)
|
||||
+ dev->msix_mask_notifier_opaque[vector] = opaque;
|
||||
+ return r;
|
||||
+}
|
||||
diff --git a/hw/msix.h b/hw/msix.h
|
||||
index a9f7993..f167231 100644
|
||||
--- a/hw/msix.h
|
||||
+++ b/hw/msix.h
|
||||
@@ -33,4 +33,5 @@ void msix_reset(PCIDevice *dev);
|
||||
|
||||
extern int msix_supported;
|
||||
|
||||
+int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque);
|
||||
#endif
|
||||
diff --git a/hw/pci.h b/hw/pci.h
|
||||
index a225a6a..bf722ca 100644
|
||||
--- a/hw/pci.h
|
||||
+++ b/hw/pci.h
|
||||
@@ -217,6 +217,9 @@ enum {
|
||||
#define PCI_CAPABILITY_CONFIG_MSI_LENGTH 0x10
|
||||
#define PCI_CAPABILITY_CONFIG_MSIX_LENGTH 0x10
|
||||
|
||||
+typedef int (*msix_mask_notifier_func)(PCIDevice *, unsigned vector,
|
||||
+ void *opaque, int masked);
|
||||
+
|
||||
struct PCIDevice {
|
||||
DeviceState qdev;
|
||||
/* PCI config space */
|
||||
@@ -282,6 +285,9 @@ struct PCIDevice {
|
||||
|
||||
struct kvm_irq_routing_entry *msix_irq_entries;
|
||||
|
||||
+ void **msix_mask_notifier_opaque;
|
||||
+ msix_mask_notifier_func msix_mask_notifier;
|
||||
+
|
||||
/* Device capability configuration space */
|
||||
struct {
|
||||
int supported;
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,68 +0,0 @@
|
||||
When vhost is bound to a backend device, we need to stop polling it when
|
||||
vhost is started, and restart polling when vhost is stopped.
|
||||
Add an API for that for use by vhost, and implement in tap backend.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
(cherry picked from commit ceb696159d569db5b2a7659ce38752398c236742)
|
||||
---
|
||||
net.h | 3 +++
|
||||
net/tap.c | 8 ++++++++
|
||||
2 files changed, 11 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/net.h b/net.h
|
||||
index 4971fcb..116bb80 100644
|
||||
--- a/net.h
|
||||
+++ b/net.h
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef QEMU_NET_H
|
||||
#define QEMU_NET_H
|
||||
|
||||
+#include <stdbool.h>
|
||||
#include "qemu-queue.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qdict.h"
|
||||
@@ -36,6 +37,7 @@ typedef enum {
|
||||
NET_CLIENT_TYPE_DUMP
|
||||
} net_client_type;
|
||||
|
||||
+typedef void (NetPoll)(VLANClientState *, bool enable);
|
||||
typedef int (NetCanReceive)(VLANClientState *);
|
||||
typedef ssize_t (NetReceive)(VLANClientState *, const uint8_t *, size_t);
|
||||
typedef ssize_t (NetReceiveIOV)(VLANClientState *, const struct iovec *, int);
|
||||
@@ -51,6 +53,7 @@ typedef struct NetClientInfo {
|
||||
NetCanReceive *can_receive;
|
||||
NetCleanup *cleanup;
|
||||
LinkStatusChanged *link_status_changed;
|
||||
+ NetPoll *poll;
|
||||
} NetClientInfo;
|
||||
|
||||
struct VLANClientState {
|
||||
diff --git a/net/tap.c b/net/tap.c
|
||||
index 0d8b424..d3492de 100644
|
||||
--- a/net/tap.c
|
||||
+++ b/net/tap.c
|
||||
@@ -262,6 +262,13 @@ static void tap_cleanup(VLANClientState *nc)
|
||||
close(s->fd);
|
||||
}
|
||||
|
||||
+static void tap_poll(VLANClientState *nc, bool enable)
|
||||
+{
|
||||
+ TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
+ tap_read_poll(s, enable);
|
||||
+ tap_write_poll(s, enable);
|
||||
+}
|
||||
+
|
||||
/* fd support */
|
||||
|
||||
static NetClientInfo net_tap_info = {
|
||||
@@ -270,6 +277,7 @@ static NetClientInfo net_tap_info = {
|
||||
.receive = tap_receive,
|
||||
.receive_raw = tap_receive_raw,
|
||||
.receive_iov = tap_receive_iov,
|
||||
+ .poll = tap_poll,
|
||||
.cleanup = tap_cleanup,
|
||||
};
|
||||
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,122 +0,0 @@
|
||||
event notifiers are slightly generalized eventfd descriptors. Current
|
||||
implementation depends on eventfd because vhost is the only user, and
|
||||
vhost depends on eventfd anyway, but a stub is provided for non-eventfd
|
||||
case.
|
||||
|
||||
We'll be able to further generalize this when another user comes along
|
||||
and we see how to best do this.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
Makefile.target | 1 +
|
||||
hw/notifier.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
hw/notifier.h | 16 ++++++++++++++++
|
||||
qemu-common.h | 1 +
|
||||
4 files changed, 68 insertions(+), 0 deletions(-)
|
||||
create mode 100644 hw/notifier.c
|
||||
create mode 100644 hw/notifier.h
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 6037fed..0c844a9 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -167,6 +167,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.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-pci.o virtio-serial-bus.o
|
||||
+obj-y += notifier.o
|
||||
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
|
||||
# MSI-X depends on kvm for interrupt injection,
|
||||
# so moved it from Makefile.hw to Makefile.target for now
|
||||
diff --git a/hw/notifier.c b/hw/notifier.c
|
||||
new file mode 100644
|
||||
index 0000000..dff38de
|
||||
--- /dev/null
|
||||
+++ b/hw/notifier.c
|
||||
@@ -0,0 +1,50 @@
|
||||
+#include "hw.h"
|
||||
+#include "notifier.h"
|
||||
+#ifdef CONFIG_EVENTFD
|
||||
+#include <sys/eventfd.h>
|
||||
+#endif
|
||||
+
|
||||
+int event_notifier_init(EventNotifier *e, int active)
|
||||
+{
|
||||
+#ifdef CONFIG_EVENTFD
|
||||
+ int fd = eventfd(!!active, EFD_NONBLOCK | EFD_CLOEXEC);
|
||||
+ if (fd < 0)
|
||||
+ return -errno;
|
||||
+ e->fd = fd;
|
||||
+ return 0;
|
||||
+#else
|
||||
+ return -ENOSYS;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+void event_notifier_cleanup(EventNotifier *e)
|
||||
+{
|
||||
+ close(e->fd);
|
||||
+}
|
||||
+
|
||||
+int event_notifier_get_fd(EventNotifier *e)
|
||||
+{
|
||||
+ return e->fd;
|
||||
+}
|
||||
+
|
||||
+int event_notifier_test_and_clear(EventNotifier *e)
|
||||
+{
|
||||
+ uint64_t value;
|
||||
+ int r = read(e->fd, &value, sizeof value);
|
||||
+ return r == sizeof value;
|
||||
+}
|
||||
+
|
||||
+int event_notifier_test(EventNotifier *e)
|
||||
+{
|
||||
+ uint64_t value;
|
||||
+ int r = read(e->fd, &value, sizeof value);
|
||||
+ if (r == sizeof value) {
|
||||
+ /* restore previous value. */
|
||||
+ int s = write(e->fd, &value, sizeof value);
|
||||
+ /* never blocks because we use EFD_SEMAPHORE.
|
||||
+ * If we didn't we'd get EAGAIN on overflow
|
||||
+ * and we'd have to write code to ignore it. */
|
||||
+ assert(s == sizeof value);
|
||||
+ }
|
||||
+ return r == sizeof value;
|
||||
+}
|
||||
diff --git a/hw/notifier.h b/hw/notifier.h
|
||||
new file mode 100644
|
||||
index 0000000..24117ea
|
||||
--- /dev/null
|
||||
+++ b/hw/notifier.h
|
||||
@@ -0,0 +1,16 @@
|
||||
+#ifndef QEMU_EVENT_NOTIFIER_H
|
||||
+#define QEMU_EVENT_NOTIFIER_H
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+
|
||||
+struct EventNotifier {
|
||||
+ int fd;
|
||||
+};
|
||||
+
|
||||
+int event_notifier_init(EventNotifier *, int active);
|
||||
+void event_notifier_cleanup(EventNotifier *);
|
||||
+int event_notifier_get_fd(EventNotifier *);
|
||||
+int event_notifier_test_and_clear(EventNotifier *);
|
||||
+int event_notifier_test(EventNotifier *);
|
||||
+
|
||||
+#endif
|
||||
diff --git a/qemu-common.h b/qemu-common.h
|
||||
index 5fbe0f9..cdead98 100644
|
||||
--- a/qemu-common.h
|
||||
+++ b/qemu-common.h
|
||||
@@ -217,6 +217,7 @@ typedef struct uWireSlave uWireSlave;
|
||||
typedef struct I2SCodec I2SCodec;
|
||||
typedef struct DeviceState DeviceState;
|
||||
typedef struct SSIBus SSIBus;
|
||||
+typedef struct EventNotifier EventNotifier;
|
||||
|
||||
/* CPU save/load. */
|
||||
void cpu_save(QEMUFile *f, void *opaque);
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,156 +0,0 @@
|
||||
This adds "bit" property type, which is a boolean stored in a 32 bit
|
||||
integer field, with legal values on and off. Will be used by virtio for
|
||||
feature bits.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
(cherry picked from commit d2364ee424ebf9180afaf21128a71da55321ad00)
|
||||
---
|
||||
hw/qdev-properties.c | 62 ++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
hw/qdev.h | 11 +++++++++
|
||||
2 files changed, 66 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
|
||||
index 217ddc0..9e123ae 100644
|
||||
--- a/hw/qdev-properties.c
|
||||
+++ b/hw/qdev-properties.c
|
||||
@@ -9,6 +9,59 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
+static uint32_t qdev_get_prop_mask(Property *prop)
|
||||
+{
|
||||
+ assert(prop->info->type == PROP_TYPE_BIT);
|
||||
+ return 0x1 << prop->bitnr;
|
||||
+}
|
||||
+
|
||||
+static void bit_prop_set(DeviceState *dev, Property *props, bool val)
|
||||
+{
|
||||
+ uint32_t *p = qdev_get_prop_ptr(dev, props);
|
||||
+ uint32_t mask = qdev_get_prop_mask(props);
|
||||
+ if (val)
|
||||
+ *p |= ~mask;
|
||||
+ else
|
||||
+ *p &= ~mask;
|
||||
+}
|
||||
+
|
||||
+static void qdev_prop_cpy(DeviceState *dev, Property *props, void *src)
|
||||
+{
|
||||
+ if (props->info->type == PROP_TYPE_BIT) {
|
||||
+ bool *defval = src;
|
||||
+ bit_prop_set(dev, props, *defval);
|
||||
+ } else {
|
||||
+ char *dst = qdev_get_prop_ptr(dev, props);
|
||||
+ memcpy(dst, src, props->info->size);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Bit */
|
||||
+static int parse_bit(DeviceState *dev, Property *prop, const char *str)
|
||||
+{
|
||||
+ if (!strncasecmp(str, "on", 2))
|
||||
+ bit_prop_set(dev, prop, true);
|
||||
+ else if (!strncasecmp(str, "off", 3))
|
||||
+ bit_prop_set(dev, prop, false);
|
||||
+ else
|
||||
+ return -1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
+{
|
||||
+ uint8_t *p = qdev_get_prop_ptr(dev, prop);
|
||||
+ return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
|
||||
+}
|
||||
+
|
||||
+PropertyInfo qdev_prop_bit = {
|
||||
+ .name = "on/off",
|
||||
+ .type = PROP_TYPE_BIT,
|
||||
+ .size = sizeof(uint32_t),
|
||||
+ .parse = parse_bit,
|
||||
+ .print = print_bit,
|
||||
+};
|
||||
+
|
||||
/* --- 8bit integer --- */
|
||||
|
||||
static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
|
||||
@@ -511,7 +564,6 @@ int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
|
||||
void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
|
||||
{
|
||||
Property *prop;
|
||||
- void *dst;
|
||||
|
||||
prop = qdev_prop_find(dev, name);
|
||||
if (!prop) {
|
||||
@@ -524,8 +576,7 @@ void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyT
|
||||
__FUNCTION__, dev->info->name, name);
|
||||
abort();
|
||||
}
|
||||
- dst = qdev_get_prop_ptr(dev, prop);
|
||||
- memcpy(dst, src, prop->info->size);
|
||||
+ qdev_prop_cpy(dev, prop, src);
|
||||
}
|
||||
|
||||
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
|
||||
@@ -585,14 +636,11 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
|
||||
|
||||
void qdev_prop_set_defaults(DeviceState *dev, Property *props)
|
||||
{
|
||||
- char *dst;
|
||||
-
|
||||
if (!props)
|
||||
return;
|
||||
while (props->name) {
|
||||
if (props->defval) {
|
||||
- dst = qdev_get_prop_ptr(dev, props);
|
||||
- memcpy(dst, props->defval, props->info->size);
|
||||
+ qdev_prop_cpy(dev, props, props->defval);
|
||||
}
|
||||
props++;
|
||||
}
|
||||
diff --git a/hw/qdev.h b/hw/qdev.h
|
||||
index bbcdba1..07b9603 100644
|
||||
--- a/hw/qdev.h
|
||||
+++ b/hw/qdev.h
|
||||
@@ -64,6 +64,7 @@ struct Property {
|
||||
const char *name;
|
||||
PropertyInfo *info;
|
||||
int offset;
|
||||
+ int bitnr;
|
||||
void *defval;
|
||||
};
|
||||
|
||||
@@ -82,6 +83,7 @@ enum PropertyType {
|
||||
PROP_TYPE_NETDEV,
|
||||
PROP_TYPE_VLAN,
|
||||
PROP_TYPE_PTR,
|
||||
+ PROP_TYPE_BIT,
|
||||
};
|
||||
|
||||
struct PropertyInfo {
|
||||
@@ -173,6 +175,7 @@ void do_device_del(Monitor *mon, const QDict *qdict);
|
||||
|
||||
/*** qdev-properties.c ***/
|
||||
|
||||
+extern PropertyInfo qdev_prop_bit;
|
||||
extern PropertyInfo qdev_prop_uint8;
|
||||
extern PropertyInfo qdev_prop_uint16;
|
||||
extern PropertyInfo qdev_prop_uint32;
|
||||
@@ -202,6 +205,14 @@ extern PropertyInfo qdev_prop_pci_devfn;
|
||||
+ type_check(_type,typeof_field(_state, _field)), \
|
||||
.defval = (_type[]) { _defval }, \
|
||||
}
|
||||
+#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) { \
|
||||
+ .name = (_name), \
|
||||
+ .info = &(qdev_prop_bit), \
|
||||
+ .bitnr = (_bit), \
|
||||
+ .offset = offsetof(_state, _field) \
|
||||
+ + type_check(uint32_t,typeof_field(_state, _field)), \
|
||||
+ .defval = (bool[]) { (_defval) }, \
|
||||
+ }
|
||||
|
||||
#define DEFINE_PROP_UINT8(_n, _s, _f, _d) \
|
||||
DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,24 +0,0 @@
|
||||
Without this fix, guest crashes with drive=virtio.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
(cherry picked from commit dbd483242c2e6dfaacb9fd3d20c333bbdad87243)
|
||||
---
|
||||
hw/qdev-properties.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
|
||||
index 9e123ae..277ff9e 100644
|
||||
--- a/hw/qdev-properties.c
|
||||
+++ b/hw/qdev-properties.c
|
||||
@@ -20,7 +20,7 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val)
|
||||
uint32_t *p = qdev_get_prop_ptr(dev, props);
|
||||
uint32_t mask = qdev_get_prop_mask(props);
|
||||
if (val)
|
||||
- *p |= ~mask;
|
||||
+ *p |= mask;
|
||||
else
|
||||
*p &= ~mask;
|
||||
}
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,37 +0,0 @@
|
||||
will be used by virtio-net for vhost net support
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
net/tap.c | 7 +++++++
|
||||
net/tap.h | 3 +++
|
||||
2 files changed, 10 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/net/tap.c b/net/tap.c
|
||||
index d9f2e41..166cf05 100644
|
||||
--- a/net/tap.c
|
||||
+++ b/net/tap.c
|
||||
@@ -491,3 +491,10 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+struct vhost_net *tap_get_vhost_net(VLANClientState *nc)
|
||||
+{
|
||||
+ TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
+ assert(nc->info->type == NET_CLIENT_TYPE_TAP);
|
||||
+ return s->vhost_net;
|
||||
+}
|
||||
diff --git a/net/tap.h b/net/tap.h
|
||||
index a244b28..b8cec83 100644
|
||||
--- a/net/tap.h
|
||||
+++ b/net/tap.h
|
||||
@@ -50,4 +50,7 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo);
|
||||
|
||||
int tap_get_fd(VLANClientState *vc);
|
||||
|
||||
+struct vhost_net;
|
||||
+struct vhost_net *tap_get_vhost_net(VLANClientState *vc);
|
||||
+
|
||||
#endif /* QEMU_NET_TAP_H */
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,39 +0,0 @@
|
||||
Will be used by vhost to attach/detach to backend.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
net/tap.c | 7 +++++++
|
||||
net/tap.h | 2 ++
|
||||
2 files changed, 9 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/net/tap.c b/net/tap.c
|
||||
index d3492de..7e9ca79 100644
|
||||
--- a/net/tap.c
|
||||
+++ b/net/tap.c
|
||||
@@ -269,6 +269,13 @@ static void tap_poll(VLANClientState *nc, bool enable)
|
||||
tap_write_poll(s, enable);
|
||||
}
|
||||
|
||||
+int tap_get_fd(VLANClientState *nc)
|
||||
+{
|
||||
+ TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
+ assert(nc->info->type == NET_CLIENT_TYPE_TAP);
|
||||
+ return s->fd;
|
||||
+}
|
||||
+
|
||||
/* fd support */
|
||||
|
||||
static NetClientInfo net_tap_info = {
|
||||
diff --git a/net/tap.h b/net/tap.h
|
||||
index 538a562..a244b28 100644
|
||||
--- a/net/tap.h
|
||||
+++ b/net/tap.h
|
||||
@@ -48,4 +48,6 @@ int tap_probe_vnet_hdr(int fd);
|
||||
int tap_probe_has_ufo(int fd);
|
||||
void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo);
|
||||
|
||||
+int tap_get_fd(VLANClientState *vc);
|
||||
+
|
||||
#endif /* QEMU_NET_TAP_H */
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,117 +0,0 @@
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
net.c | 8 ++++++++
|
||||
net/tap.c | 29 +++++++++++++++++++++++++++++
|
||||
qemu-options.hx | 4 +++-
|
||||
3 files changed, 40 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/net.c b/net.c
|
||||
index 6ef93e6..b942d03 100644
|
||||
--- a/net.c
|
||||
+++ b/net.c
|
||||
@@ -976,6 +976,14 @@ static struct {
|
||||
.name = "vnet_hdr",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "enable the IFF_VNET_HDR flag on the tap interface"
|
||||
+ }, {
|
||||
+ .name = "vhost",
|
||||
+ .type = QEMU_OPT_BOOL,
|
||||
+ .help = "enable vhost-net network accelerator",
|
||||
+ }, {
|
||||
+ .name = "vhostfd",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ .help = "file descriptor of an already opened vhost net device",
|
||||
},
|
||||
#endif /* _WIN32 */
|
||||
{ /* end of list */ }
|
||||
diff --git a/net/tap.c b/net/tap.c
|
||||
index 7e9ca79..d9f2e41 100644
|
||||
--- a/net/tap.c
|
||||
+++ b/net/tap.c
|
||||
@@ -41,6 +41,8 @@
|
||||
|
||||
#include "net/tap-linux.h"
|
||||
|
||||
+#include "hw/vhost_net.h"
|
||||
+
|
||||
/* Maximum GSO packet size (64k) plus plenty of room for
|
||||
* the ethernet and virtio_net headers
|
||||
*/
|
||||
@@ -57,6 +59,7 @@ typedef struct TAPState {
|
||||
unsigned int has_vnet_hdr : 1;
|
||||
unsigned int using_vnet_hdr : 1;
|
||||
unsigned int has_ufo: 1;
|
||||
+ struct vhost_net *vhost_net;
|
||||
} TAPState;
|
||||
|
||||
static int launch_script(const char *setup_script, const char *ifname, int fd);
|
||||
@@ -252,6 +255,10 @@ static void tap_cleanup(VLANClientState *nc)
|
||||
{
|
||||
TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
|
||||
+ if (s->vhost_net) {
|
||||
+ vhost_net_cleanup(s->vhost_net);
|
||||
+ }
|
||||
+
|
||||
qemu_purge_queued_packets(nc);
|
||||
|
||||
if (s->down_script[0])
|
||||
@@ -307,6 +314,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
|
||||
s->has_ufo = tap_probe_has_ufo(s->fd);
|
||||
tap_set_offload(&s->nc, 0, 0, 0, 0, 0);
|
||||
tap_read_poll(s, 1);
|
||||
+ s->vhost_net = NULL;
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -456,5 +464,26 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
|
||||
}
|
||||
}
|
||||
|
||||
+ if (qemu_opt_get_bool(opts, "vhost", 0)) {
|
||||
+ int vhostfd, r;
|
||||
+ if (qemu_opt_get(opts, "vhostfd")) {
|
||||
+ r = net_handle_fd_param(mon, qemu_opt_get(opts, "vhostfd"));
|
||||
+ if (r == -1) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ vhostfd = r;
|
||||
+ } else {
|
||||
+ vhostfd = -1;
|
||||
+ }
|
||||
+ s->vhost_net = vhost_net_init(&s->nc, vhostfd);
|
||||
+ if (!s->vhost_net) {
|
||||
+ qemu_error("vhost-net requested but could not be initialized\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ } else if (qemu_opt_get(opts, "vhostfd")) {
|
||||
+ qemu_error("vhostfd= is not valid without vhost\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
diff --git a/qemu-options.hx b/qemu-options.hx
|
||||
index ca73ba5..2b3d9b8 100644
|
||||
--- a/qemu-options.hx
|
||||
+++ b/qemu-options.hx
|
||||
@@ -814,7 +814,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
|
||||
"-net tap[,vlan=n][,name=str],ifname=name\n"
|
||||
" connect the host TAP network interface to VLAN 'n'\n"
|
||||
#else
|
||||
- "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes][,vnet_hdr=on|off]\n"
|
||||
+ "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h]\n"
|
||||
" connect the host TAP network interface to VLAN 'n' and use the\n"
|
||||
" network scripts 'file' (default=%s)\n"
|
||||
" and 'dfile' (default=%s);\n"
|
||||
@@ -824,6 +824,8 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
|
||||
" default of 'sndbuf=1048576' can be disabled using 'sndbuf=0'\n"
|
||||
" use vnet_hdr=off to avoid enabling the IFF_VNET_HDR tap flag; use\n"
|
||||
" vnet_hdr=on to make the lack of IFF_VNET_HDR support an error condition\n"
|
||||
+ " use vhost=on to enable experimental in kernel accelerator\n"
|
||||
+ " use 'vhostfd=h' to connect to an already opened vhost net device\n"
|
||||
#endif
|
||||
"-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n"
|
||||
" connect the vlan 'n' to another VLAN using a socket connection\n"
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,41 +0,0 @@
|
||||
If we go over the maximum number of iovecs support by syscall we get
|
||||
back EINVAL from the kernel which translate to I/O errors for the guest.
|
||||
|
||||
Add a MAX_IOV defintion for platforms that don't have it. For now we use
|
||||
the same 1024 define that's used on Linux and various other platforms,
|
||||
but until the windows block backend implements some kind of vectored I/O
|
||||
it doesn't matter.
|
||||
|
||||
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
||||
|
||||
Index: qemu/block.c
|
||||
===================================================================
|
||||
--- qemu.orig/block.c 2010-01-26 10:59:39.757004445 +0100
|
||||
+++ qemu/block.c 2010-01-26 11:01:38.056023231 +0100
|
||||
@@ -1689,6 +1689,10 @@ static int multiwrite_merge(BlockDriverS
|
||||
merge = bs->drv->bdrv_merge_requests(bs, &reqs[outidx], &reqs[i]);
|
||||
}
|
||||
|
||||
+ if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > IOV_MAX) {
|
||||
+ merge = 0;
|
||||
+ }
|
||||
+
|
||||
if (merge) {
|
||||
size_t size;
|
||||
QEMUIOVector *qiov = qemu_mallocz(sizeof(*qiov));
|
||||
Index: qemu/qemu-common.h
|
||||
===================================================================
|
||||
--- qemu.orig/qemu-common.h 2010-01-26 14:41:40.894254285 +0100
|
||||
+++ qemu/qemu-common.h 2010-01-26 14:42:27.267275698 +0100
|
||||
@@ -54,6 +54,10 @@ struct iovec {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
+/*
|
||||
+ * Use the same value as Linux for now.
|
||||
+ */
|
||||
+#define IOV_MAX 1024
|
||||
#else
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
@ -1,118 +0,0 @@
|
||||
Teach configure to check for vhost.h
|
||||
and disable vhost_net if not present.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>'
|
||||
|
||||
---
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 2ebd30c..38783da 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -168,7 +168,8 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
|
||||
# need to fix this properly
|
||||
obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
|
||||
obj-y += notifier.o
|
||||
-obj-y += vhost_net.o vhost.o
|
||||
+obj-y += vhost_net.o
|
||||
+obj-$(CONFIG_VHOST_NET) += vhost.o
|
||||
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
|
||||
# MSI-X depends on kvm for interrupt injection,
|
||||
# so moved it from Makefile.hw to Makefile.target for now
|
||||
diff --git a/configure b/configure
|
||||
index 88ba002..4994506 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -1510,6 +1510,23 @@ EOF
|
||||
fi
|
||||
|
||||
##########################################
|
||||
+# test for vhost net
|
||||
+
|
||||
+if test "$kvm" != "no"; then
|
||||
+ cat > $TMPC <<EOF
|
||||
+#include <linux/vhost.h>
|
||||
+int main(void) { return 0; }
|
||||
+EOF
|
||||
+ if compile_prog "$kvm_cflags" "" ; then
|
||||
+ vhost_net=yes
|
||||
+ else
|
||||
+ vhost_net=no
|
||||
+ fi
|
||||
+else
|
||||
+ vhost_net=no
|
||||
+fi
|
||||
+
|
||||
+##########################################
|
||||
# libpci probe for kvm_cap_device_assignment
|
||||
if test $kvm_cap_device_assignment = "yes" ; then
|
||||
cat > $TMPC << EOF
|
||||
@@ -2058,6 +2075,7 @@ echo "fdt support $fdt"
|
||||
echo "preadv support $preadv"
|
||||
echo "fdatasync $fdatasync"
|
||||
echo "uuid support $uuid"
|
||||
+echo "vhost-net support $vhost_net"
|
||||
|
||||
if test $sdl_too_old = "yes"; then
|
||||
echo "-> Your SDL version is too old - please upgrade to have SDL support"
|
||||
@@ -2593,6 +2611,9 @@ case "$target_arch2" in
|
||||
if test $kvm_cap_device_assignment = "yes" ; then
|
||||
echo "CONFIG_KVM_DEVICE_ASSIGNMENT=y" >> $config_target_mak
|
||||
fi
|
||||
+ if test $vhost_net = "yes" ; then
|
||||
+ echo "CONFIG_VHOST_NET=y" >> $config_target_mak
|
||||
+ fi
|
||||
fi
|
||||
esac
|
||||
echo "TARGET_PHYS_ADDR_BITS=$target_phys_bits" >> $config_target_mak
|
||||
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
|
||||
index c89ff40..cab9a0a 100644
|
||||
--- a/hw/vhost_net.c
|
||||
+++ b/hw/vhost_net.c
|
||||
@@ -16,9 +16,13 @@
|
||||
#include "net/tap.h"
|
||||
|
||||
#include "virtio-net.h"
|
||||
-#include "vhost.h"
|
||||
#include "vhost_net.h"
|
||||
|
||||
+#include "config.h"
|
||||
+
|
||||
+#ifdef CONFIG_VHOST_NET
|
||||
+#include "vhost.h"
|
||||
+
|
||||
struct vhost_net {
|
||||
struct vhost_dev dev;
|
||||
struct vhost_virtqueue vqs[2];
|
||||
@@ -145,3 +149,31 @@ void vhost_net_cleanup(struct vhost_net *net)
|
||||
qemu_free(net);
|
||||
}
|
||||
/* TODO: log */
|
||||
+#else
|
||||
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+int vhost_net_start(struct vhost_net *net,
|
||||
+ VirtIODevice *dev)
|
||||
+{
|
||||
+ return -ENOSYS;
|
||||
+}
|
||||
+void vhost_net_stop(struct vhost_net *net,
|
||||
+ VirtIODevice *dev)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+void vhost_net_cleanup(struct vhost_net *net)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
|
||||
+{
|
||||
+ return features;
|
||||
+}
|
||||
+void vhost_net_ack_features(struct vhost_net *net, unsigned features)
|
||||
+{
|
||||
+}
|
||||
+#endif
|
@ -1,869 +0,0 @@
|
||||
This adds vhost net support in qemu. Will be tied to tap device and
|
||||
virtio by following patches. Raw backend is currently missing, will be
|
||||
worked on/submitted separately.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
Makefile.target | 1 +
|
||||
hw/vhost.c | 603 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
hw/vhost.h | 44 ++++
|
||||
hw/vhost_net.c | 147 ++++++++++++++
|
||||
hw/vhost_net.h | 20 ++
|
||||
5 files changed, 815 insertions(+), 0 deletions(-)
|
||||
create mode 100644 hw/vhost.c
|
||||
create mode 100644 hw/vhost.h
|
||||
create mode 100644 hw/vhost_net.c
|
||||
create mode 100644 hw/vhost_net.h
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 0c844a9..2ebd30c 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -168,6 +168,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
|
||||
# need to fix this properly
|
||||
obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
|
||||
obj-y += notifier.o
|
||||
+obj-y += vhost_net.o vhost.o
|
||||
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
|
||||
# MSI-X depends on kvm for interrupt injection,
|
||||
# so moved it from Makefile.hw to Makefile.target for now
|
||||
diff --git a/hw/vhost.c b/hw/vhost.c
|
||||
new file mode 100644
|
||||
index 0000000..e5c1ead
|
||||
--- /dev/null
|
||||
+++ b/hw/vhost.c
|
||||
@@ -0,0 +1,603 @@
|
||||
+#include "linux/vhost.h"
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <sys/eventfd.h>
|
||||
+#include "vhost.h"
|
||||
+#include "hw/hw.h"
|
||||
+/* For range_get_last */
|
||||
+#include "pci.h"
|
||||
+
|
||||
+static void vhost_dev_sync_region(struct vhost_dev *dev,
|
||||
+ uint64_t mfirst, uint64_t mlast,
|
||||
+ uint64_t rfirst, uint64_t rlast)
|
||||
+{
|
||||
+ uint64_t start = MAX(mfirst, rfirst);
|
||||
+ uint64_t end = MIN(mlast, rlast);
|
||||
+ vhost_log_chunk_t *from = dev->log + start / VHOST_LOG_CHUNK;
|
||||
+ vhost_log_chunk_t *to = dev->log + end / VHOST_LOG_CHUNK + 1;
|
||||
+ uint64_t addr = (start / VHOST_LOG_CHUNK) * VHOST_LOG_CHUNK;
|
||||
+
|
||||
+ assert(end / VHOST_LOG_CHUNK < dev->log_size);
|
||||
+ assert(start / VHOST_LOG_CHUNK < dev->log_size);
|
||||
+ if (end < start) {
|
||||
+ return;
|
||||
+ }
|
||||
+ for (;from < to; ++from) {
|
||||
+ vhost_log_chunk_t log;
|
||||
+ int bit;
|
||||
+ /* We first check with non-atomic: much cheaper,
|
||||
+ * and we expect non-dirty to be the common case. */
|
||||
+ if (!*from) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ /* Data must be read atomically. We don't really
|
||||
+ * need the barrier semantics of __sync
|
||||
+ * builtins, but it's easier to use them than
|
||||
+ * roll our own. */
|
||||
+ log = __sync_fetch_and_and(from, 0);
|
||||
+ while ((bit = sizeof(log) > sizeof(int) ?
|
||||
+ ffsll(log) : ffs(log))) {
|
||||
+ bit -= 1;
|
||||
+ cpu_physical_memory_set_dirty(addr + bit * VHOST_LOG_PAGE);
|
||||
+ log &= ~(0x1ull << bit);
|
||||
+ }
|
||||
+ addr += VHOST_LOG_CHUNK;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int vhost_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,
|
||||
+ target_phys_addr_t start_addr,
|
||||
+ target_phys_addr_t end_addr)
|
||||
+{
|
||||
+ struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
|
||||
+ int i;
|
||||
+ if (!dev->log_enabled || !dev->started) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ for (i = 0; i < dev->mem->nregions; ++i) {
|
||||
+ struct vhost_memory_region *reg = dev->mem->regions + i;
|
||||
+ vhost_dev_sync_region(dev, start_addr, end_addr,
|
||||
+ reg->guest_phys_addr,
|
||||
+ range_get_last(reg->guest_phys_addr,
|
||||
+ reg->memory_size));
|
||||
+ }
|
||||
+ for (i = 0; i < dev->nvqs; ++i) {
|
||||
+ struct vhost_virtqueue *vq = dev->vqs + i;
|
||||
+ unsigned size = sizeof(struct vring_used_elem) * vq->num;
|
||||
+ vhost_dev_sync_region(dev, start_addr, end_addr, vq->used_phys,
|
||||
+ range_get_last(vq->used_phys, size));
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Assign/unassign. Keep an unsorted array of non-overlapping
|
||||
+ * memory regions in dev->mem. */
|
||||
+static void vhost_dev_unassign_memory(struct vhost_dev *dev,
|
||||
+ uint64_t start_addr,
|
||||
+ uint64_t size)
|
||||
+{
|
||||
+ int from, to, n = dev->mem->nregions;
|
||||
+ /* Track overlapping/split regions for sanity checking. */
|
||||
+ int overlap_start = 0, overlap_end = 0, overlap_middle = 0, split = 0;
|
||||
+
|
||||
+ for (from = 0, to = 0; from < n; ++from, ++to) {
|
||||
+ struct vhost_memory_region *reg = dev->mem->regions + to;
|
||||
+ uint64_t reglast;
|
||||
+ uint64_t memlast;
|
||||
+ uint64_t change;
|
||||
+
|
||||
+ /* clone old region */
|
||||
+ if (to != from) {
|
||||
+ memcpy(reg, dev->mem->regions + from, sizeof *reg);
|
||||
+ }
|
||||
+
|
||||
+ /* No overlap is simple */
|
||||
+ if (!ranges_overlap(reg->guest_phys_addr, reg->memory_size,
|
||||
+ start_addr, size)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Split only happens if supplied region
|
||||
+ * is in the middle of an existing one. Thus it can not
|
||||
+ * overlap with any other existing region. */
|
||||
+ assert(!split);
|
||||
+
|
||||
+ reglast = range_get_last(reg->guest_phys_addr, reg->memory_size);
|
||||
+ memlast = range_get_last(start_addr, size);
|
||||
+
|
||||
+ /* Remove whole region */
|
||||
+ if (start_addr <= reg->guest_phys_addr && memlast >= reglast) {
|
||||
+ --dev->mem->nregions;
|
||||
+ --to;
|
||||
+ assert(to >= 0);
|
||||
+ ++overlap_middle;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Shrink region */
|
||||
+ if (memlast >= reglast) {
|
||||
+ reg->memory_size = start_addr - reg->guest_phys_addr;
|
||||
+ assert(reg->memory_size);
|
||||
+ assert(!overlap_end);
|
||||
+ ++overlap_end;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Shift region */
|
||||
+ if (start_addr <= reg->guest_phys_addr) {
|
||||
+ change = memlast + 1 - reg->guest_phys_addr;
|
||||
+ reg->memory_size -= change;
|
||||
+ reg->guest_phys_addr += change;
|
||||
+ reg->userspace_addr += change;
|
||||
+ assert(reg->memory_size);
|
||||
+ assert(!overlap_start);
|
||||
+ ++overlap_start;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* This only happens if supplied region
|
||||
+ * is in the middle of an existing one. Thus it can not
|
||||
+ * overlap with any other existing region. */
|
||||
+ assert(!overlap_start);
|
||||
+ assert(!overlap_end);
|
||||
+ assert(!overlap_middle);
|
||||
+ /* Split region: shrink first part, shift second part. */
|
||||
+ memcpy(dev->mem->regions + n, reg, sizeof *reg);
|
||||
+ reg->memory_size = start_addr - reg->guest_phys_addr;
|
||||
+ assert(reg->memory_size);
|
||||
+ change = memlast + 1 - reg->guest_phys_addr;
|
||||
+ reg = dev->mem->regions + n;
|
||||
+ reg->memory_size -= change;
|
||||
+ assert(reg->memory_size);
|
||||
+ reg->guest_phys_addr += change;
|
||||
+ reg->userspace_addr += change;
|
||||
+ /* Never add more than 1 region */
|
||||
+ assert(dev->mem->nregions == n);
|
||||
+ ++dev->mem->nregions;
|
||||
+ ++split;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Called after unassign, so no regions overlap the given range. */
|
||||
+static void vhost_dev_assign_memory(struct vhost_dev *dev,
|
||||
+ uint64_t start_addr,
|
||||
+ uint64_t size,
|
||||
+ uint64_t uaddr)
|
||||
+{
|
||||
+ int from, to;
|
||||
+ struct vhost_memory_region *merged = NULL;
|
||||
+ for (from = 0, to = 0; from < dev->mem->nregions; ++from, ++to) {
|
||||
+ struct vhost_memory_region *reg = dev->mem->regions + to;
|
||||
+ uint64_t prlast, urlast;
|
||||
+ uint64_t pmlast, umlast;
|
||||
+ uint64_t s, e, u;
|
||||
+
|
||||
+ /* clone old region */
|
||||
+ if (to != from) {
|
||||
+ memcpy(reg, dev->mem->regions + from, sizeof *reg);
|
||||
+ }
|
||||
+ prlast = range_get_last(reg->guest_phys_addr, reg->memory_size);
|
||||
+ pmlast = range_get_last(start_addr, size);
|
||||
+ urlast = range_get_last(reg->userspace_addr, reg->memory_size);
|
||||
+ umlast = range_get_last(uaddr, size);
|
||||
+
|
||||
+ /* check for overlapping regions: should never happen. */
|
||||
+ assert(prlast < start_addr || pmlast < reg->guest_phys_addr);
|
||||
+ /* Not an adjacent or overlapping region - do not merge. */
|
||||
+ if ((prlast + 1 != start_addr || urlast + 1 != uaddr) &&
|
||||
+ (pmlast + 1 != reg->guest_phys_addr ||
|
||||
+ umlast + 1 != reg->userspace_addr)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (merged) {
|
||||
+ --to;
|
||||
+ assert(to >= 0);
|
||||
+ } else {
|
||||
+ merged = reg;
|
||||
+ }
|
||||
+ u = MIN(uaddr, reg->userspace_addr);
|
||||
+ s = MIN(start_addr, reg->guest_phys_addr);
|
||||
+ e = MAX(pmlast, prlast);
|
||||
+ uaddr = merged->userspace_addr = u;
|
||||
+ start_addr = merged->guest_phys_addr = s;
|
||||
+ size = merged->memory_size = e - s + 1;
|
||||
+ assert(merged->memory_size);
|
||||
+ }
|
||||
+
|
||||
+ if (!merged) {
|
||||
+ struct vhost_memory_region *reg = dev->mem->regions + to;
|
||||
+ memset(reg, 0, sizeof *reg);
|
||||
+ reg->memory_size = size;
|
||||
+ assert(reg->memory_size);
|
||||
+ reg->guest_phys_addr = start_addr;
|
||||
+ reg->userspace_addr = uaddr;
|
||||
+ ++to;
|
||||
+ }
|
||||
+ assert(to <= dev->mem->nregions + 1);
|
||||
+ dev->mem->nregions = to;
|
||||
+}
|
||||
+
|
||||
+static uint64_t vhost_get_log_size(struct vhost_dev *dev)
|
||||
+{
|
||||
+ uint64_t log_size = 0;
|
||||
+ int i;
|
||||
+ for (i = 0; i < dev->mem->nregions; ++i) {
|
||||
+ struct vhost_memory_region *reg = dev->mem->regions + i;
|
||||
+ uint64_t last = range_get_last(reg->guest_phys_addr,
|
||||
+ reg->memory_size);
|
||||
+ log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
|
||||
+ }
|
||||
+ for (i = 0; i < dev->nvqs; ++i) {
|
||||
+ struct vhost_virtqueue *vq = dev->vqs + i;
|
||||
+ uint64_t last = vq->used_phys +
|
||||
+ sizeof(struct vring_used_elem) * vq->num - 1;
|
||||
+ log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
|
||||
+ }
|
||||
+ return log_size;
|
||||
+}
|
||||
+
|
||||
+static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
|
||||
+{
|
||||
+ vhost_log_chunk_t *log;
|
||||
+ int r;
|
||||
+ if (size) {
|
||||
+ log = qemu_mallocz(size * sizeof *log);
|
||||
+ } else {
|
||||
+ log = NULL;
|
||||
+ }
|
||||
+ r = ioctl(dev->control, VHOST_SET_LOG_BASE,
|
||||
+ (uint64_t)(unsigned long)log);
|
||||
+ assert(r >= 0);
|
||||
+ vhost_client_sync_dirty_bitmap(&dev->client, 0,
|
||||
+ (target_phys_addr_t)~0x0ull);
|
||||
+ if (dev->log) {
|
||||
+ qemu_free(dev->log);
|
||||
+ }
|
||||
+ dev->log = log;
|
||||
+ dev->log_size = size;
|
||||
+}
|
||||
+
|
||||
+static void vhost_client_set_memory(CPUPhysMemoryClient *client,
|
||||
+ target_phys_addr_t start_addr,
|
||||
+ ram_addr_t size,
|
||||
+ ram_addr_t phys_offset)
|
||||
+{
|
||||
+ struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
|
||||
+ ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
|
||||
+ int s = offsetof(struct vhost_memory, regions) +
|
||||
+ (dev->mem->nregions + 1) * sizeof dev->mem->regions[0];
|
||||
+ uint64_t log_size;
|
||||
+ int r;
|
||||
+ dev->mem = qemu_realloc(dev->mem, s);
|
||||
+
|
||||
+ assert(size);
|
||||
+
|
||||
+ vhost_dev_unassign_memory(dev, start_addr, size);
|
||||
+ if (flags == IO_MEM_RAM) {
|
||||
+ /* Add given mapping, merging adjacent regions if any */
|
||||
+ vhost_dev_assign_memory(dev, start_addr, size,
|
||||
+ (uintptr_t)qemu_get_ram_ptr(phys_offset));
|
||||
+ } else {
|
||||
+ /* Remove old mapping for this memory, if any. */
|
||||
+ vhost_dev_unassign_memory(dev, start_addr, size);
|
||||
+ }
|
||||
+
|
||||
+ if (!dev->started) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!dev->log_enabled) {
|
||||
+ r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem);
|
||||
+ assert(r >= 0);
|
||||
+ return;
|
||||
+ }
|
||||
+ log_size = vhost_get_log_size(dev);
|
||||
+ /* We allocate an extra 4K bytes to log,
|
||||
+ * to reduce the * number of reallocations. */
|
||||
+#define VHOST_LOG_BUFFER (0x1000 / sizeof *dev->log)
|
||||
+ /* To log more, must increase log size before table update. */
|
||||
+ if (dev->log_size < log_size) {
|
||||
+ vhost_dev_log_resize(dev, log_size + VHOST_LOG_BUFFER);
|
||||
+ }
|
||||
+ r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem);
|
||||
+ assert(r >= 0);
|
||||
+ /* To log less, can only decrease log size after table update. */
|
||||
+ if (dev->log_size > log_size + VHOST_LOG_BUFFER) {
|
||||
+ vhost_dev_log_resize(dev, log_size);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
|
||||
+{
|
||||
+ uint64_t features = dev->acked_features;
|
||||
+ int r;
|
||||
+ if (dev->log_enabled) {
|
||||
+ features |= 0x1 << VHOST_F_LOG_ALL;
|
||||
+ }
|
||||
+ r = ioctl(dev->control, VHOST_SET_FEATURES, &features);
|
||||
+ return r < 0 ? -errno : 0;
|
||||
+}
|
||||
+
|
||||
+static int vhost_client_migration_log(struct CPUPhysMemoryClient *client,
|
||||
+ int enable)
|
||||
+{
|
||||
+ struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
|
||||
+ int r;
|
||||
+ if (!!enable == dev->log_enabled) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (!dev->started) {
|
||||
+ dev->log_enabled = enable;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (!enable) {
|
||||
+ r = vhost_dev_set_log(dev, false);
|
||||
+ if (r < 0) {
|
||||
+ return r;
|
||||
+ }
|
||||
+ if (dev->log) {
|
||||
+ qemu_free(dev->log);
|
||||
+ }
|
||||
+ dev->log = NULL;
|
||||
+ dev->log_size = 0;
|
||||
+ } else {
|
||||
+ vhost_dev_log_resize(dev, vhost_get_log_size(dev));
|
||||
+ r = vhost_dev_set_log(dev, false);
|
||||
+ if (r < 0) {
|
||||
+ return r;
|
||||
+ }
|
||||
+ }
|
||||
+ dev->log_enabled = enable;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
|
||||
+ struct vhost_virtqueue *vq,
|
||||
+ unsigned idx, bool enable_log)
|
||||
+{
|
||||
+ struct vhost_vring_addr addr = {
|
||||
+ .index = idx,
|
||||
+ .desc_user_addr = (u_int64_t)(unsigned long)vq->desc,
|
||||
+ .avail_user_addr = (u_int64_t)(unsigned long)vq->avail,
|
||||
+ .used_user_addr = (u_int64_t)(unsigned long)vq->used,
|
||||
+ .log_guest_addr = vq->used_phys,
|
||||
+ .flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0,
|
||||
+ };
|
||||
+ int r = ioctl(dev->control, VHOST_SET_VRING_ADDR, &addr);
|
||||
+ if (r < 0) {
|
||||
+ return -errno;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vhost_virtqueue_init(struct vhost_dev *dev,
|
||||
+ struct VirtIODevice *vdev,
|
||||
+ struct vhost_virtqueue *vq,
|
||||
+ unsigned idx)
|
||||
+{
|
||||
+ target_phys_addr_t s, l, a;
|
||||
+ int r;
|
||||
+ struct vhost_vring_file file = {
|
||||
+ .index = idx,
|
||||
+ };
|
||||
+ struct vhost_vring_state state = {
|
||||
+ .index = idx,
|
||||
+ };
|
||||
+ struct VirtQueue *q = virtio_queue(vdev, idx);
|
||||
+
|
||||
+ vq->num = state.num = virtio_queue_get_num(vdev, idx);
|
||||
+ r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state);
|
||||
+ if (r) {
|
||||
+ return -errno;
|
||||
+ }
|
||||
+
|
||||
+ state.num = virtio_queue_last_avail_idx(vdev, idx);
|
||||
+ r = ioctl(dev->control, VHOST_SET_VRING_BASE, &state);
|
||||
+ if (r) {
|
||||
+ return -errno;
|
||||
+ }
|
||||
+
|
||||
+ s = l = sizeof(struct vring_desc) * vq->num;
|
||||
+ a = virtio_queue_get_desc(vdev, idx);
|
||||
+ vq->desc = cpu_physical_memory_map(a, &l, 0);
|
||||
+ if (!vq->desc || l != s) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto fail_alloc;
|
||||
+ }
|
||||
+ s = l = offsetof(struct vring_avail, ring) +
|
||||
+ sizeof(u_int64_t) * vq->num;
|
||||
+ a = virtio_queue_get_avail(vdev, idx);
|
||||
+ vq->avail = cpu_physical_memory_map(a, &l, 0);
|
||||
+ if (!vq->avail || l != s) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto fail_alloc;
|
||||
+ }
|
||||
+ s = l = offsetof(struct vring_used, ring) +
|
||||
+ sizeof(struct vring_used_elem) * vq->num;
|
||||
+ vq->used_phys = a = virtio_queue_get_used(vdev, idx);
|
||||
+ vq->used = cpu_physical_memory_map(a, &l, 1);
|
||||
+ if (!vq->used || l != s) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto fail_alloc;
|
||||
+ }
|
||||
+
|
||||
+ r = vhost_virtqueue_set_addr(dev, vq, idx, dev->log_enabled);
|
||||
+ if (r < 0) {
|
||||
+ r = -errno;
|
||||
+ goto fail_alloc;
|
||||
+ }
|
||||
+ if (!vdev->binding->guest_notifier || !vdev->binding->host_notifier) {
|
||||
+ fprintf(stderr, "binding does not support irqfd/queuefd\n");
|
||||
+ r = -ENOSYS;
|
||||
+ goto fail_alloc;
|
||||
+ }
|
||||
+ r = vdev->binding->guest_notifier(vdev->binding_opaque, idx, true);
|
||||
+ if (r < 0) {
|
||||
+ fprintf(stderr, "Error binding guest notifier: %d\n", -r);
|
||||
+ goto fail_guest_notifier;
|
||||
+ }
|
||||
+
|
||||
+ r = vdev->binding->host_notifier(vdev->binding_opaque, idx, true);
|
||||
+ if (r < 0) {
|
||||
+ fprintf(stderr, "Error binding host notifier: %d\n", -r);
|
||||
+ goto fail_host_notifier;
|
||||
+ }
|
||||
+
|
||||
+ file.fd = event_notifier_get_fd(virtio_queue_host_notifier(q));
|
||||
+ r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file);
|
||||
+ if (r) {
|
||||
+ goto fail_kick;
|
||||
+ }
|
||||
+
|
||||
+ file.fd = event_notifier_get_fd(virtio_queue_guest_notifier(q));
|
||||
+ r = ioctl(dev->control, VHOST_SET_VRING_CALL, &file);
|
||||
+ if (r) {
|
||||
+ goto fail_call;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+fail_call:
|
||||
+fail_kick:
|
||||
+ vdev->binding->host_notifier(vdev->binding_opaque, idx, false);
|
||||
+fail_host_notifier:
|
||||
+ vdev->binding->guest_notifier(vdev->binding_opaque, idx, false);
|
||||
+fail_guest_notifier:
|
||||
+fail_alloc:
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+static void vhost_virtqueue_cleanup(struct vhost_dev *dev,
|
||||
+ struct VirtIODevice *vdev,
|
||||
+ struct vhost_virtqueue *vq,
|
||||
+ unsigned idx)
|
||||
+{
|
||||
+ struct vhost_vring_state state = {
|
||||
+ .index = idx,
|
||||
+ };
|
||||
+ int r;
|
||||
+ r = vdev->binding->guest_notifier(vdev->binding_opaque, idx, false);
|
||||
+ if (r < 0) {
|
||||
+ fprintf(stderr, "vhost VQ %d guest cleanup failed: %d\n", idx, r);
|
||||
+ fflush(stderr);
|
||||
+ }
|
||||
+ assert (r >= 0);
|
||||
+
|
||||
+ r = vdev->binding->host_notifier(vdev->binding_opaque, idx, false);
|
||||
+ if (r < 0) {
|
||||
+ fprintf(stderr, "vhost VQ %d host cleanup failed: %d\n", idx, r);
|
||||
+ fflush(stderr);
|
||||
+ }
|
||||
+ assert (r >= 0);
|
||||
+ r = ioctl(dev->control, VHOST_GET_VRING_BASE, &state);
|
||||
+ if (r < 0) {
|
||||
+ fprintf(stderr, "vhost VQ %d ring restore failed: %d\n", idx, r);
|
||||
+ fflush(stderr);
|
||||
+ }
|
||||
+ virtio_queue_set_last_avail_idx(vdev, idx, state.num);
|
||||
+ assert (r >= 0);
|
||||
+}
|
||||
+
|
||||
+int vhost_dev_init(struct vhost_dev *hdev, int devfd)
|
||||
+{
|
||||
+ uint64_t features;
|
||||
+ int r;
|
||||
+ if (devfd >= 0) {
|
||||
+ hdev->control = devfd;
|
||||
+ } else {
|
||||
+ hdev->control = open("/dev/vhost-net", O_RDWR);
|
||||
+ if (hdev->control < 0)
|
||||
+ return -errno;
|
||||
+ }
|
||||
+ r = ioctl(hdev->control, VHOST_SET_OWNER, NULL);
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
+
|
||||
+ r = ioctl(hdev->control, VHOST_GET_FEATURES, &features);
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
+ hdev->features = features;
|
||||
+
|
||||
+ hdev->client.set_memory = vhost_client_set_memory;
|
||||
+ hdev->client.sync_dirty_bitmap = vhost_client_sync_dirty_bitmap;
|
||||
+ hdev->client.migration_log = vhost_client_migration_log;
|
||||
+ hdev->mem = qemu_mallocz(offsetof(struct vhost_memory, regions));
|
||||
+ hdev->log = NULL;
|
||||
+ hdev->log_size = 0;
|
||||
+ hdev->log_enabled = false;
|
||||
+ hdev->started = false;
|
||||
+ cpu_register_phys_memory_client(&hdev->client);
|
||||
+ return 0;
|
||||
+fail:
|
||||
+ r = -errno;
|
||||
+ close(hdev->control);
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+void vhost_dev_cleanup(struct vhost_dev *hdev)
|
||||
+{
|
||||
+ cpu_unregister_phys_memory_client(&hdev->client);
|
||||
+ qemu_free(hdev->mem);
|
||||
+ close(hdev->control);
|
||||
+}
|
||||
+
|
||||
+int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
|
||||
+{
|
||||
+ int i, r;
|
||||
+
|
||||
+ r = vhost_dev_set_log(hdev, hdev->log_enabled);
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
+ r = ioctl(hdev->control, VHOST_SET_MEM_TABLE, hdev->mem);
|
||||
+ if (r < 0) {
|
||||
+ r = -errno;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ if (hdev->log_enabled) {
|
||||
+ hdev->log_size = vhost_get_log_size(hdev);
|
||||
+ hdev->log = hdev->log_size ?
|
||||
+ qemu_mallocz(hdev->log_size * sizeof *hdev->log) : NULL;
|
||||
+ r = ioctl(hdev->control, VHOST_SET_LOG_BASE,
|
||||
+ (uint64_t)(unsigned long)hdev->log);
|
||||
+ if (r < 0) {
|
||||
+ r = -errno;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < hdev->nvqs; ++i) {
|
||||
+ r = vhost_virtqueue_init(hdev,
|
||||
+ vdev,
|
||||
+ hdev->vqs + i,
|
||||
+ i);
|
||||
+ if (r < 0)
|
||||
+ goto fail_vq;
|
||||
+ }
|
||||
+ hdev->started = true;
|
||||
+
|
||||
+ return 0;
|
||||
+fail_vq:
|
||||
+ while (--i >= 0) {
|
||||
+ vhost_virtqueue_cleanup(hdev,
|
||||
+ vdev,
|
||||
+ hdev->vqs + i,
|
||||
+ i);
|
||||
+ }
|
||||
+fail:
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
|
||||
+{
|
||||
+ int i;
|
||||
+ for (i = 0; i < hdev->nvqs; ++i) {
|
||||
+ vhost_virtqueue_cleanup(hdev,
|
||||
+ vdev,
|
||||
+ hdev->vqs + i,
|
||||
+ i);
|
||||
+ }
|
||||
+ vhost_client_sync_dirty_bitmap(&hdev->client, 0,
|
||||
+ (target_phys_addr_t)~0x0ull);
|
||||
+ hdev->started = false;
|
||||
+ qemu_free(hdev->log);
|
||||
+ hdev->log_size = 0;
|
||||
+}
|
||||
diff --git a/hw/vhost.h b/hw/vhost.h
|
||||
new file mode 100644
|
||||
index 0000000..2ed3933
|
||||
--- /dev/null
|
||||
+++ b/hw/vhost.h
|
||||
@@ -0,0 +1,44 @@
|
||||
+#ifndef VHOST_H
|
||||
+#define VHOST_H
|
||||
+
|
||||
+#include "hw/hw.h"
|
||||
+#include "hw/virtio.h"
|
||||
+
|
||||
+/* Generic structures common for any vhost based device. */
|
||||
+struct vhost_virtqueue {
|
||||
+ int kick;
|
||||
+ int call;
|
||||
+ void *desc;
|
||||
+ void *avail;
|
||||
+ void *used;
|
||||
+ int num;
|
||||
+ unsigned long long used_phys;
|
||||
+};
|
||||
+
|
||||
+typedef unsigned long vhost_log_chunk_t;
|
||||
+#define VHOST_LOG_PAGE 0x1000
|
||||
+#define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t))
|
||||
+#define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS)
|
||||
+
|
||||
+struct vhost_memory;
|
||||
+struct vhost_dev {
|
||||
+ CPUPhysMemoryClient client;
|
||||
+ int control;
|
||||
+ struct vhost_memory *mem;
|
||||
+ struct vhost_virtqueue *vqs;
|
||||
+ int nvqs;
|
||||
+ unsigned long long features;
|
||||
+ unsigned long long acked_features;
|
||||
+ unsigned long long backend_features;
|
||||
+ bool started;
|
||||
+ bool log_enabled;
|
||||
+ vhost_log_chunk_t *log;
|
||||
+ unsigned long long log_size;
|
||||
+};
|
||||
+
|
||||
+int vhost_dev_init(struct vhost_dev *hdev, int devfd);
|
||||
+void vhost_dev_cleanup(struct vhost_dev *hdev);
|
||||
+int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
|
||||
+void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
|
||||
+
|
||||
+#endif
|
||||
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
|
||||
new file mode 100644
|
||||
index 0000000..c89ff40
|
||||
--- /dev/null
|
||||
+++ b/hw/vhost_net.c
|
||||
@@ -0,0 +1,147 @@
|
||||
+#include <sys/eventfd.h>
|
||||
+#include <sys/socket.h>
|
||||
+#include <linux/kvm.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <linux/vhost.h>
|
||||
+#include <linux/virtio_ring.h>
|
||||
+#include <netpacket/packet.h>
|
||||
+#include <net/ethernet.h>
|
||||
+#include <net/if.h>
|
||||
+#include <netinet/in.h>
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+#include "net.h"
|
||||
+#include "net/tap.h"
|
||||
+
|
||||
+#include "virtio-net.h"
|
||||
+#include "vhost.h"
|
||||
+#include "vhost_net.h"
|
||||
+
|
||||
+struct vhost_net {
|
||||
+ struct vhost_dev dev;
|
||||
+ struct vhost_virtqueue vqs[2];
|
||||
+ int backend;
|
||||
+ VLANClientState *vc;
|
||||
+};
|
||||
+
|
||||
+unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
|
||||
+{
|
||||
+ /* Clear features not supported by host kernel. */
|
||||
+ if (!(net->dev.features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)))
|
||||
+ features &= ~(1 << VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
+ if (!(net->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC)))
|
||||
+ features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
|
||||
+ if (!(net->dev.features & (1 << VIRTIO_NET_F_MRG_RXBUF)))
|
||||
+ features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
|
||||
+ return features;
|
||||
+}
|
||||
+
|
||||
+void vhost_net_ack_features(struct vhost_net *net, unsigned features)
|
||||
+{
|
||||
+ net->dev.acked_features = net->dev.backend_features;
|
||||
+ if (features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY))
|
||||
+ net->dev.acked_features |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
+ if (features & (1 << VIRTIO_RING_F_INDIRECT_DESC))
|
||||
+ net->dev.acked_features |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
|
||||
+}
|
||||
+
|
||||
+static int vhost_net_get_fd(VLANClientState *backend)
|
||||
+{
|
||||
+ switch (backend->info->type) {
|
||||
+ case NET_CLIENT_TYPE_TAP:
|
||||
+ return tap_get_fd(backend);
|
||||
+ default:
|
||||
+ fprintf(stderr, "vhost-net requires tap backend\n");
|
||||
+ return -EBADFD;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
|
||||
+{
|
||||
+ int r;
|
||||
+ struct vhost_net *net = qemu_malloc(sizeof *net);
|
||||
+ if (!backend) {
|
||||
+ fprintf(stderr, "vhost-net requires backend to be setup\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ r = vhost_net_get_fd(backend);
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
+ net->vc = backend;
|
||||
+ net->dev.backend_features = tap_has_vnet_hdr(backend) ? 0 :
|
||||
+ (1 << VHOST_NET_F_VIRTIO_NET_HDR);
|
||||
+ net->backend = r;
|
||||
+
|
||||
+ r = vhost_dev_init(&net->dev, devfd);
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
+ if (~net->dev.features & net->dev.backend_features) {
|
||||
+ fprintf(stderr, "vhost lacks feature mask %llu for backend\n",
|
||||
+ ~net->dev.features & net->dev.backend_features);
|
||||
+ vhost_dev_cleanup(&net->dev);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* Set sane init value. Override when guest acks. */
|
||||
+ vhost_net_ack_features(net, 0);
|
||||
+ return net;
|
||||
+fail:
|
||||
+ qemu_free(net);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+int vhost_net_start(struct vhost_net *net,
|
||||
+ VirtIODevice *dev)
|
||||
+{
|
||||
+ struct vhost_vring_file file = { };
|
||||
+ int r;
|
||||
+
|
||||
+ net->dev.nvqs = 2;
|
||||
+ net->dev.vqs = net->vqs;
|
||||
+ r = vhost_dev_start(&net->dev, dev);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ net->vc->info->poll(net->vc, false);
|
||||
+ qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
|
||||
+ file.fd = net->backend;
|
||||
+ for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
|
||||
+ r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
|
||||
+ if (r < 0) {
|
||||
+ r = -errno;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+fail:
|
||||
+ file.fd = -1;
|
||||
+ while (--file.index >= 0) {
|
||||
+ int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
|
||||
+ assert(r >= 0);
|
||||
+ }
|
||||
+ net->vc->info->poll(net->vc, true);
|
||||
+ vhost_dev_stop(&net->dev, dev);
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+void vhost_net_stop(struct vhost_net *net,
|
||||
+ VirtIODevice *dev)
|
||||
+{
|
||||
+ struct vhost_vring_file file = { .fd = -1 };
|
||||
+
|
||||
+ for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
|
||||
+ int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
|
||||
+ assert(r >= 0);
|
||||
+ }
|
||||
+ net->vc->info->poll(net->vc, true);
|
||||
+ vhost_dev_stop(&net->dev, dev);
|
||||
+}
|
||||
+
|
||||
+void vhost_net_cleanup(struct vhost_net *net)
|
||||
+{
|
||||
+ vhost_dev_cleanup(&net->dev);
|
||||
+ qemu_free(net);
|
||||
+}
|
||||
+/* TODO: log */
|
||||
diff --git a/hw/vhost_net.h b/hw/vhost_net.h
|
||||
new file mode 100644
|
||||
index 0000000..21f0277
|
||||
--- /dev/null
|
||||
+++ b/hw/vhost_net.h
|
||||
@@ -0,0 +1,20 @@
|
||||
+#ifndef VHOST_NET_H
|
||||
+#define VHOST_NET_H
|
||||
+
|
||||
+#include "net.h"
|
||||
+
|
||||
+struct vhost_net;
|
||||
+
|
||||
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd);
|
||||
+
|
||||
+int vhost_net_start(struct vhost_net *net,
|
||||
+ VirtIODevice *dev);
|
||||
+void vhost_net_stop(struct vhost_net *net,
|
||||
+ VirtIODevice *dev);
|
||||
+
|
||||
+void vhost_net_cleanup(struct vhost_net *net);
|
||||
+
|
||||
+unsigned vhost_net_get_features(struct vhost_net *net, unsigned features);
|
||||
+void vhost_net_ack_features(struct vhost_net *net, unsigned features);
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,47 +0,0 @@
|
||||
From c11631e8bc91a1d1be2b89196e886a1385820dfb Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Wed, 20 Jan 2010 00:36:51 +0530
|
||||
Subject: [PATCH 1/9] virtio: Remove duplicate macro definition for max. virtqueues, bump up the max
|
||||
|
||||
VIRTIO_PCI_QUEUE_MAX is redefined in hw/virtio.c. Let's just keep it in
|
||||
hw/virtio.h.
|
||||
|
||||
Also, bump up the value of the maximum allowed virtqueues to 64. This is
|
||||
in preparation to allow multiple ports per virtio-console device.
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
hw/virtio.c | 2 --
|
||||
hw/virtio.h | 2 +-
|
||||
2 files changed, 1 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio.c b/hw/virtio.c
|
||||
index cecd0dc..88f4e78 100644
|
||||
--- a/hw/virtio.c
|
||||
+++ b/hw/virtio.c
|
||||
@@ -75,8 +75,6 @@ struct VirtQueue
|
||||
void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
|
||||
};
|
||||
|
||||
-#define VIRTIO_PCI_QUEUE_MAX 16
|
||||
-
|
||||
/* virt queue functions */
|
||||
static void virtqueue_init(VirtQueue *vq)
|
||||
{
|
||||
diff --git a/hw/virtio.h b/hw/virtio.h
|
||||
index 35532a6..051910a 100644
|
||||
--- a/hw/virtio.h
|
||||
+++ b/hw/virtio.h
|
||||
@@ -90,7 +90,7 @@ typedef struct {
|
||||
unsigned (*get_features)(void * opaque);
|
||||
} VirtIOBindings;
|
||||
|
||||
-#define VIRTIO_PCI_QUEUE_MAX 16
|
||||
+#define VIRTIO_PCI_QUEUE_MAX 64
|
||||
|
||||
#define VIRTIO_NO_VECTOR 0xffff
|
||||
|
||||
--
|
||||
1.6.2.5
|
||||
|
@ -1,111 +0,0 @@
|
||||
vhost needs physical addresses for ring and other queue fields,
|
||||
so add APIs for these.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/virtio.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
hw/virtio.h | 10 +++++++++-
|
||||
2 files changed, 56 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio.c b/hw/virtio.c
|
||||
index c2b80aa..b16ee1a 100644
|
||||
--- a/hw/virtio.c
|
||||
+++ b/hw/virtio.c
|
||||
@@ -73,6 +73,9 @@ struct VirtQueue
|
||||
int inuse;
|
||||
uint16_t vector;
|
||||
void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
|
||||
+ VirtIODevice *vdev;
|
||||
+ EventNotifier guest_notifier;
|
||||
+ EventNotifier host_notifier;
|
||||
};
|
||||
|
||||
/* virt queue functions */
|
||||
@@ -594,10 +597,10 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
|
||||
return &vdev->vq[i];
|
||||
}
|
||||
|
||||
-void virtio_irq(VirtIODevice *vdev, VirtQueue *vq)
|
||||
+void virtio_irq(VirtQueue *vq)
|
||||
{
|
||||
- vdev->isr |= 0x01;
|
||||
- virtio_notify_vector(vdev, vq->vector);
|
||||
+ vq->vdev->isr |= 0x01;
|
||||
+ virtio_notify_vector(vq->vdev, vq->vector);
|
||||
}
|
||||
|
||||
void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
|
||||
@@ -608,7 +611,8 @@ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
|
||||
(vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
|
||||
return;
|
||||
|
||||
- virtio_irq(vdev, vq);
|
||||
+ vdev->isr |= 0x01;
|
||||
+ virtio_notify_vector(vdev, vq->vector);
|
||||
}
|
||||
|
||||
void virtio_notify_config(VirtIODevice *vdev)
|
||||
@@ -742,3 +746,42 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
|
||||
vdev->binding = binding;
|
||||
vdev->binding_opaque = opaque;
|
||||
}
|
||||
+
|
||||
+target_phys_addr_t virtio_queue_get_desc(VirtIODevice *vdev, int n)
|
||||
+{
|
||||
+ return vdev->vq[n].vring.desc;
|
||||
+}
|
||||
+
|
||||
+target_phys_addr_t virtio_queue_get_avail(VirtIODevice *vdev, int n)
|
||||
+{
|
||||
+ return vdev->vq[n].vring.avail;
|
||||
+}
|
||||
+
|
||||
+target_phys_addr_t virtio_queue_get_used(VirtIODevice *vdev, int n)
|
||||
+{
|
||||
+ return vdev->vq[n].vring.used;
|
||||
+}
|
||||
+
|
||||
+uint16_t virtio_queue_last_avail_idx(VirtIODevice *vdev, int n)
|
||||
+{
|
||||
+ return vdev->vq[n].last_avail_idx;
|
||||
+}
|
||||
+
|
||||
+void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx)
|
||||
+{
|
||||
+ vdev->vq[n].last_avail_idx = idx;
|
||||
+}
|
||||
+
|
||||
+VirtQueue *virtio_queue(VirtIODevice *vdev, int n)
|
||||
+{
|
||||
+ return vdev->vq + n;
|
||||
+}
|
||||
+
|
||||
+EventNotifier *virtio_queue_guest_notifier(VirtQueue *vq)
|
||||
+{
|
||||
+ return &vq->guest_notifier;
|
||||
+}
|
||||
+EventNotifier *virtio_queue_host_notifier(VirtQueue *vq)
|
||||
+{
|
||||
+ return &vq->host_notifier;
|
||||
+}
|
||||
diff --git a/hw/virtio.h b/hw/virtio.h
|
||||
index 10a0959..f140ca3 100644
|
||||
--- a/hw/virtio.h
|
||||
+++ b/hw/virtio.h
|
||||
@@ -183,5 +183,13 @@ void virtio_net_exit(VirtIODevice *vdev);
|
||||
DEFINE_PROP_BIT("indirect_desc", _state, _field, \
|
||||
VIRTIO_RING_F_INDIRECT_DESC, true)
|
||||
|
||||
-void virtio_irq(VirtIODevice *vdev, VirtQueue *vq);
|
||||
+target_phys_addr_t virtio_queue_get_desc(VirtIODevice *vdev, int n);
|
||||
+target_phys_addr_t virtio_queue_get_avail(VirtIODevice *vdev, int n);
|
||||
+target_phys_addr_t virtio_queue_get_used(VirtIODevice *vdev, int n);
|
||||
+uint16_t virtio_queue_last_avail_idx(VirtIODevice *vdev, int n);
|
||||
+void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx);
|
||||
+VirtQueue *virtio_queue(VirtIODevice *vdev, int n);
|
||||
+EventNotifier *virtio_queue_guest_notifier(VirtQueue *vq);
|
||||
+EventNotifier *virtio_queue_host_notifier(VirtQueue *vq);
|
||||
+void virtio_irq(VirtQueue *vq);
|
||||
#endif
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,400 +0,0 @@
|
||||
Add feature bits as properties to virtio. This makes it possible to e.g. define
|
||||
machine without indirect buffer support, which is required for 0.10
|
||||
compatibility, or without hardware checksum support, which is required for 0.11
|
||||
compatibility. Since default values for optional features are now set by qdev,
|
||||
get_features callback has been modified: it sets non-optional bits, and clears
|
||||
bits not supported by host.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
(cherry picked from commit 8172539d21a03e982aa7f139ddc1607dc1422045)
|
||||
---
|
||||
hw/s390-virtio-bus.c | 12 +++++++++---
|
||||
hw/s390-virtio-bus.h | 1 +
|
||||
hw/syborg_virtio.c | 13 ++++++++-----
|
||||
hw/virtio-balloon.c | 4 ++--
|
||||
hw/virtio-blk.c | 6 +-----
|
||||
hw/virtio-blk.h | 8 ++++++++
|
||||
hw/virtio-net.c | 39 ++++++++++++++++-----------------------
|
||||
hw/virtio-net.h | 20 ++++++++++++++++++++
|
||||
hw/virtio-pci.c | 25 +++++++++++++++++--------
|
||||
hw/virtio.c | 2 +-
|
||||
hw/virtio.h | 7 ++++++-
|
||||
12 files changed, 91 insertions(+), 50 deletions(-)
|
||||
|
||||
--- a/hw/s390-virtio-bus.c 2010-02-09 00:18:58.000000000 -0600
|
||||
+++ b/hw/s390-virtio-bus.c 2010-02-09 00:02:12.000000000 -0600
|
||||
@@ -101,6 +101,7 @@ static int s390_virtio_device_init(VirtI
|
||||
bus->dev_offs += dev_len;
|
||||
|
||||
virtio_bind_device(vdev, &virtio_s390_bindings, dev);
|
||||
+ dev->host_features = vdev->get_features(vdev, dev->host_features);
|
||||
s390_virtio_device_sync(dev);
|
||||
|
||||
return 0;
|
||||
@@ -222,9 +223,7 @@ static void s390_virtio_device_sync(Virt
|
||||
cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
|
||||
|
||||
/* Sync feature bitmap */
|
||||
- if (dev->vdev->get_features) {
|
||||
- stl_phys(cur_offs, dev->vdev->get_features(dev->vdev));
|
||||
- }
|
||||
+ stl_phys(cur_offs, dev->host_features);
|
||||
|
||||
dev->feat_offs = cur_offs + dev->feat_len;
|
||||
cur_offs += dev->feat_len * 2;
|
||||
@@ -310,10 +309,17 @@ static void virtio_s390_notify(void *opa
|
||||
kvm_s390_virtio_irq(s390_cpu_addr2state(0), 0, token);
|
||||
}
|
||||
|
||||
+static unsigned virtio_s390_get_features(void *opaque)
|
||||
+{
|
||||
+ VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
|
||||
+ return dev->host_features;
|
||||
+}
|
||||
+
|
||||
/**************** S390 Virtio Bus Device Descriptions *******************/
|
||||
|
||||
static const VirtIOBindings virtio_s390_bindings = {
|
||||
.notify = virtio_s390_notify,
|
||||
+ .get_features = virtio_s390_get_features,
|
||||
};
|
||||
|
||||
static VirtIOS390DeviceInfo s390_virtio_net = {
|
||||
--- a/hw/s390-virtio-bus.h 2010-02-09 00:18:58.000000000 -0600
|
||||
+++ b/s390-virtio-bus.h 2010-02-09 00:18:16.000000000 -0600
|
||||
@@ -40,6 +40,7 @@ typedef struct VirtIOS390Device {
|
||||
VirtIODevice *vdev;
|
||||
DriveInfo *dinfo;
|
||||
NICConf nic;
|
||||
+ uint32_t host_features;
|
||||
/* Max. number of ports we can have for a the virtio-serial device */
|
||||
uint32_t max_virtserial_ports;
|
||||
} VirtIOS390Device;
|
||||
--- a/hw/syborg_virtio.c 2010-02-09 00:18:58.000000000 -0600
|
||||
+++ b/hw/syborg_virtio.c 2010-02-09 00:02:12.000000000 -0600
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "syborg.h"
|
||||
#include "sysbus.h"
|
||||
#include "virtio.h"
|
||||
+#include "virtio-net.h"
|
||||
#include "sysemu.h"
|
||||
|
||||
//#define DEBUG_SYBORG_VIRTIO
|
||||
@@ -66,6 +67,7 @@ typedef struct {
|
||||
uint32_t int_enable;
|
||||
uint32_t id;
|
||||
NICConf nic;
|
||||
+ uint32_t host_features;
|
||||
} SyborgVirtIOProxy;
|
||||
|
||||
static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
|
||||
@@ -86,8 +88,7 @@ static uint32_t syborg_virtio_readl(void
|
||||
ret = s->id;
|
||||
break;
|
||||
case SYBORG_VIRTIO_HOST_FEATURES:
|
||||
- ret = vdev->get_features(vdev);
|
||||
- ret |= vdev->binding->get_features(s);
|
||||
+ ret = s->host_features;
|
||||
break;
|
||||
case SYBORG_VIRTIO_GUEST_FEATURES:
|
||||
ret = vdev->guest_features;
|
||||
@@ -244,9 +245,8 @@ static void syborg_virtio_update_irq(voi
|
||||
|
||||
static unsigned syborg_virtio_get_features(void *opaque)
|
||||
{
|
||||
- unsigned ret = 0;
|
||||
- ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
- return ret;
|
||||
+ SyborgVirtIOProxy *proxy = opaque;
|
||||
+ return proxy->host_features;
|
||||
}
|
||||
|
||||
static VirtIOBindings syborg_virtio_bindings = {
|
||||
@@ -272,6 +272,8 @@ static int syborg_virtio_init(SyborgVirt
|
||||
qemu_register_reset(virtio_reset, vdev);
|
||||
|
||||
virtio_bind_device(vdev, &syborg_virtio_bindings, proxy);
|
||||
+ proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
+ proxy->host_features = vdev->get_features(vdev, proxy->host_features);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -292,6 +294,7 @@ static SysBusDeviceInfo syborg_virtio_ne
|
||||
.qdev.size = sizeof(SyborgVirtIOProxy),
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
|
||||
+ DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
}
|
||||
};
|
||||
--- a/hw/virtio-balloon.c 2010-01-18 12:48:25.000000000 -0600
|
||||
+++ b/hw/virtio-balloon.c 2010-02-09 00:02:12.000000000 -0600
|
||||
@@ -125,9 +125,9 @@ static void virtio_balloon_set_config(Vi
|
||||
dev->actual = config.actual;
|
||||
}
|
||||
|
||||
-static uint32_t virtio_balloon_get_features(VirtIODevice *vdev)
|
||||
+static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f)
|
||||
{
|
||||
- return 0;
|
||||
+ return f;
|
||||
}
|
||||
|
||||
static ram_addr_t virtio_balloon_to_target(void *opaque, ram_addr_t target)
|
||||
--- a/hw/virtio-blk.c 2010-01-18 12:48:25.000000000 -0600
|
||||
+++ b/hw/virtio-blk.c 2010-02-09 00:02:12.000000000 -0600
|
||||
@@ -432,19 +432,15 @@ static void virtio_blk_update_config(Vir
|
||||
memcpy(config, &blkcfg, s->config_size);
|
||||
}
|
||||
|
||||
-static uint32_t virtio_blk_get_features(VirtIODevice *vdev)
|
||||
+static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
|
||||
{
|
||||
VirtIOBlock *s = to_virtio_blk(vdev);
|
||||
- uint32_t features = 0;
|
||||
|
||||
features |= (1 << VIRTIO_BLK_F_SEG_MAX);
|
||||
features |= (1 << VIRTIO_BLK_F_GEOMETRY);
|
||||
|
||||
if (bdrv_enable_write_cache(s->bs))
|
||||
features |= (1 << VIRTIO_BLK_F_WCACHE);
|
||||
-#ifdef __linux__
|
||||
- features |= (1 << VIRTIO_BLK_F_SCSI);
|
||||
-#endif
|
||||
if (strcmp(s->serial_str, "0"))
|
||||
features |= 1 << VIRTIO_BLK_F_IDENTIFY;
|
||||
|
||||
--- a/hw/virtio-blk.h 2010-01-18 12:48:25.000000000 -0600
|
||||
+++ b/hw/virtio-blk.h 2010-02-09 00:02:12.000000000 -0600
|
||||
@@ -92,4 +92,12 @@ struct virtio_scsi_inhdr
|
||||
uint32_t residual;
|
||||
};
|
||||
|
||||
+#ifdef __linux__
|
||||
+#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
|
||||
+ DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
|
||||
+ DEFINE_PROP_BIT("scsi", _state, _field, VIRTIO_BLK_F_SCSI, true)
|
||||
+#else
|
||||
+#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
|
||||
+ DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
|
||||
+#endif
|
||||
#endif
|
||||
--- a/hw/virtio.c 2010-02-09 00:18:58.000000000 -0600
|
||||
+++ b/hw/virtio.c 2010-02-09 00:02:12.000000000 -0600
|
||||
@@ -650,7 +650,7 @@ int virtio_load(VirtIODevice *vdev, QEMU
|
||||
{
|
||||
int num, i, ret;
|
||||
uint32_t features;
|
||||
- uint32_t supported_features = vdev->get_features(vdev) |
|
||||
+ uint32_t supported_features =
|
||||
vdev->binding->get_features(vdev->binding_opaque);
|
||||
|
||||
if (vdev->binding->load_config) {
|
||||
--- a/hw/virtio.h 2010-02-09 00:18:58.000000000 -0600
|
||||
+++ bhw/virtio.h 2010-02-09 00:02:12.000000000 -0600
|
||||
@@ -105,7 +105,7 @@ struct VirtIODevice
|
||||
void *config;
|
||||
uint16_t config_vector;
|
||||
int nvectors;
|
||||
- uint32_t (*get_features)(VirtIODevice *vdev);
|
||||
+ uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
|
||||
uint32_t (*bad_features)(VirtIODevice *vdev);
|
||||
void (*set_features)(VirtIODevice *vdev, uint32_t val);
|
||||
void (*get_config)(VirtIODevice *vdev, uint8_t *config);
|
||||
@@ -176,4 +176,9 @@ VirtIODevice *virtio_balloon_init(Device
|
||||
|
||||
void virtio_net_exit(VirtIODevice *vdev);
|
||||
|
||||
+#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
|
||||
+ DEFINE_PROP_BIT("indirect_desc", _state, _field, \
|
||||
+ VIRTIO_RING_F_INDIRECT_DESC, true)
|
||||
+
|
||||
+
|
||||
#endif
|
||||
--- a/hw/virtio-net.c 2010-02-09 00:18:58.000000000 -0600
|
||||
+++ b/hw/virtio-net.c 2010-02-09 00:02:12.000000000 -0600
|
||||
@@ -147,34 +147,27 @@ static int peer_has_ufo(VirtIONet *n)
|
||||
return n->has_ufo;
|
||||
}
|
||||
|
||||
-static uint32_t virtio_net_get_features(VirtIODevice *vdev)
|
||||
+static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
|
||||
{
|
||||
VirtIONet *n = to_virtio_net(vdev);
|
||||
- uint32_t features = (1 << VIRTIO_NET_F_MAC) |
|
||||
- (1 << VIRTIO_NET_F_MRG_RXBUF) |
|
||||
- (1 << VIRTIO_NET_F_STATUS) |
|
||||
- (1 << VIRTIO_NET_F_CTRL_VQ) |
|
||||
- (1 << VIRTIO_NET_F_CTRL_RX) |
|
||||
- (1 << VIRTIO_NET_F_CTRL_VLAN) |
|
||||
- (1 << VIRTIO_NET_F_CTRL_RX_EXTRA);
|
||||
|
||||
if (peer_has_vnet_hdr(n)) {
|
||||
tap_using_vnet_hdr(n->nic->nc.peer, 1);
|
||||
+ } else {
|
||||
+ features &= ~(0x1 << VIRTIO_NET_F_CSUM);
|
||||
+ features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4);
|
||||
+ features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO6);
|
||||
+ features &= ~(0x1 << VIRTIO_NET_F_HOST_ECN);
|
||||
+
|
||||
+ features &= ~(0x1 << VIRTIO_NET_F_GUEST_CSUM);
|
||||
+ features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO4);
|
||||
+ features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO6);
|
||||
+ features &= ~(0x1 << VIRTIO_NET_F_GUEST_ECN);
|
||||
+ }
|
||||
|
||||
- features |= (1 << VIRTIO_NET_F_CSUM);
|
||||
- features |= (1 << VIRTIO_NET_F_HOST_TSO4);
|
||||
- features |= (1 << VIRTIO_NET_F_HOST_TSO6);
|
||||
- features |= (1 << VIRTIO_NET_F_HOST_ECN);
|
||||
-
|
||||
- features |= (1 << VIRTIO_NET_F_GUEST_CSUM);
|
||||
- features |= (1 << VIRTIO_NET_F_GUEST_TSO4);
|
||||
- features |= (1 << VIRTIO_NET_F_GUEST_TSO6);
|
||||
- features |= (1 << VIRTIO_NET_F_GUEST_ECN);
|
||||
-
|
||||
- if (peer_has_ufo(n)) {
|
||||
- features |= (1 << VIRTIO_NET_F_GUEST_UFO);
|
||||
- features |= (1 << VIRTIO_NET_F_HOST_UFO);
|
||||
- }
|
||||
+ if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
|
||||
+ features &= ~(0x1 << VIRTIO_NET_F_GUEST_UFO);
|
||||
+ features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
|
||||
}
|
||||
|
||||
return features;
|
||||
@@ -192,7 +185,7 @@ static uint32_t virtio_net_bad_features(
|
||||
features |= (1 << VIRTIO_NET_F_HOST_TSO6);
|
||||
features |= (1 << VIRTIO_NET_F_HOST_ECN);
|
||||
|
||||
- return features & virtio_net_get_features(vdev);
|
||||
+ return features;
|
||||
}
|
||||
|
||||
static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
|
||||
--- a/hw/virtio-net.h 2010-01-18 12:48:25.000000000 -0600
|
||||
+++ b/hw/virtio-net.h 2010-02-09 00:02:12.000000000 -0600
|
||||
@@ -153,4 +153,24 @@ struct virtio_net_ctrl_mac {
|
||||
#define VIRTIO_NET_CTRL_VLAN_ADD 0
|
||||
#define VIRTIO_NET_CTRL_VLAN_DEL 1
|
||||
|
||||
+#define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \
|
||||
+ DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
|
||||
+ DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \
|
||||
+ DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \
|
||||
+ DEFINE_PROP_BIT("mac", _state, _field, VIRTIO_NET_F_MAC, true), \
|
||||
+ DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \
|
||||
+ DEFINE_PROP_BIT("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \
|
||||
+ DEFINE_PROP_BIT("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \
|
||||
+ DEFINE_PROP_BIT("guest_ecn", _state, _field, VIRTIO_NET_F_GUEST_ECN, true), \
|
||||
+ DEFINE_PROP_BIT("guest_ufo", _state, _field, VIRTIO_NET_F_GUEST_UFO, true), \
|
||||
+ DEFINE_PROP_BIT("host_tso4", _state, _field, VIRTIO_NET_F_HOST_TSO4, true), \
|
||||
+ DEFINE_PROP_BIT("host_tso6", _state, _field, VIRTIO_NET_F_HOST_TSO6, true), \
|
||||
+ DEFINE_PROP_BIT("host_ecn", _state, _field, VIRTIO_NET_F_HOST_ECN, true), \
|
||||
+ DEFINE_PROP_BIT("host_ufo", _state, _field, VIRTIO_NET_F_HOST_UFO, true), \
|
||||
+ DEFINE_PROP_BIT("mrg_rxbuf", _state, _field, VIRTIO_NET_F_MRG_RXBUF, true), \
|
||||
+ DEFINE_PROP_BIT("status", _state, _field, VIRTIO_NET_F_STATUS, true), \
|
||||
+ DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \
|
||||
+ DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \
|
||||
+ DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \
|
||||
+ DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true)
|
||||
#endif
|
||||
--- a/hw/virtio-pci.c 2010-02-09 00:18:58.000000000 -0600
|
||||
+++ b/hw/virtio-pci.c 2010-02-09 00:16:13.000000000 -0600
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "virtio.h"
|
||||
+#include "virtio-blk.h"
|
||||
+#include "virtio-net.h"
|
||||
#include "pci.h"
|
||||
#include "sysemu.h"
|
||||
#include "msix.h"
|
||||
@@ -92,6 +94,7 @@ typedef struct {
|
||||
uint32_t nvectors;
|
||||
DriveInfo *dinfo;
|
||||
NICConf nic;
|
||||
+ uint32_t host_features;
|
||||
/* Max. number of ports we can have for a the virtio-serial device */
|
||||
uint32_t max_virtserial_ports;
|
||||
} VirtIOPCIProxy;
|
||||
@@ -177,7 +180,7 @@ static void virtio_ioport_write(void *op
|
||||
/* Guest does not negotiate properly? We have to assume nothing. */
|
||||
if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
|
||||
if (vdev->bad_features)
|
||||
- val = vdev->bad_features(vdev);
|
||||
+ val = proxy->host_features & vdev->bad_features(vdev);
|
||||
else
|
||||
val = 0;
|
||||
}
|
||||
@@ -237,8 +240,7 @@ static uint32_t virtio_ioport_read(VirtI
|
||||
|
||||
switch (addr) {
|
||||
case VIRTIO_PCI_HOST_FEATURES:
|
||||
- ret = vdev->get_features(vdev);
|
||||
- ret |= vdev->binding->get_features(proxy);
|
||||
+ ret = proxy->host_features;
|
||||
break;
|
||||
case VIRTIO_PCI_GUEST_FEATURES:
|
||||
ret = vdev->guest_features;
|
||||
@@ -384,11 +386,8 @@ static void virtio_write_config(PCIDevic
|
||||
|
||||
static unsigned virtio_pci_get_features(void *opaque)
|
||||
{
|
||||
- unsigned ret = 0;
|
||||
- ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
- ret |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
|
||||
- ret |= (1 << VIRTIO_F_BAD_FEATURE);
|
||||
- return ret;
|
||||
+ VirtIOPCIProxy *proxy = opaque;
|
||||
+ return proxy->host_features;
|
||||
}
|
||||
|
||||
static const VirtIOBindings virtio_pci_bindings = {
|
||||
@@ -444,6 +443,9 @@ static void virtio_init_pci(VirtIOPCIPro
|
||||
virtio_map);
|
||||
|
||||
virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
|
||||
+ proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
|
||||
+ proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
|
||||
+ proxy->host_features = vdev->get_features(vdev, proxy->host_features);
|
||||
}
|
||||
|
||||
static int virtio_blk_init_pci(PCIDevice *pci_dev)
|
||||
@@ -558,6 +560,7 @@ static PCIDeviceInfo virtio_info[] = {
|
||||
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
|
||||
DEFINE_PROP_DRIVE("drive", VirtIOPCIProxy, dinfo),
|
||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
|
||||
+ DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
},
|
||||
.qdev.reset = virtio_pci_reset,
|
||||
@@ -569,6 +572,7 @@ static PCIDeviceInfo virtio_info[] = {
|
||||
.romfile = "pxe-virtio.bin",
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
|
||||
+ DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
|
||||
DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
},
|
||||
@@ -582,6 +586,7 @@ static PCIDeviceInfo virtio_info[] = {
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 0),
|
||||
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
|
||||
+ DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
|
||||
DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, max_virtserial_ports,
|
||||
31),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
@@ -592,6 +597,10 @@ static PCIDeviceInfo virtio_info[] = {
|
||||
.qdev.size = sizeof(VirtIOPCIProxy),
|
||||
.init = virtio_balloon_init_pci,
|
||||
.exit = virtio_exit_pci,
|
||||
+ .qdev.props = (Property[]) {
|
||||
+ DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
|
||||
+ DEFINE_PROP_END_OF_LIST(),
|
||||
+ },
|
||||
.qdev.reset = virtio_pci_reset,
|
||||
},{
|
||||
/* end of list */
|
@ -1,78 +0,0 @@
|
||||
Add binding API to set host/guest notifiers.
|
||||
Will be used by vhost.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/virtio.c | 13 ++++++++++---
|
||||
hw/virtio.h | 5 ++++-
|
||||
2 files changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio.c b/hw/virtio.c
|
||||
index fa7184a..c2b80aa 100644
|
||||
--- a/hw/virtio.c
|
||||
+++ b/hw/virtio.c
|
||||
@@ -594,6 +594,12 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
|
||||
return &vdev->vq[i];
|
||||
}
|
||||
|
||||
+void virtio_irq(VirtIODevice *vdev, VirtQueue *vq)
|
||||
+{
|
||||
+ vdev->isr |= 0x01;
|
||||
+ virtio_notify_vector(vdev, vq->vector);
|
||||
+}
|
||||
+
|
||||
void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
/* Always notify when queue is empty (when feature acknowledge) */
|
||||
@@ -602,8 +608,7 @@ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
|
||||
(vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
|
||||
return;
|
||||
|
||||
- vdev->isr |= 0x01;
|
||||
- virtio_notify_vector(vdev, vq->vector);
|
||||
+ virtio_irq(vdev, vq);
|
||||
}
|
||||
|
||||
void virtio_notify_config(VirtIODevice *vdev)
|
||||
@@ -716,8 +721,10 @@ VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
|
||||
vdev->queue_sel = 0;
|
||||
vdev->config_vector = VIRTIO_NO_VECTOR;
|
||||
vdev->vq = qemu_mallocz(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX);
|
||||
- for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++)
|
||||
+ for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
|
||||
vdev->vq[i].vector = VIRTIO_NO_VECTOR;
|
||||
+ vdev->vq[i].vdev = vdev;
|
||||
+ }
|
||||
|
||||
vdev->name = name;
|
||||
vdev->config_len = config_size;
|
||||
diff --git a/hw/virtio.h b/hw/virtio.h
|
||||
index 3994cc9..10a0959 100644
|
||||
--- a/hw/virtio.h
|
||||
+++ b/hw/virtio.h
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "net.h"
|
||||
#include "qdev.h"
|
||||
#include "sysemu.h"
|
||||
+#include "notifier.h"
|
||||
|
||||
/* from Linux's linux/virtio_config.h */
|
||||
|
||||
@@ -88,6 +89,8 @@ typedef struct {
|
||||
int (*load_config)(void * opaque, QEMUFile *f);
|
||||
int (*load_queue)(void * opaque, int n, QEMUFile *f);
|
||||
unsigned (*get_features)(void * opaque);
|
||||
+ int (*guest_notifier)(void * opaque, int n, bool assigned);
|
||||
+ int (*host_notifier)(void * opaque, int n, bool assigned);
|
||||
} VirtIOBindings;
|
||||
|
||||
#define VIRTIO_PCI_QUEUE_MAX 64
|
||||
@@ -180,5 +183,5 @@ void virtio_net_exit(VirtIODevice *vdev);
|
||||
DEFINE_PROP_BIT("indirect_desc", _state, _field, \
|
||||
VIRTIO_RING_F_INDIRECT_DESC, true)
|
||||
|
||||
-
|
||||
+void virtio_irq(VirtIODevice *vdev, VirtQueue *vq);
|
||||
#endif
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,76 +0,0 @@
|
||||
vhost net backend needs to be notified when
|
||||
frontend status changes. Add a callback.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/s390-virtio-bus.c | 3 +++
|
||||
hw/syborg_virtio.c | 2 ++
|
||||
hw/virtio-pci.c | 6 ++++++
|
||||
hw/virtio.h | 1 +
|
||||
4 files changed, 12 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
|
||||
index 980e7eb..f45b67d 100644
|
||||
--- a/hw/s390-virtio-bus.c
|
||||
+++ b/hw/s390-virtio-bus.c
|
||||
@@ -243,6 +243,9 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
|
||||
uint32_t features;
|
||||
|
||||
vdev->status = ldub_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS);
|
||||
+ if (vdev->set_status) {
|
||||
+ vdev->set_status(vdev);
|
||||
+ }
|
||||
|
||||
/* Update guest supported feature bitmap */
|
||||
|
||||
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
|
||||
index 65239a0..19f6473 100644
|
||||
--- a/hw/syborg_virtio.c
|
||||
+++ b/hw/syborg_virtio.c
|
||||
@@ -152,6 +152,8 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
|
||||
vdev->status = value & 0xFF;
|
||||
if (vdev->status == 0)
|
||||
virtio_reset(vdev);
|
||||
+ if (vdev->set_status)
|
||||
+ vdev->set_status(vdev);
|
||||
break;
|
||||
case SYBORG_VIRTIO_INT_ENABLE:
|
||||
s->int_enable = value;
|
||||
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
|
||||
index 573c98a..05898c8 100644
|
||||
--- a/hw/virtio-pci.c
|
||||
+++ b/hw/virtio-pci.c
|
||||
@@ -208,6 +208,9 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
virtio_reset(proxy->vdev);
|
||||
msix_unuse_all_vectors(&proxy->pci_dev);
|
||||
}
|
||||
+ if (vdev->set_status) {
|
||||
+ vdev->set_status(vdev);
|
||||
+ }
|
||||
break;
|
||||
case VIRTIO_MSI_CONFIG_VECTOR:
|
||||
msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
|
||||
@@ -375,6 +378,9 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
|
||||
if (PCI_COMMAND == address) {
|
||||
if (!(val & PCI_COMMAND_MASTER)) {
|
||||
proxy->vdev->status &= ~VIRTIO_CONFIG_S_DRIVER_OK;
|
||||
+ if (proxy->vdev->set_status) {
|
||||
+ proxy->vdev->set_status(proxy->vdev);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/hw/virtio.h b/hw/virtio.h
|
||||
index f140ca3..39d0763 100644
|
||||
--- a/hw/virtio.h
|
||||
+++ b/hw/virtio.h
|
||||
@@ -114,6 +114,7 @@ struct VirtIODevice
|
||||
void (*get_config)(VirtIODevice *vdev, uint8_t *config);
|
||||
void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
|
||||
void (*reset)(VirtIODevice *vdev);
|
||||
+ void (*set_status)(VirtIODevice *vdev);
|
||||
VirtQueue *vq;
|
||||
const VirtIOBindings *binding;
|
||||
void *binding_opaque;
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,25 +0,0 @@
|
||||
verify that peer is tap before checking for vhost net
|
||||
|
||||
Reported-by: Shirley Ma <mashirle@us.ibm.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/virtio-net.c | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
|
||||
index 088029b..b28fd92 100644
|
||||
--- a/hw/virtio-net.c
|
||||
+++ b/hw/virtio-net.c
|
||||
@@ -179,6 +179,10 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
|
||||
features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
|
||||
}
|
||||
|
||||
+ if (!n->nic->nc.peer ||
|
||||
+ n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) {
|
||||
+ return features;
|
||||
+ }
|
||||
if (!tap_get_vhost_net(n->nic->nc.peer)) {
|
||||
return features;
|
||||
}
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,341 +0,0 @@
|
||||
From 9c7f6b094950f7772068b957c795d76463cdeba0 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Thu, 21 Jan 2010 15:43:26 +0530
|
||||
Subject: [PATCH 9/9] virtio-console: Rename virtio-serial.c back to virtio-console.c
|
||||
|
||||
This file was renamed to ease the reviews of the recent changes
|
||||
that went in.
|
||||
|
||||
Now that the changes are done, rename the file back to its original
|
||||
name.
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
Makefile.hw | 2 +-
|
||||
hw/virtio-console.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
hw/virtio-serial.c | 146 ---------------------------------------------------
|
||||
3 files changed, 147 insertions(+), 147 deletions(-)
|
||||
create mode 100644 hw/virtio-console.c
|
||||
delete mode 100644 hw/virtio-serial.c
|
||||
|
||||
diff --git a/Makefile.hw b/Makefile.hw
|
||||
index de8a0c5..43ca541 100644
|
||||
--- a/Makefile.hw
|
||||
+++ b/Makefile.hw
|
||||
@@ -13,7 +13,7 @@ QEMU_CFLAGS+=-I.. -I$(SRC_PATH)/fpu
|
||||
|
||||
obj-y =
|
||||
obj-y += loader.o
|
||||
-obj-y += virtio.o virtio-serial.o
|
||||
+obj-y += virtio.o virtio-console.o
|
||||
obj-y += fw_cfg.o
|
||||
obj-y += watchdog.o
|
||||
obj-$(CONFIG_ECC) += ecc.o
|
||||
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
|
||||
new file mode 100644
|
||||
index 0000000..bd44ec6
|
||||
--- /dev/null
|
||||
+++ b/hw/virtio-console.c
|
||||
@@ -0,0 +1,146 @@
|
||||
+/*
|
||||
+ * Virtio Console and Generic Serial Port Devices
|
||||
+ *
|
||||
+ * Copyright Red Hat, Inc. 2009
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Amit Shah <amit.shah@redhat.com>
|
||||
+ *
|
||||
+ * This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
+ * the COPYING file in the top-level directory.
|
||||
+ */
|
||||
+
|
||||
+#include "qemu-char.h"
|
||||
+#include "virtio-serial.h"
|
||||
+
|
||||
+typedef struct VirtConsole {
|
||||
+ VirtIOSerialPort port;
|
||||
+ CharDriverState *chr;
|
||||
+} VirtConsole;
|
||||
+
|
||||
+
|
||||
+/* Callback function that's called when the guest sends us data */
|
||||
+static size_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
|
||||
+{
|
||||
+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||
+ ssize_t ret;
|
||||
+
|
||||
+ ret = qemu_chr_write(vcon->chr, buf, len);
|
||||
+
|
||||
+ return ret < 0 ? 0 : ret;
|
||||
+}
|
||||
+
|
||||
+/* Readiness of the guest to accept data on a port */
|
||||
+static int chr_can_read(void *opaque)
|
||||
+{
|
||||
+ VirtConsole *vcon = opaque;
|
||||
+
|
||||
+ return virtio_serial_guest_ready(&vcon->port);
|
||||
+}
|
||||
+
|
||||
+/* Send data from a char device over to the guest */
|
||||
+static void chr_read(void *opaque, const uint8_t *buf, int size)
|
||||
+{
|
||||
+ VirtConsole *vcon = opaque;
|
||||
+
|
||||
+ virtio_serial_write(&vcon->port, buf, size);
|
||||
+}
|
||||
+
|
||||
+static void chr_event(void *opaque, int event)
|
||||
+{
|
||||
+ VirtConsole *vcon = opaque;
|
||||
+
|
||||
+ switch (event) {
|
||||
+ case CHR_EVENT_OPENED: {
|
||||
+ virtio_serial_open(&vcon->port);
|
||||
+ break;
|
||||
+ }
|
||||
+ case CHR_EVENT_CLOSED:
|
||||
+ virtio_serial_close(&vcon->port);
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Virtio Console Ports */
|
||||
+static int virtconsole_initfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||
+
|
||||
+ port->info = dev->info;
|
||||
+
|
||||
+ port->is_console = true;
|
||||
+
|
||||
+ if (vcon->chr) {
|
||||
+ qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
|
||||
+ vcon);
|
||||
+ port->info->have_data = flush_buf;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int virtconsole_exitfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||
+
|
||||
+ if (vcon->chr) {
|
||||
+ port->info->have_data = NULL;
|
||||
+ qemu_chr_close(vcon->chr);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static VirtIOSerialPortInfo virtconsole_info = {
|
||||
+ .qdev.name = "virtconsole",
|
||||
+ .qdev.size = sizeof(VirtConsole),
|
||||
+ .init = virtconsole_initfn,
|
||||
+ .exit = virtconsole_exitfn,
|
||||
+ .qdev.props = (Property[]) {
|
||||
+ DEFINE_PROP_UINT8("is_console", VirtConsole, port.is_console, 1),
|
||||
+ DEFINE_PROP_CHR("chardev", VirtConsole, chr),
|
||||
+ DEFINE_PROP_STRING("name", VirtConsole, port.name),
|
||||
+ DEFINE_PROP_END_OF_LIST(),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void virtconsole_register(void)
|
||||
+{
|
||||
+ virtio_serial_port_qdev_register(&virtconsole_info);
|
||||
+}
|
||||
+device_init(virtconsole_register)
|
||||
+
|
||||
+/* Generic Virtio Serial Ports */
|
||||
+static int virtserialport_initfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||
+
|
||||
+ port->info = dev->info;
|
||||
+
|
||||
+ if (vcon->chr) {
|
||||
+ qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
|
||||
+ vcon);
|
||||
+ port->info->have_data = flush_buf;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static VirtIOSerialPortInfo virtserialport_info = {
|
||||
+ .qdev.name = "virtserialport",
|
||||
+ .qdev.size = sizeof(VirtConsole),
|
||||
+ .init = virtserialport_initfn,
|
||||
+ .exit = virtconsole_exitfn,
|
||||
+ .qdev.props = (Property[]) {
|
||||
+ DEFINE_PROP_CHR("chardev", VirtConsole, chr),
|
||||
+ DEFINE_PROP_STRING("name", VirtConsole, port.name),
|
||||
+ DEFINE_PROP_END_OF_LIST(),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void virtserialport_register(void)
|
||||
+{
|
||||
+ virtio_serial_port_qdev_register(&virtserialport_info);
|
||||
+}
|
||||
+device_init(virtserialport_register)
|
||||
diff --git a/hw/virtio-serial.c b/hw/virtio-serial.c
|
||||
deleted file mode 100644
|
||||
index bd44ec6..0000000
|
||||
--- a/hw/virtio-serial.c
|
||||
+++ /dev/null
|
||||
@@ -1,146 +0,0 @@
|
||||
-/*
|
||||
- * Virtio Console and Generic Serial Port Devices
|
||||
- *
|
||||
- * Copyright Red Hat, Inc. 2009
|
||||
- *
|
||||
- * Authors:
|
||||
- * Amit Shah <amit.shah@redhat.com>
|
||||
- *
|
||||
- * This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
- * the COPYING file in the top-level directory.
|
||||
- */
|
||||
-
|
||||
-#include "qemu-char.h"
|
||||
-#include "virtio-serial.h"
|
||||
-
|
||||
-typedef struct VirtConsole {
|
||||
- VirtIOSerialPort port;
|
||||
- CharDriverState *chr;
|
||||
-} VirtConsole;
|
||||
-
|
||||
-
|
||||
-/* Callback function that's called when the guest sends us data */
|
||||
-static size_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
|
||||
-{
|
||||
- VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||
- ssize_t ret;
|
||||
-
|
||||
- ret = qemu_chr_write(vcon->chr, buf, len);
|
||||
-
|
||||
- return ret < 0 ? 0 : ret;
|
||||
-}
|
||||
-
|
||||
-/* Readiness of the guest to accept data on a port */
|
||||
-static int chr_can_read(void *opaque)
|
||||
-{
|
||||
- VirtConsole *vcon = opaque;
|
||||
-
|
||||
- return virtio_serial_guest_ready(&vcon->port);
|
||||
-}
|
||||
-
|
||||
-/* Send data from a char device over to the guest */
|
||||
-static void chr_read(void *opaque, const uint8_t *buf, int size)
|
||||
-{
|
||||
- VirtConsole *vcon = opaque;
|
||||
-
|
||||
- virtio_serial_write(&vcon->port, buf, size);
|
||||
-}
|
||||
-
|
||||
-static void chr_event(void *opaque, int event)
|
||||
-{
|
||||
- VirtConsole *vcon = opaque;
|
||||
-
|
||||
- switch (event) {
|
||||
- case CHR_EVENT_OPENED: {
|
||||
- virtio_serial_open(&vcon->port);
|
||||
- break;
|
||||
- }
|
||||
- case CHR_EVENT_CLOSED:
|
||||
- virtio_serial_close(&vcon->port);
|
||||
- break;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-/* Virtio Console Ports */
|
||||
-static int virtconsole_initfn(VirtIOSerialDevice *dev)
|
||||
-{
|
||||
- VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
- VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||
-
|
||||
- port->info = dev->info;
|
||||
-
|
||||
- port->is_console = true;
|
||||
-
|
||||
- if (vcon->chr) {
|
||||
- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
|
||||
- vcon);
|
||||
- port->info->have_data = flush_buf;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int virtconsole_exitfn(VirtIOSerialDevice *dev)
|
||||
-{
|
||||
- VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
- VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||
-
|
||||
- if (vcon->chr) {
|
||||
- port->info->have_data = NULL;
|
||||
- qemu_chr_close(vcon->chr);
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static VirtIOSerialPortInfo virtconsole_info = {
|
||||
- .qdev.name = "virtconsole",
|
||||
- .qdev.size = sizeof(VirtConsole),
|
||||
- .init = virtconsole_initfn,
|
||||
- .exit = virtconsole_exitfn,
|
||||
- .qdev.props = (Property[]) {
|
||||
- DEFINE_PROP_UINT8("is_console", VirtConsole, port.is_console, 1),
|
||||
- DEFINE_PROP_CHR("chardev", VirtConsole, chr),
|
||||
- DEFINE_PROP_STRING("name", VirtConsole, port.name),
|
||||
- DEFINE_PROP_END_OF_LIST(),
|
||||
- },
|
||||
-};
|
||||
-
|
||||
-static void virtconsole_register(void)
|
||||
-{
|
||||
- virtio_serial_port_qdev_register(&virtconsole_info);
|
||||
-}
|
||||
-device_init(virtconsole_register)
|
||||
-
|
||||
-/* Generic Virtio Serial Ports */
|
||||
-static int virtserialport_initfn(VirtIOSerialDevice *dev)
|
||||
-{
|
||||
- VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
- VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||
-
|
||||
- port->info = dev->info;
|
||||
-
|
||||
- if (vcon->chr) {
|
||||
- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
|
||||
- vcon);
|
||||
- port->info->have_data = flush_buf;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static VirtIOSerialPortInfo virtserialport_info = {
|
||||
- .qdev.name = "virtserialport",
|
||||
- .qdev.size = sizeof(VirtConsole),
|
||||
- .init = virtserialport_initfn,
|
||||
- .exit = virtconsole_exitfn,
|
||||
- .qdev.props = (Property[]) {
|
||||
- DEFINE_PROP_CHR("chardev", VirtConsole, chr),
|
||||
- DEFINE_PROP_STRING("name", VirtConsole, port.name),
|
||||
- DEFINE_PROP_END_OF_LIST(),
|
||||
- },
|
||||
-};
|
||||
-
|
||||
-static void virtserialport_register(void)
|
||||
-{
|
||||
- virtio_serial_port_qdev_register(&virtserialport_info);
|
||||
-}
|
||||
-device_init(virtserialport_register)
|
||||
--
|
||||
1.6.2.5
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,34 +0,0 @@
|
||||
make it possible to use type without header include
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/virtio.h | 1 -
|
||||
qemu-common.h | 1 +
|
||||
2 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio.h b/hw/virtio.h
|
||||
index 39d0763..a5bd0ba 100644
|
||||
--- a/hw/virtio.h
|
||||
+++ b/hw/virtio.h
|
||||
@@ -68,7 +68,6 @@ static inline target_phys_addr_t vring_align(target_phys_addr_t addr,
|
||||
}
|
||||
|
||||
typedef struct VirtQueue VirtQueue;
|
||||
-typedef struct VirtIODevice VirtIODevice;
|
||||
|
||||
#define VIRTQUEUE_MAX_SIZE 1024
|
||||
|
||||
diff --git a/qemu-common.h b/qemu-common.h
|
||||
index cdead98..1a54f9e 100644
|
||||
--- a/qemu-common.h
|
||||
+++ b/qemu-common.h
|
||||
@@ -218,6 +218,7 @@ typedef struct I2SCodec I2SCodec;
|
||||
typedef struct DeviceState DeviceState;
|
||||
typedef struct SSIBus SSIBus;
|
||||
typedef struct EventNotifier EventNotifier;
|
||||
+typedef struct VirtIODevice VirtIODevice;
|
||||
|
||||
/* CPU save/load. */
|
||||
void cpu_save(QEMUFile *f, void *opaque);
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,40 +0,0 @@
|
||||
Mac feature bit isn't going to work as all network cards already have a
|
||||
'mac' property to set the mac address. Remove it from mask and add in
|
||||
get_features.
|
||||
|
||||
Reported-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
(cherry picked from commit c9f79a3f79a48de28b4575cb5644bcf45d3754d0)
|
||||
---
|
||||
hw/virtio-net.c | 2 ++
|
||||
hw/virtio-net.h | 1 -
|
||||
2 files changed, 2 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
|
||||
index c2a389f..02d9180 100644
|
||||
--- a/hw/virtio-net.c
|
||||
+++ b/hw/virtio-net.c
|
||||
@@ -151,6 +151,8 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
|
||||
{
|
||||
VirtIONet *n = to_virtio_net(vdev);
|
||||
|
||||
+ features |= (1 << VIRTIO_NET_F_MAC);
|
||||
+
|
||||
if (peer_has_vnet_hdr(n)) {
|
||||
tap_using_vnet_hdr(n->nic->nc.peer, 1);
|
||||
} else {
|
||||
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
|
||||
index 9130d75..e55119b 100644
|
||||
--- a/hw/virtio-net.h
|
||||
+++ b/hw/virtio-net.h
|
||||
@@ -157,7 +157,6 @@ struct virtio_net_ctrl_mac {
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
|
||||
DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \
|
||||
DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \
|
||||
- DEFINE_PROP_BIT("mac", _state, _field, VIRTIO_NET_F_MAC, true), \
|
||||
DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \
|
||||
DEFINE_PROP_BIT("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \
|
||||
DEFINE_PROP_BIT("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,153 +0,0 @@
|
||||
This connects virtio-net to vhost net backend.
|
||||
The code is structured in a way analogous to what we have with vnet
|
||||
header capability in tap. We start/stop backend on driver start/stop as
|
||||
well as on save and vm start (for migration).
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/virtio-net.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 files changed, 65 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
|
||||
index 02d9180..088029b 100644
|
||||
--- a/hw/virtio-net.c
|
||||
+++ b/hw/virtio-net.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "net/tap.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "virtio-net.h"
|
||||
+#include "vhost_net.h"
|
||||
|
||||
#define VIRTIO_NET_VM_VERSION 11
|
||||
|
||||
@@ -47,6 +48,8 @@ typedef struct VirtIONet
|
||||
uint8_t nomulti;
|
||||
uint8_t nouni;
|
||||
uint8_t nobcast;
|
||||
+ uint8_t vhost_started;
|
||||
+ VMChangeStateEntry *vmstate;
|
||||
struct {
|
||||
int in_use;
|
||||
int first_multi;
|
||||
@@ -114,6 +117,10 @@ static void virtio_net_reset(VirtIODevice *vdev)
|
||||
n->nomulti = 0;
|
||||
n->nouni = 0;
|
||||
n->nobcast = 0;
|
||||
+ if (n->vhost_started) {
|
||||
+ vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
|
||||
+ n->vhost_started = 0;
|
||||
+ }
|
||||
|
||||
/* Flush any MAC and VLAN filter table state */
|
||||
n->mac_table.in_use = 0;
|
||||
@@ -172,7 +179,10 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
|
||||
features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
|
||||
}
|
||||
|
||||
- return features;
|
||||
+ if (!tap_get_vhost_net(n->nic->nc.peer)) {
|
||||
+ return features;
|
||||
+ }
|
||||
+ return vhost_net_get_features(tap_get_vhost_net(n->nic->nc.peer), features);
|
||||
}
|
||||
|
||||
static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
|
||||
@@ -690,6 +700,12 @@ static void virtio_net_save(QEMUFile *f, void *opaque)
|
||||
{
|
||||
VirtIONet *n = opaque;
|
||||
|
||||
+ if (n->vhost_started) {
|
||||
+ /* TODO: should we really stop the backend?
|
||||
+ * If we don't, it might keep writing to memory. */
|
||||
+ vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
|
||||
+ n->vhost_started = 0;
|
||||
+ }
|
||||
virtio_save(&n->vdev, f);
|
||||
|
||||
qemu_put_buffer(f, n->mac, ETH_ALEN);
|
||||
@@ -802,7 +818,6 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
|
||||
qemu_mod_timer(n->tx_timer,
|
||||
qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
|
||||
}
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -822,6 +837,47 @@ static NetClientInfo net_virtio_info = {
|
||||
.link_status_changed = virtio_net_set_link_status,
|
||||
};
|
||||
|
||||
+static void virtio_net_set_status(struct VirtIODevice *vdev)
|
||||
+{
|
||||
+ VirtIONet *n = to_virtio_net(vdev);
|
||||
+ if (!n->nic->nc.peer) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!tap_get_vhost_net(n->nic->nc.peer)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!!n->vhost_started == !!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) {
|
||||
+ int r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), vdev);
|
||||
+ if (r < 0) {
|
||||
+ fprintf(stderr, "unable to start vhost net: %d: "
|
||||
+ "falling back on userspace virtio\n", -r);
|
||||
+ } else {
|
||||
+ n->vhost_started = 1;
|
||||
+ }
|
||||
+ } else {
|
||||
+ vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
|
||||
+ n->vhost_started = 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void virtio_net_vmstate_change(void *opaque, int running, int reason)
|
||||
+{
|
||||
+ VirtIONet *n = opaque;
|
||||
+ if (!running) {
|
||||
+ return;
|
||||
+ }
|
||||
+ /* This is called when vm is started, it will start vhost backend if it
|
||||
+ * appropriate e.g. after migration. */
|
||||
+ virtio_net_set_status(&n->vdev);
|
||||
+}
|
||||
+
|
||||
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
|
||||
{
|
||||
VirtIONet *n;
|
||||
@@ -837,6 +893,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
|
||||
n->vdev.set_features = virtio_net_set_features;
|
||||
n->vdev.bad_features = virtio_net_bad_features;
|
||||
n->vdev.reset = virtio_net_reset;
|
||||
+ n->vdev.set_status = virtio_net_set_status;
|
||||
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);
|
||||
@@ -859,6 +916,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
|
||||
|
||||
register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
|
||||
virtio_net_save, virtio_net_load, n);
|
||||
+ n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
|
||||
|
||||
return &n->vdev;
|
||||
}
|
||||
@@ -866,6 +924,11 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
|
||||
void virtio_net_exit(VirtIODevice *vdev)
|
||||
{
|
||||
VirtIONet *n = DO_UPCAST(VirtIONet, vdev, vdev);
|
||||
+ qemu_del_vm_change_state_handler(n->vmstate);
|
||||
+
|
||||
+ if (n->vhost_started) {
|
||||
+ vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
|
||||
+ }
|
||||
|
||||
qemu_purge_queued_packets(&n->nic->nc);
|
||||
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,98 +0,0 @@
|
||||
Support host/guest notifiers in virtio-pci.
|
||||
The last one only with kvm, that's okay
|
||||
because vhost relies on kvm anyway.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/virtio-pci.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 files changed, 62 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
|
||||
index 05898c8..c454093 100644
|
||||
--- a/hw/virtio-pci.c
|
||||
+++ b/hw/virtio-pci.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "msix.h"
|
||||
#include "net.h"
|
||||
#include "loader.h"
|
||||
+#include "kvm.h"
|
||||
|
||||
/* from Linux's linux/virtio_pci.h */
|
||||
|
||||
@@ -394,6 +395,65 @@ static unsigned virtio_pci_get_features(void *opaque)
|
||||
return proxy->host_features;
|
||||
}
|
||||
|
||||
+static void virtio_pci_guest_notifier_read(void *opaque)
|
||||
+{
|
||||
+ VirtQueue *vq = opaque;
|
||||
+ EventNotifier *n = virtio_queue_guest_notifier(vq);
|
||||
+ if (event_notifier_test_and_clear(n)) {
|
||||
+ virtio_irq(vq);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int virtio_pci_guest_notifier(void *opaque, int n, bool assign)
|
||||
+{
|
||||
+ VirtIOPCIProxy *proxy = opaque;
|
||||
+ VirtQueue *vq = virtio_queue(proxy->vdev, n);
|
||||
+ EventNotifier *notifier = virtio_queue_guest_notifier(vq);
|
||||
+
|
||||
+ if (assign) {
|
||||
+ int r = event_notifier_init(notifier, 0);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ qemu_set_fd_handler(event_notifier_get_fd(notifier),
|
||||
+ virtio_pci_guest_notifier_read, NULL, vq);
|
||||
+ } else {
|
||||
+ qemu_set_fd_handler(event_notifier_get_fd(notifier),
|
||||
+ NULL, NULL, vq);
|
||||
+ event_notifier_cleanup(notifier);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int virtio_pci_host_notifier(void *opaque, int n, bool assign)
|
||||
+{
|
||||
+ VirtIOPCIProxy *proxy = opaque;
|
||||
+ VirtQueue *vq = virtio_queue(proxy->vdev, n);
|
||||
+ EventNotifier *notifier = virtio_queue_host_notifier(vq);
|
||||
+ int r;
|
||||
+ if (assign) {
|
||||
+ r = event_notifier_init(notifier, 1);
|
||||
+ if (r < 0) {
|
||||
+ return r;
|
||||
+ }
|
||||
+ r = kvm_set_ioeventfd(proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
|
||||
+ n, event_notifier_get_fd(notifier),
|
||||
+ assign);
|
||||
+ if (r < 0) {
|
||||
+ event_notifier_cleanup(notifier);
|
||||
+ }
|
||||
+ } else {
|
||||
+ r = kvm_set_ioeventfd(proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
|
||||
+ n, event_notifier_get_fd(notifier),
|
||||
+ assign);
|
||||
+ if (r < 0) {
|
||||
+ return r;
|
||||
+ }
|
||||
+ event_notifier_cleanup(notifier);
|
||||
+ }
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
static const VirtIOBindings virtio_pci_bindings = {
|
||||
.notify = virtio_pci_notify,
|
||||
.save_config = virtio_pci_save_config,
|
||||
@@ -401,6 +461,8 @@ static const VirtIOBindings virtio_pci_bindings = {
|
||||
.save_queue = virtio_pci_save_queue,
|
||||
.load_queue = virtio_pci_load_queue,
|
||||
.get_features = virtio_pci_get_features,
|
||||
+ .host_notifier = virtio_pci_host_notifier,
|
||||
+ .guest_notifier = virtio_pci_guest_notifier,
|
||||
};
|
||||
|
||||
static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,34 +0,0 @@
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
|
||||
---
|
||||
|
||||
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
|
||||
index e8e0d82..fd0c73f 100644
|
||||
--- a/hw/virtio-pci.c
|
||||
+++ b/hw/virtio-pci.c
|
||||
@@ -404,6 +404,7 @@ static void virtio_pci_guest_notifier_read(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_KVM
|
||||
static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
|
||||
void *opaque, int masked)
|
||||
{
|
||||
@@ -424,6 +425,7 @@ static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+#endif
|
||||
|
||||
static int virtio_pci_guest_notifier(void *opaque, int n, bool assign)
|
||||
{
|
||||
@@ -526,7 +528,9 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
|
||||
|
||||
proxy->pci_dev.config_write = virtio_write_config;
|
||||
|
||||
+#ifdef CONFIG_KVM
|
||||
proxy->pci_dev.msix_mask_notifier = virtio_pci_mask_notifier;
|
||||
+#endif
|
||||
|
||||
size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
|
||||
if (size & (size-1))
|
@ -1,70 +0,0 @@
|
||||
Use irqfd when supported by kernel.
|
||||
This uses msix mask notifiers: when vector is masked, we poll it from
|
||||
userspace. When it is unmasked, we poll it from kernel.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/virtio-pci.c | 31 +++++++++++++++++++++++++++++--
|
||||
1 files changed, 29 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
|
||||
index c454093..e8e0d82 100644
|
||||
--- a/hw/virtio-pci.c
|
||||
+++ b/hw/virtio-pci.c
|
||||
@@ -404,6 +404,27 @@ static void virtio_pci_guest_notifier_read(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
+static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
|
||||
+ void *opaque, int masked)
|
||||
+{
|
||||
+ VirtQueue *vq = opaque;
|
||||
+ EventNotifier *notifier = virtio_queue_guest_notifier(vq);
|
||||
+ int r = kvm_set_irqfd(dev->msix_irq_entries[vector].gsi,
|
||||
+ event_notifier_get_fd(notifier),
|
||||
+ !masked);
|
||||
+ if (r < 0) {
|
||||
+ return (r == -ENOSYS) ? 0 : r;
|
||||
+ }
|
||||
+ if (masked) {
|
||||
+ qemu_set_fd_handler(event_notifier_get_fd(notifier),
|
||||
+ virtio_pci_guest_notifier_read, NULL, vq);
|
||||
+ } else {
|
||||
+ qemu_set_fd_handler(event_notifier_get_fd(notifier),
|
||||
+ NULL, NULL, vq);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int virtio_pci_guest_notifier(void *opaque, int n, bool assign)
|
||||
{
|
||||
VirtIOPCIProxy *proxy = opaque;
|
||||
@@ -412,11 +433,15 @@ static int virtio_pci_guest_notifier(void *opaque, int n, bool assign)
|
||||
|
||||
if (assign) {
|
||||
int r = event_notifier_init(notifier, 0);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
qemu_set_fd_handler(event_notifier_get_fd(notifier),
|
||||
virtio_pci_guest_notifier_read, NULL, vq);
|
||||
+ msix_set_mask_notifier(&proxy->pci_dev,
|
||||
+ virtio_queue_vector(proxy->vdev, n), vq);
|
||||
} else {
|
||||
+ msix_set_mask_notifier(&proxy->pci_dev,
|
||||
+ virtio_queue_vector(proxy->vdev, n), NULL);
|
||||
qemu_set_fd_handler(event_notifier_get_fd(notifier),
|
||||
NULL, NULL, vq);
|
||||
event_notifier_cleanup(notifier);
|
||||
@@ -501,6 +526,8 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
|
||||
|
||||
proxy->pci_dev.config_write = virtio_write_config;
|
||||
|
||||
+ proxy->pci_dev.msix_mask_notifier = virtio_pci_mask_notifier;
|
||||
+
|
||||
size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
|
||||
if (size & (size-1))
|
||||
size = 1 << qemu_fls(size);
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,149 +0,0 @@
|
||||
Rename features->guest_features. This is
|
||||
what they are, avoid confusion with
|
||||
host features which we also need to keep around.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
(cherry picked from commit 704a76fcd24372a683652651b4597f6654084975)
|
||||
---
|
||||
hw/s390-virtio-bus.c | 2 +-
|
||||
hw/syborg_virtio.c | 4 ++--
|
||||
hw/virtio-net.c | 10 +++++-----
|
||||
hw/virtio-pci.c | 4 ++--
|
||||
hw/virtio.c | 8 ++++----
|
||||
hw/virtio.h | 2 +-
|
||||
6 files changed, 15 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
|
||||
index dc154ed..6c0da11 100644
|
||||
--- a/hw/s390-virtio-bus.c
|
||||
+++ b/hw/s390-virtio-bus.c
|
||||
@@ -251,7 +251,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
|
||||
if (vdev->set_features) {
|
||||
vdev->set_features(vdev, features);
|
||||
}
|
||||
- vdev->features = features;
|
||||
+ vdev->guest_features = features;
|
||||
}
|
||||
|
||||
VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus)
|
||||
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
|
||||
index a84206a..fe6fc23 100644
|
||||
--- a/hw/syborg_virtio.c
|
||||
+++ b/hw/syborg_virtio.c
|
||||
@@ -90,7 +90,7 @@ static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
|
||||
ret |= vdev->binding->get_features(s);
|
||||
break;
|
||||
case SYBORG_VIRTIO_GUEST_FEATURES:
|
||||
- ret = vdev->features;
|
||||
+ ret = vdev->guest_features;
|
||||
break;
|
||||
case SYBORG_VIRTIO_QUEUE_BASE:
|
||||
ret = virtio_queue_get_addr(vdev, vdev->queue_sel);
|
||||
@@ -132,7 +132,7 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
|
||||
case SYBORG_VIRTIO_GUEST_FEATURES:
|
||||
if (vdev->set_features)
|
||||
vdev->set_features(vdev, value);
|
||||
- vdev->features = value;
|
||||
+ vdev->guest_features = value;
|
||||
break;
|
||||
case SYBORG_VIRTIO_QUEUE_BASE:
|
||||
if (value == 0)
|
||||
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
|
||||
index 2f201ff..ab20a33 100644
|
||||
--- a/hw/virtio-net.c
|
||||
+++ b/hw/virtio-net.c
|
||||
@@ -768,11 +768,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
|
||||
if (n->has_vnet_hdr) {
|
||||
tap_using_vnet_hdr(n->nic->nc.peer, 1);
|
||||
tap_set_offload(n->nic->nc.peer,
|
||||
- (n->vdev.features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
|
||||
- (n->vdev.features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
|
||||
- (n->vdev.features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
|
||||
- (n->vdev.features >> VIRTIO_NET_F_GUEST_ECN) & 1,
|
||||
- (n->vdev.features >> VIRTIO_NET_F_GUEST_UFO) & 1);
|
||||
+ (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
|
||||
+ (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
|
||||
+ (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
|
||||
+ (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_ECN) & 1,
|
||||
+ (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_UFO) & 1);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
|
||||
index 3594152..c23dbc0 100644
|
||||
--- a/hw/virtio-pci.c
|
||||
+++ b/hw/virtio-pci.c
|
||||
@@ -181,7 +181,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
}
|
||||
if (vdev->set_features)
|
||||
vdev->set_features(vdev, val);
|
||||
- vdev->features = val;
|
||||
+ vdev->guest_features = val;
|
||||
break;
|
||||
case VIRTIO_PCI_QUEUE_PFN:
|
||||
pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
|
||||
@@ -239,7 +239,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
|
||||
ret |= vdev->binding->get_features(proxy);
|
||||
break;
|
||||
case VIRTIO_PCI_GUEST_FEATURES:
|
||||
- ret = vdev->features;
|
||||
+ ret = vdev->guest_features;
|
||||
break;
|
||||
case VIRTIO_PCI_QUEUE_PFN:
|
||||
ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
|
||||
diff --git a/hw/virtio.c b/hw/virtio.c
|
||||
index cecd0dc..c25a5f1 100644
|
||||
--- a/hw/virtio.c
|
||||
+++ b/hw/virtio.c
|
||||
@@ -445,7 +445,7 @@ void virtio_reset(void *opaque)
|
||||
if (vdev->reset)
|
||||
vdev->reset(vdev);
|
||||
|
||||
- vdev->features = 0;
|
||||
+ vdev->guest_features = 0;
|
||||
vdev->queue_sel = 0;
|
||||
vdev->status = 0;
|
||||
vdev->isr = 0;
|
||||
@@ -598,7 +598,7 @@ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
/* Always notify when queue is empty (when feature acknowledge) */
|
||||
if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) &&
|
||||
- (!(vdev->features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
|
||||
+ (!(vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
|
||||
(vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
|
||||
return;
|
||||
|
||||
@@ -625,7 +625,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
|
||||
qemu_put_8s(f, &vdev->status);
|
||||
qemu_put_8s(f, &vdev->isr);
|
||||
qemu_put_be16s(f, &vdev->queue_sel);
|
||||
- qemu_put_be32s(f, &vdev->features);
|
||||
+ qemu_put_be32s(f, &vdev->guest_features);
|
||||
qemu_put_be32(f, vdev->config_len);
|
||||
qemu_put_buffer(f, vdev->config, vdev->config_len);
|
||||
|
||||
@@ -670,7 +670,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
|
||||
features, supported_features);
|
||||
return -1;
|
||||
}
|
||||
- vdev->features = features;
|
||||
+ vdev->guest_features = features;
|
||||
vdev->config_len = qemu_get_be32(f);
|
||||
qemu_get_buffer(f, vdev->config, vdev->config_len);
|
||||
|
||||
diff --git a/hw/virtio.h b/hw/virtio.h
|
||||
index 35532a6..85ef171 100644
|
||||
--- a/hw/virtio.h
|
||||
+++ b/hw/virtio.h
|
||||
@@ -100,7 +100,7 @@ struct VirtIODevice
|
||||
uint8_t status;
|
||||
uint8_t isr;
|
||||
uint16_t queue_sel;
|
||||
- uint32_t features;
|
||||
+ uint32_t guest_features;
|
||||
size_t config_len;
|
||||
void *config;
|
||||
uint16_t config_vector;
|
||||
--
|
||||
1.6.6.144.g5c3af
|
@ -1,63 +0,0 @@
|
||||
From fcb66d7ac2271bcf0b46d6b1ae2d3db38e78bf2b Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Wed, 20 Jan 2010 00:36:56 +0530
|
||||
Subject: [PATCH 6/9] virtio-serial: Add a 'virtserialport' device for generic serial port support
|
||||
|
||||
This commit adds a simple chardev-based serial port. Any data the guest
|
||||
sends is forwarded to the chardev and vice-versa.
|
||||
|
||||
Sample uses for such a device can be obtaining info from the guest like
|
||||
the file systems used, apps installed, etc. for offline usage and
|
||||
logged-in users, clipboard copy-paste, etc. for online usage.
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
hw/virtio-serial.c | 34 ++++++++++++++++++++++++++++++++++
|
||||
1 files changed, 34 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-serial.c b/hw/virtio-serial.c
|
||||
index 9c2c93c..bd44ec6 100644
|
||||
--- a/hw/virtio-serial.c
|
||||
+++ b/hw/virtio-serial.c
|
||||
@@ -110,3 +110,37 @@ static void virtconsole_register(void)
|
||||
virtio_serial_port_qdev_register(&virtconsole_info);
|
||||
}
|
||||
device_init(virtconsole_register)
|
||||
+
|
||||
+/* Generic Virtio Serial Ports */
|
||||
+static int virtserialport_initfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||
+
|
||||
+ port->info = dev->info;
|
||||
+
|
||||
+ if (vcon->chr) {
|
||||
+ qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
|
||||
+ vcon);
|
||||
+ port->info->have_data = flush_buf;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static VirtIOSerialPortInfo virtserialport_info = {
|
||||
+ .qdev.name = "virtserialport",
|
||||
+ .qdev.size = sizeof(VirtConsole),
|
||||
+ .init = virtserialport_initfn,
|
||||
+ .exit = virtconsole_exitfn,
|
||||
+ .qdev.props = (Property[]) {
|
||||
+ DEFINE_PROP_CHR("chardev", VirtConsole, chr),
|
||||
+ DEFINE_PROP_STRING("name", VirtConsole, port.name),
|
||||
+ DEFINE_PROP_END_OF_LIST(),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void virtserialport_register(void)
|
||||
+{
|
||||
+ virtio_serial_port_qdev_register(&virtserialport_info);
|
||||
+}
|
||||
+device_init(virtserialport_register)
|
||||
--
|
||||
1.6.2.5
|
||||
|
@ -1,45 +0,0 @@
|
||||
From 43fa8533e10c478825952d489269d55e5c652c1a Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Wed, 20 Jan 2010 00:36:58 +0530
|
||||
Subject: [PATCH 8/9] virtio-serial: Use MSI vectors for port virtqueues
|
||||
|
||||
This commit enables the use of MSI interrupts for virtqueue
|
||||
notifications for ports. We use nr_ports + 1 (for control channel) msi
|
||||
entries for the ports, as only the in_vq operations need an interrupt on
|
||||
the guest.
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
hw/virtio-pci.c | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
|
||||
index c1a1e4c..4451a63 100644
|
||||
--- a/hw/virtio-pci.c
|
||||
+++ b/hw/virtio-pci.c
|
||||
@@ -497,10 +497,13 @@ static int virtio_serial_init_pci(PCIDevice *pci_dev)
|
||||
if (!vdev) {
|
||||
return -1;
|
||||
}
|
||||
+ vdev->nvectors = proxy->nvectors ? proxy->nvectors
|
||||
+ : proxy->max_virtserial_ports + 1;
|
||||
virtio_init_pci(proxy, vdev,
|
||||
PCI_VENDOR_ID_REDHAT_QUMRANET,
|
||||
PCI_DEVICE_ID_VIRTIO_CONSOLE,
|
||||
proxy->class_code, 0x00);
|
||||
+ proxy->nvectors = vdev->nvectors;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -577,6 +580,7 @@ static PCIDeviceInfo virtio_info[] = {
|
||||
.init = virtio_serial_init_pci,
|
||||
.exit = virtio_exit_pci,
|
||||
.qdev.props = (Property[]) {
|
||||
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 0),
|
||||
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
|
||||
DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, max_virtserial_ports,
|
||||
31),
|
||||
--
|
||||
1.6.2.5
|
||||
|
@ -1,116 +0,0 @@
|
||||
From ed4daf8c7722562ec05e83ec98a4d4d8adf20f7f Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Wed, 20 Jan 2010 00:36:54 +0530
|
||||
Subject: [PATCH 4/9] virtio-serial-bus: Add a port 'name' property for port discovery in guests
|
||||
|
||||
The port 'id' or number is internal state between the guest kernel and
|
||||
our bus implementation. This is invocation-dependent and isn't part of
|
||||
the guest-host ABI.
|
||||
|
||||
To correcly enumerate and map ports between the host and the guest, the
|
||||
'name' property is used.
|
||||
|
||||
Example:
|
||||
|
||||
-device virtserialport,name=org.qemu.port.0
|
||||
|
||||
This invocation will get us a char device in the guest at:
|
||||
|
||||
/dev/virtio-ports/org.qemu.port.0
|
||||
|
||||
which can be a symlink to
|
||||
|
||||
/dev/vport0p3
|
||||
|
||||
This 'name' property is exposed by the guest kernel in a sysfs
|
||||
attribute:
|
||||
|
||||
/sys/kernel/virtio-ports/vport0p3/name
|
||||
|
||||
A simple udev script can pick up this name and create the symlink
|
||||
mentioned above.
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
hw/virtio-serial-bus.c | 17 +++++++++++++++++
|
||||
hw/virtio-serial.c | 1 +
|
||||
hw/virtio-serial.h | 8 ++++++++
|
||||
3 files changed, 26 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
|
||||
index 9af21df..6d69c56 100644
|
||||
--- a/hw/virtio-serial-bus.c
|
||||
+++ b/hw/virtio-serial-bus.c
|
||||
@@ -204,6 +204,8 @@ static void handle_control_message(VirtIOSerial *vser, void *buf)
|
||||
{
|
||||
struct VirtIOSerialPort *port;
|
||||
struct virtio_console_control cpkt, *gcpkt;
|
||||
+ uint8_t *buffer;
|
||||
+ size_t buffer_len;
|
||||
|
||||
gcpkt = buf;
|
||||
port = find_port_by_id(vser, ldl_p(&gcpkt->id));
|
||||
@@ -226,6 +228,21 @@ static void handle_control_message(VirtIOSerial *vser, void *buf)
|
||||
send_control_event(port, VIRTIO_CONSOLE_CONSOLE_PORT, 1);
|
||||
}
|
||||
|
||||
+ if (port->name) {
|
||||
+ stw_p(&cpkt.event, VIRTIO_CONSOLE_PORT_NAME);
|
||||
+ stw_p(&cpkt.value, 1);
|
||||
+
|
||||
+ buffer_len = sizeof(cpkt) + strlen(port->name) + 1;
|
||||
+ buffer = qemu_malloc(buffer_len);
|
||||
+
|
||||
+ memcpy(buffer, &cpkt, sizeof(cpkt));
|
||||
+ memcpy(buffer + sizeof(cpkt), port->name, strlen(port->name));
|
||||
+ buffer[buffer_len - 1] = 0;
|
||||
+
|
||||
+ send_control_msg(port, buffer, buffer_len);
|
||||
+ qemu_free(buffer);
|
||||
+ }
|
||||
+
|
||||
if (port->host_connected) {
|
||||
send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
|
||||
}
|
||||
diff --git a/hw/virtio-serial.c b/hw/virtio-serial.c
|
||||
index 1dc031e..9c2c93c 100644
|
||||
--- a/hw/virtio-serial.c
|
||||
+++ b/hw/virtio-serial.c
|
||||
@@ -100,6 +100,7 @@ static VirtIOSerialPortInfo virtconsole_info = {
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_PROP_UINT8("is_console", VirtConsole, port.is_console, 1),
|
||||
DEFINE_PROP_CHR("chardev", VirtConsole, chr),
|
||||
+ DEFINE_PROP_STRING("name", VirtConsole, port.name),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
},
|
||||
};
|
||||
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
|
||||
index d9c7acb..28ea7da 100644
|
||||
--- a/hw/virtio-serial.h
|
||||
+++ b/hw/virtio-serial.h
|
||||
@@ -50,6 +50,7 @@ struct virtio_console_control {
|
||||
#define VIRTIO_CONSOLE_CONSOLE_PORT 1
|
||||
#define VIRTIO_CONSOLE_RESIZE 2
|
||||
#define VIRTIO_CONSOLE_PORT_OPEN 3
|
||||
+#define VIRTIO_CONSOLE_PORT_NAME 4
|
||||
|
||||
/* == In-qemu interface == */
|
||||
|
||||
@@ -84,6 +85,13 @@ struct VirtIOSerialPort {
|
||||
VirtQueue *ivq, *ovq;
|
||||
|
||||
/*
|
||||
+ * This name is sent to the guest and exported via sysfs.
|
||||
+ * The guest could create symlinks based on this information.
|
||||
+ * The name is in the reverse fqdn format, like org.qemu.console.0
|
||||
+ */
|
||||
+ char *name;
|
||||
+
|
||||
+ /*
|
||||
* This id helps identify ports between the guest and the host.
|
||||
* The guest sends a "header" with this id with each data packet
|
||||
* that it sends and the host can then find out which associated
|
||||
--
|
||||
1.6.2.5
|
||||
|
@ -1,40 +0,0 @@
|
||||
From c101ff585d5b156a1f3461015a9acd73f15a45f6 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Wed, 20 Jan 2010 00:36:55 +0530
|
||||
Subject: [PATCH 5/9] virtio-serial-bus: Add ability to hot-unplug ports
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
hw/virtio-serial-bus.c | 2 ++
|
||||
hw/virtio-serial.h | 1 +
|
||||
2 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
|
||||
index 6d69c56..037864f 100644
|
||||
--- a/hw/virtio-serial-bus.c
|
||||
+++ b/hw/virtio-serial-bus.c
|
||||
@@ -517,6 +517,8 @@ static int virtser_port_qdev_exit(DeviceState *qdev)
|
||||
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
VirtIOSerial *vser = port->vser;
|
||||
|
||||
+ send_control_event(port, VIRTIO_CONSOLE_PORT_REMOVE, 1);
|
||||
+
|
||||
/*
|
||||
* Don't decrement nr_ports here; thus we keep a linearly
|
||||
* increasing port id. Not utilising an id again saves us a couple
|
||||
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
|
||||
index 28ea7da..f297b00 100644
|
||||
--- a/hw/virtio-serial.h
|
||||
+++ b/hw/virtio-serial.h
|
||||
@@ -51,6 +51,7 @@ struct virtio_console_control {
|
||||
#define VIRTIO_CONSOLE_RESIZE 2
|
||||
#define VIRTIO_CONSOLE_PORT_OPEN 3
|
||||
#define VIRTIO_CONSOLE_PORT_NAME 4
|
||||
+#define VIRTIO_CONSOLE_PORT_REMOVE 5
|
||||
|
||||
/* == In-qemu interface == */
|
||||
|
||||
--
|
||||
1.6.2.5
|
||||
|
@ -1,232 +0,0 @@
|
||||
From 4945aee74f494cc8a17ce1634b5200eb9ee227d2 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Wed, 20 Jan 2010 00:36:53 +0530
|
||||
Subject: [PATCH 3/9] virtio-serial-bus: Maintain guest and host port open/close state
|
||||
|
||||
Via control channel messages, the guest can tell us whether a port got
|
||||
opened or closed. Similarly, we can also indicate to the guest of host
|
||||
port open/close events.
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
hw/virtio-serial-bus.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
hw/virtio-serial.h | 6 +++
|
||||
2 files changed, 100 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
|
||||
index 5132c9c..9af21df 100644
|
||||
--- a/hw/virtio-serial-bus.c
|
||||
+++ b/hw/virtio-serial-bus.c
|
||||
@@ -66,6 +66,11 @@ static VirtIOSerialPort *find_port_by_vq(VirtIOSerial *vser, VirtQueue *vq)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static bool use_multiport(VirtIOSerial *vser)
|
||||
+{
|
||||
+ return vser->vdev.features & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
|
||||
+}
|
||||
+
|
||||
static size_t write_to_port(VirtIOSerialPort *port,
|
||||
const uint8_t *buf, size_t size)
|
||||
{
|
||||
@@ -139,11 +144,22 @@ static size_t send_control_event(VirtIOSerialPort *port, uint16_t event,
|
||||
/* Functions for use inside qemu to open and read from/write to ports */
|
||||
int virtio_serial_open(VirtIOSerialPort *port)
|
||||
{
|
||||
+ /* Don't allow opening an already-open port */
|
||||
+ if (port->host_connected) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ /* Send port open notification to the guest */
|
||||
+ port->host_connected = true;
|
||||
+ send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
int virtio_serial_close(VirtIOSerialPort *port)
|
||||
{
|
||||
+ port->host_connected = false;
|
||||
+ send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -151,6 +167,9 @@ int virtio_serial_close(VirtIOSerialPort *port)
|
||||
ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf,
|
||||
size_t size)
|
||||
{
|
||||
+ if (!port || !port->host_connected || !port->guest_connected) {
|
||||
+ return 0;
|
||||
+ }
|
||||
return write_to_port(port, buf, size);
|
||||
}
|
||||
|
||||
@@ -167,6 +186,9 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port)
|
||||
virtio_queue_empty(vq)) {
|
||||
return 0;
|
||||
}
|
||||
+ if (use_multiport(port->vser) && !port->guest_connected) {
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
if (virtqueue_avail_bytes(vq, 4096, 0)) {
|
||||
return 4096;
|
||||
@@ -203,6 +225,11 @@ static void handle_control_message(VirtIOSerial *vser, void *buf)
|
||||
if (port->is_console) {
|
||||
send_control_event(port, VIRTIO_CONSOLE_CONSOLE_PORT, 1);
|
||||
}
|
||||
+
|
||||
+ if (port->host_connected) {
|
||||
+ send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* When the guest has asked us for this information it means
|
||||
* the guest is all setup and has its virtqueues
|
||||
@@ -213,6 +240,19 @@ static void handle_control_message(VirtIOSerial *vser, void *buf)
|
||||
port->info->guest_ready(port);
|
||||
}
|
||||
break;
|
||||
+
|
||||
+ case VIRTIO_CONSOLE_PORT_OPEN:
|
||||
+ port->guest_connected = cpkt.value;
|
||||
+ if (cpkt.value && port->info->guest_open) {
|
||||
+ /* Send the guest opened notification if an app is interested */
|
||||
+ port->info->guest_open(port);
|
||||
+ }
|
||||
+
|
||||
+ if (!cpkt.value && port->info->guest_close) {
|
||||
+ /* Send the guest closed notification if an app is interested */
|
||||
+ port->info->guest_close(port);
|
||||
+ }
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,6 +340,8 @@ static void set_config(VirtIODevice *vdev, const uint8_t *config_data)
|
||||
static void virtio_serial_save(QEMUFile *f, void *opaque)
|
||||
{
|
||||
VirtIOSerial *s = opaque;
|
||||
+ VirtIOSerialPort *port;
|
||||
+ uint32_t nr_active_ports;
|
||||
|
||||
/* The virtio device */
|
||||
virtio_save(&s->vdev, f);
|
||||
@@ -308,15 +350,41 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
|
||||
qemu_put_be16s(f, &s->config.cols);
|
||||
qemu_put_be16s(f, &s->config.rows);
|
||||
qemu_put_be32s(f, &s->config.nr_ports);
|
||||
+
|
||||
+ /* Items in struct VirtIOSerial */
|
||||
+
|
||||
+ /* Do this because we might have hot-unplugged some ports */
|
||||
+ nr_active_ports = 0;
|
||||
+ QTAILQ_FOREACH(port, &s->ports, next)
|
||||
+ nr_active_ports++;
|
||||
+
|
||||
+ qemu_put_be32s(f, &nr_active_ports);
|
||||
+
|
||||
+ /*
|
||||
+ * Items in struct VirtIOSerialPort.
|
||||
+ */
|
||||
+ QTAILQ_FOREACH(port, &s->ports, next) {
|
||||
+ /*
|
||||
+ * We put the port number because we may not have an active
|
||||
+ * port at id 0 that's reserved for a console port, or in case
|
||||
+ * of ports that might have gotten unplugged
|
||||
+ */
|
||||
+ qemu_put_be32s(f, &port->id);
|
||||
+ qemu_put_byte(f, port->guest_connected);
|
||||
+ }
|
||||
}
|
||||
|
||||
static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
VirtIOSerial *s = opaque;
|
||||
+ VirtIOSerialPort *port;
|
||||
+ uint32_t nr_active_ports;
|
||||
+ unsigned int i;
|
||||
|
||||
if (version_id > 2) {
|
||||
return -EINVAL;
|
||||
}
|
||||
+
|
||||
/* The virtio device */
|
||||
virtio_load(&s->vdev, f);
|
||||
|
||||
@@ -329,6 +397,20 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
|
||||
qemu_get_be16s(f, &s->config.rows);
|
||||
s->config.nr_ports = qemu_get_be32(f);
|
||||
|
||||
+ /* Items in struct VirtIOSerial */
|
||||
+
|
||||
+ qemu_get_be32s(f, &nr_active_ports);
|
||||
+
|
||||
+ /* Items in struct VirtIOSerialPort */
|
||||
+ for (i = 0; i < nr_active_ports; i++) {
|
||||
+ uint32_t id;
|
||||
+
|
||||
+ id = qemu_get_be32(f);
|
||||
+ port = find_port_by_id(s, id);
|
||||
+
|
||||
+ port->guest_connected = qemu_get_byte(f);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -357,6 +439,10 @@ static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
|
||||
|
||||
monitor_printf(mon, "%*s dev-prop-int: id: %u\n",
|
||||
indent, "", port->id);
|
||||
+ monitor_printf(mon, "%*s dev-prop-int: guest_connected: %d\n",
|
||||
+ indent, "", port->guest_connected);
|
||||
+ monitor_printf(mon, "%*s dev-prop-int: host_connected: %d\n",
|
||||
+ indent, "", port->host_connected);
|
||||
}
|
||||
|
||||
static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
|
||||
@@ -390,6 +476,14 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
|
||||
|
||||
port->id = plugging_port0 ? 0 : port->vser->config.nr_ports++;
|
||||
|
||||
+ if (!use_multiport(port->vser)) {
|
||||
+ /*
|
||||
+ * Allow writes to guest in this case; we have no way of
|
||||
+ * knowing if a guest port is connected.
|
||||
+ */
|
||||
+ port->guest_connected = true;
|
||||
+ }
|
||||
+
|
||||
QTAILQ_INSERT_TAIL(&port->vser->ports, port, next);
|
||||
port->ivq = port->vser->ivqs[port->id];
|
||||
port->ovq = port->vser->ovqs[port->id];
|
||||
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
|
||||
index fe8e357..d9c7acb 100644
|
||||
--- a/hw/virtio-serial.h
|
||||
+++ b/hw/virtio-serial.h
|
||||
@@ -49,6 +49,7 @@ struct virtio_console_control {
|
||||
#define VIRTIO_CONSOLE_PORT_READY 0
|
||||
#define VIRTIO_CONSOLE_CONSOLE_PORT 1
|
||||
#define VIRTIO_CONSOLE_RESIZE 2
|
||||
+#define VIRTIO_CONSOLE_PORT_OPEN 3
|
||||
|
||||
/* == In-qemu interface == */
|
||||
|
||||
@@ -92,6 +93,11 @@ struct VirtIOSerialPort {
|
||||
|
||||
/* Identify if this is a port that binds with hvc in the guest */
|
||||
uint8_t is_console;
|
||||
+
|
||||
+ /* Is the corresponding guest device open? */
|
||||
+ bool guest_connected;
|
||||
+ /* Is this device open for IO on the host? */
|
||||
+ bool host_connected;
|
||||
};
|
||||
|
||||
struct VirtIOSerialPortInfo {
|
||||
--
|
||||
1.6.2.5
|
||||
|
@ -1,25 +0,0 @@
|
||||
--- a/hw/virtio-serial-bus.c 2010-02-09 00:41:21.000000000 -0600
|
||||
+++ b/hw/virtio-serial-bus.c 2010-02-09 00:07:13.000000000 -0600
|
||||
@@ -68,7 +68,7 @@ static VirtIOSerialPort *find_port_by_vq
|
||||
|
||||
static bool use_multiport(VirtIOSerial *vser)
|
||||
{
|
||||
- return vser->vdev.features & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
|
||||
+ return vser->vdev.guest_features & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
|
||||
}
|
||||
|
||||
static size_t write_to_port(VirtIOSerialPort *port,
|
||||
@@ -333,9 +333,11 @@ static void handle_input(VirtIODevice *v
|
||||
{
|
||||
}
|
||||
|
||||
-static uint32_t get_features(VirtIODevice *vdev)
|
||||
+static uint32_t get_features(VirtIODevice *vdev, uint32_t features)
|
||||
{
|
||||
- return 1 << VIRTIO_CONSOLE_F_MULTIPORT;
|
||||
+ features |= (1 << VIRTIO_CONSOLE_F_MULTIPORT);
|
||||
+
|
||||
+ return features;
|
||||
}
|
||||
|
||||
/* Guest requested config info */
|
156
qemu.spec
156
qemu.spec
@ -1,6 +1,6 @@
|
||||
Summary: QEMU is a FAST! processor emulator
|
||||
Name: qemu
|
||||
Version: 0.12.5
|
||||
Version: 0.13.0
|
||||
Release: 1%{?dist}
|
||||
# Epoch because we pushed a qemu-1.0 package
|
||||
Epoch: 2
|
||||
@ -12,6 +12,11 @@ URL: http://www.qemu.org/
|
||||
# architecture support (--with x86only):
|
||||
%define with_x86only %{?_with_x86only: 1} %{?!_with_x86only: 0}
|
||||
|
||||
# OOM killer breaks builds with parallel make on s390(x)
|
||||
%ifarch s390 s390x
|
||||
%define _smp_mflags %{nil}
|
||||
%endif
|
||||
|
||||
Source0: http://downloads.sourceforge.net/sourceforge/kvm/qemu-kvm-%{version}.tar.gz
|
||||
Source1: qemu.init
|
||||
|
||||
@ -28,64 +33,12 @@ Source6: ksmtuned.init
|
||||
Source7: ksmtuned
|
||||
Source8: ksmtuned.conf
|
||||
|
||||
# virtio-console changes for the F13 VirtioSerial feature
|
||||
Patch01: qemu-virtio-Remove-duplicate-macro-definition-for-max.-v.patch
|
||||
Patch02: qemu-virtio-console-qdev-conversion-new-virtio-serial-b.patch
|
||||
Patch03: qemu-virtio-serial-bus-Maintain-guest-and-host-port-open.patch
|
||||
Patch04: qemu-virtio-serial-bus-Add-a-port-name-property-for-po.patch
|
||||
Patch05: qemu-virtio-serial-bus-Add-ability-to-hot-unplug-ports.patch
|
||||
Patch06: qemu-virtio-serial-Add-a-virtserialport-device-for-gen.patch
|
||||
Patch07: qemu-Move-virtio-serial-to-Makefile.objs.patch
|
||||
Patch08: qemu-virtio-serial-Use-MSI-vectors-for-port-virtqueues.patch
|
||||
Patch09: qemu-virtio-console-Rename-virtio-serial.c-back-to-virti.patch
|
||||
|
||||
# VHostNet Patches
|
||||
Patch11: qemu-net-add-API-to-disable-enable-polling.patch
|
||||
Patch12: qemu-virtio-rename-features-guest_features.patch
|
||||
Patch13: qemu-qdev-add-bit-property-type.patch
|
||||
Patch14: qemu-qdev-fix-thinko-leading-to-guest-crashes.patch
|
||||
Patch15: qemu-virtio-add-features-as-qdev-properties.patch
|
||||
Patch16: qemu-virtio-net-mac-property-is-mandatory.patch
|
||||
Patch17: qemu-exec-memory-notifiers.patch
|
||||
Patch18: qemu-kvm-add-API-to-set-ioeventfd.patch
|
||||
Patch19: qemu-notifier-event-notifier-implementation.patch
|
||||
Patch20: qemu-virtio-add-notifier-support.patch
|
||||
Patch21: qemu-virtio-add-APIs-for-queue-fields.patch
|
||||
Patch22: qemu-virtio-add-status-change-callback.patch
|
||||
Patch23: qemu-virtio-move-typedef-to-qemu-common.patch
|
||||
Patch24: qemu-virtio-pci-fill-in-notifier-support.patch
|
||||
Patch25: qemu-tap-add-interface-to-get-device-fd.patch
|
||||
Patch26: qemu-vhost-vhost-net-support.patch
|
||||
Patch27: qemu-tap-add-vhost-vhostfd-options.patch
|
||||
Patch28: qemu-tap-add-API-to-retrieve-vhost-net-header.patch
|
||||
Patch29: qemu-virtio-net-vhost-net-support.patch
|
||||
Patch30: qemu-kvm-add-vhost.h-header.patch
|
||||
Patch31: qemu-kvm-irqfd-support.patch
|
||||
Patch32: qemu-msix-add-mask-unmask-notifiers.patch
|
||||
Patch33: qemu-virtio-pci-irqfd-support.patch
|
||||
Patch34: qemu-virtio-avoid-crash-with-non-tap-backends.patch
|
||||
Patch35: qemu-virtio-serial-features-build-fix.patch
|
||||
Patch36: qemu-virtio-pci-irqfd-fix-nonkvm-build.patch
|
||||
Patch37: qemu-vhost-add-configure-check.patch
|
||||
# This patch must be carried through F-15 to support guests created
|
||||
# with F-13/
|
||||
Patch00: pc-add-a-Fedora-13-machine-type-for-backward-compat.patch
|
||||
|
||||
# Fixes from upstream
|
||||
Patch38: 0038-msix-migration-fix.patch
|
||||
Patch39: 0039-vhost-logging-thinko-fix.patch
|
||||
Patch40: 0040-vhost-move-vhost_set_vq_addr.patch
|
||||
Patch41: 0041-vhost-used-addr-migration-fix.patch
|
||||
Patch42: 0042-vhost-fix-used-logging-size-math.patch
|
||||
Patch43: 0043-vhost-logging-mistake-enable-not-disable-log.patch
|
||||
Patch44: 0044-vhost-fix-log-base.patch
|
||||
Patch45: 0045-pc-Add-a-Fedora-13-machine-type-that-contains-backpo.patch
|
||||
Patch46: 0046-pc-Add-backward-compatibility-options-for-virtio-ser.patch
|
||||
Patch47: 0047-virtio-serial-don-t-set-MULTIPORT-for-1-port-dev.patch
|
||||
Patch48: 0048-virtio-serial-pci-Allow-MSI-to-be-disabled.patch
|
||||
Patch49: 0049-migration-Clear-fd-also-in-error-cases.patch
|
||||
Patch50: 0050-raw-posix-Detect-CDROM-via-ioctl-on-linux.patch
|
||||
Patch51: 0051-usb-linux-increase-buffer-for-USB-control-requests.patch
|
||||
Patch52: 0052-virtio-console-patches.patch
|
||||
Patch55: 0055-boot-remove-unused-boot_devices_bitmap-variable.patch
|
||||
|
||||
Patch01: 0001-vhost-net-patches-for-qemu-0.13.0-tarball.patch
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: SDL-devel zlib-devel which texi2html gnutls-devel cyrus-sasl-devel
|
||||
@ -94,6 +47,7 @@ BuildRequires: rsync
|
||||
BuildRequires: pciutils-devel
|
||||
BuildRequires: pulseaudio-libs-devel
|
||||
BuildRequires: ncurses-devel
|
||||
BuildRequires: texinfo
|
||||
Requires: %{name}-user = %{epoch}:%{version}-%{release}
|
||||
Requires: %{name}-system-x86 = %{epoch}:%{version}-%{release}
|
||||
Requires: %{name}-system-sparc = %{epoch}:%{version}-%{release}
|
||||
@ -271,65 +225,14 @@ Group: Development/Tools
|
||||
|
||||
%description kvm-tools
|
||||
This package contains some diagnostics and debugging tools for KVM,
|
||||
such as kvmtrace and kvm_stat.
|
||||
such as kvm_stat.
|
||||
%endif
|
||||
|
||||
%prep
|
||||
%setup -q -n qemu-kvm-%{version}
|
||||
|
||||
%patch00 -p1
|
||||
%patch01 -p1
|
||||
%patch02 -p1
|
||||
%patch03 -p1
|
||||
%patch04 -p1
|
||||
%patch05 -p1
|
||||
%patch06 -p1
|
||||
%patch07 -p1
|
||||
%patch08 -p1
|
||||
%patch09 -p1
|
||||
|
||||
%patch11 -p1
|
||||
%patch12 -p1
|
||||
%patch13 -p1
|
||||
%patch14 -p1
|
||||
%patch15 -p1
|
||||
%patch16 -p1
|
||||
%patch17 -p1
|
||||
%patch18 -p1
|
||||
%patch19 -p1
|
||||
%patch20 -p1
|
||||
%patch21 -p1
|
||||
%patch22 -p1
|
||||
%patch23 -p1
|
||||
%patch24 -p1
|
||||
%patch25 -p1
|
||||
%patch26 -p1
|
||||
%patch27 -p1
|
||||
%patch28 -p1
|
||||
%patch29 -p1
|
||||
%patch30 -p1
|
||||
%patch31 -p1
|
||||
%patch32 -p1
|
||||
%patch33 -p1
|
||||
%patch34 -p1
|
||||
%patch35 -p1
|
||||
%patch36 -p1
|
||||
%patch37 -p1
|
||||
%patch38 -p1
|
||||
%patch39 -p1
|
||||
%patch40 -p1
|
||||
%patch41 -p1
|
||||
%patch42 -p1
|
||||
%patch43 -p1
|
||||
%patch44 -p1
|
||||
%patch45 -p1
|
||||
%patch46 -p1
|
||||
%patch47 -p1
|
||||
%patch48 -p1
|
||||
%patch49 -p1
|
||||
%patch50 -p1
|
||||
%patch51 -p1
|
||||
%patch52 -p1
|
||||
%patch55 -p1
|
||||
|
||||
%build
|
||||
# By default we build everything, but allow x86 to build a minimal version
|
||||
@ -352,16 +255,23 @@ such as kvmtrace and kvm_stat.
|
||||
extraldflags="-Wl,--build-id";
|
||||
buildldflags="VL_LDFLAGS=-Wl,--build-id"
|
||||
|
||||
%ifarch s390
|
||||
# drop -g flag to prevent memory exhaustion by linker
|
||||
%global optflags %(echo %{optflags} | sed 's/-g//')
|
||||
sed -i.debug 's/-g//g' configure
|
||||
%endif
|
||||
|
||||
%ifarch %{ix86} x86_64
|
||||
# sdl outputs to alsa or pulseaudio depending on system config, but it's broken (#495964)
|
||||
# alsa works, but causes huge CPU load due to bugs
|
||||
# oss works, but is very problematic because it grabs exclusive control of the device causing other apps to go haywire
|
||||
./configure --target-list=x86_64-softmmu \
|
||||
--prefix=%{_prefix} \
|
||||
--sysconfdir=%{_sysconfdir} \
|
||||
--audio-drv-list=pa,sdl,alsa,oss \
|
||||
--disable-strip \
|
||||
--extra-ldflags=$extraldflags \
|
||||
--extra-cflags="$RPM_OPT_FLAGS" \
|
||||
--extra-cflags="%{optflags}" \
|
||||
--disable-xen
|
||||
|
||||
echo "config-host.mak contents:"
|
||||
@ -373,22 +283,20 @@ make V=1 %{?_smp_mflags} $buildldflags
|
||||
cp -a x86_64-softmmu/qemu-system-x86_64 qemu-kvm
|
||||
make clean
|
||||
|
||||
cd kvm/user
|
||||
./configure --prefix=%{_prefix} --kerneldir=$(pwd)/../kernel/
|
||||
make kvmtrace
|
||||
cd ../../
|
||||
%endif
|
||||
|
||||
./configure \
|
||||
--target-list="$buildarch" \
|
||||
--prefix=%{_prefix} \
|
||||
--sysconfdir=%{_sysconfdir} \
|
||||
--interp-prefix=%{_prefix}/qemu-%%M \
|
||||
--audio-drv-list=pa,sdl,alsa,oss \
|
||||
--disable-kvm \
|
||||
--disable-strip \
|
||||
--extra-ldflags=$extraldflags \
|
||||
--extra-cflags="$RPM_OPT_FLAGS" \
|
||||
--disable-xen
|
||||
--extra-cflags="%{optflags}" \
|
||||
--disable-xen \
|
||||
--disable-werror
|
||||
|
||||
echo "config-host.mak contents:"
|
||||
echo "==="
|
||||
@ -414,8 +322,6 @@ mkdir -p $RPM_BUILD_ROOT%{_datadir}/%{name}
|
||||
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/udev/rules.d
|
||||
|
||||
install -m 0755 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/modules/kvm.modules
|
||||
install -m 0755 kvm/user/kvmtrace $RPM_BUILD_ROOT%{_bindir}/
|
||||
install -m 0755 kvm/user/kvmtrace_format $RPM_BUILD_ROOT%{_bindir}/
|
||||
install -m 0755 kvm/kvm_stat $RPM_BUILD_ROOT%{_bindir}/
|
||||
install -m 0755 qemu-kvm $RPM_BUILD_ROOT%{_bindir}/
|
||||
install -m 0644 %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/udev/rules.d
|
||||
@ -426,7 +332,8 @@ make prefix="${RPM_BUILD_ROOT}%{_prefix}" \
|
||||
sharedir="${RPM_BUILD_ROOT}%{_datadir}/%{name}" \
|
||||
mandir="${RPM_BUILD_ROOT}%{_mandir}" \
|
||||
docdir="${RPM_BUILD_ROOT}%{_docdir}/%{name}-%{version}" \
|
||||
datadir="${RPM_BUILD_ROOT}%{_datadir}/%{name}" install
|
||||
datadir="${RPM_BUILD_ROOT}%{_datadir}/%{name}" \
|
||||
sysconfdir="${RPM_BUILD_ROOT}%{_sysconfdir}" install
|
||||
chmod -x ${RPM_BUILD_ROOT}%{_mandir}/man1/*
|
||||
install -D -p -m 0755 %{SOURCE1} $RPM_BUILD_ROOT%{_initddir}/qemu
|
||||
install -D -p -m 0644 -t ${RPM_BUILD_ROOT}%{qemudocdir} Changelog README TODO COPYING COPYING.LIB LICENSE
|
||||
@ -435,11 +342,13 @@ install -D -p -m 0644 qemu.sasl $RPM_BUILD_ROOT%{_sysconfdir}/sasl2/qemu.conf
|
||||
|
||||
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/pxe*bin
|
||||
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/vgabios*bin
|
||||
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/gpxe*rom
|
||||
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/bios.bin
|
||||
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/openbios-ppc
|
||||
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/openbios-sparc32
|
||||
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/openbios-sparc64
|
||||
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/petalogix-s3adsp1800.dtb
|
||||
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/s390-zipl.rom
|
||||
%if %{with_x86only}
|
||||
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/bamboo.dtb
|
||||
rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/ppc_rom.bin
|
||||
@ -542,6 +451,7 @@ fi
|
||||
%{_initddir}/ksmtuned
|
||||
%{_sbindir}/ksmtuned
|
||||
%config(noreplace) %{_sysconfdir}/ksmtuned.conf
|
||||
%dir %{_sysconfdir}/qemu
|
||||
%files user
|
||||
%defattr(-,root,root)
|
||||
%{_initddir}/qemu
|
||||
@ -579,6 +489,7 @@ fi
|
||||
%{_datadir}/%{name}/pxe-pcnet.bin
|
||||
%{_datadir}/%{name}/pxe-rtl8139.bin
|
||||
%{_datadir}/%{name}/pxe-ne2k_pci.bin
|
||||
%config(noreplace) %{_sysconfdir}/qemu/target-x86_64.conf
|
||||
%ifarch %{ix86} x86_64
|
||||
%{_datadir}/%{name}/extboot.bin
|
||||
%{_bindir}/qemu-kvm
|
||||
@ -586,8 +497,6 @@ fi
|
||||
%{_sysconfdir}/udev/rules.d/80-kvm.rules
|
||||
%files kvm-tools
|
||||
%defattr(-,root,root,-)
|
||||
%{_bindir}/kvmtrace
|
||||
%{_bindir}/kvmtrace_format
|
||||
%{_bindir}/kvm_stat
|
||||
%endif
|
||||
%if !%{with_x86only}
|
||||
@ -633,6 +542,9 @@ fi
|
||||
%{_mandir}/man1/qemu-img.1*
|
||||
|
||||
%changelog
|
||||
* Thu Mar 03 2011 Justin M. Forbes <jforbes@redhat.com> - 2:0.13.0-1
|
||||
- Update to 0.13.0 to remove 50+ patches and catch several bugfixes.
|
||||
|
||||
* Wed Aug 11 2010 Justin M. Forbes <jforbes@redhat.com> - 2:0.12.5-1
|
||||
- Fix e1000 gpxe rom requires.
|
||||
- Update to 0.12.5 stable for a number of bug fixes.
|
||||
|
Loading…
Reference in New Issue
Block a user