Compare commits
No commits in common. "master" and "qemu-0_12_3-7_fc14" have entirely different histories.
master
...
qemu-0_12_
3
.cvsignore
Normal file
3
.cvsignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
qemu-kvm-0.12.1.2.tar.gz
|
||||||
|
qemu-kvm-0.12.2.tar.gz
|
||||||
|
qemu-kvm-0.12.3.tar.gz
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,4 +0,0 @@
|
|||||||
/.build*.log
|
|
||||||
/x86_64/
|
|
||||||
/*.src.rpm
|
|
||||||
/qemu-*.tar.xz
|
|
43
0038-msix-migration-fix.patch
Normal file
43
0038-msix-migration-fix.patch
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
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
|
||||||
|
|
28
0039-vhost-logging-thinko-fix.patch
Normal file
28
0039-vhost-logging-thinko-fix.patch
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
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
|
||||||
|
|
72
0040-vhost-move-vhost_set_vq_addr.patch
Normal file
72
0040-vhost-move-vhost_set_vq_addr.patch
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
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
|
||||||
|
|
70
0041-vhost-used-addr-migration-fix.patch
Normal file
70
0041-vhost-used-addr-migration-fix.patch
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
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
|
||||||
|
|
37
0042-vhost-fix-used-logging-size-math.patch
Normal file
37
0042-vhost-fix-used-logging-size-math.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
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
|
||||||
|
|
26
0043-vhost-logging-mistake-enable-not-disable-log.patch
Normal file
26
0043-vhost-logging-mistake-enable-not-disable-log.patch
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
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
|
||||||
|
|
38
0044-vhost-fix-log-base.patch
Normal file
38
0044-vhost-fix-log-base.patch
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
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
|
||||||
|
|
@ -0,0 +1,62 @@
|
|||||||
|
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
|
||||||
|
|
@ -0,0 +1,72 @@
|
|||||||
|
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
|
||||||
|
|
39
0047-virtio-serial-don-t-set-MULTIPORT-for-1-port-dev.patch
Normal file
39
0047-virtio-serial-don-t-set-MULTIPORT-for-1-port-dev.patch
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
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
|
||||||
|
|
44
0048-virtio-serial-pci-Allow-MSI-to-be-disabled.patch
Normal file
44
0048-virtio-serial-pci-Allow-MSI-to-be-disabled.patch
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
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
|
||||||
|
|
100
0049-migration-Clear-fd-also-in-error-cases.patch
Normal file
100
0049-migration-Clear-fd-also-in-error-cases.patch
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
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
|
||||||
|
|
61
0050-raw-posix-Detect-CDROM-via-ioctl-on-linux.patch
Normal file
61
0050-raw-posix-Detect-CDROM-via-ioctl-on-linux.patch
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
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
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
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
|
||||||
|
|
936
0052-virtio-console-patches.patch
Normal file
936
0052-virtio-console-patches.patch
Normal file
@ -0,0 +1,936 @@
|
|||||||
|
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
|
||||||
|
|
43
0053-net-remove-NICInfo.bootable-field.patch
Normal file
43
0053-net-remove-NICInfo.bootable-field.patch
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
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
|
||||||
|
|
100
0054-net-remove-broken-net_set_boot_mask-boot-device-vali.patch
Normal file
100
0054-net-remove-broken-net_set_boot_mask-boot-device-vali.patch
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
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
|
||||||
|
|
63
0055-boot-remove-unused-boot_devices_bitmap-variable.patch
Normal file
63
0055-boot-remove-unused-boot_devices_bitmap-variable.patch
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
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
|
||||||
|
|
1
80-kvm.rules
Normal file
1
80-kvm.rules
Normal file
@ -0,0 +1 @@
|
|||||||
|
KERNEL=="kvm", GROUP="kvm", MODE="0666"
|
@ -1,12 +0,0 @@
|
|||||||
# The KVM HV implementation on Power can require a significant amount
|
|
||||||
# of unswappable memory (about half of which also needs to be host
|
|
||||||
# physically contiguous) to hold the guest's Hash Page Table (HPT) -
|
|
||||||
# roughly 1/64th of the guest's RAM size, minimum 16MiB.
|
|
||||||
#
|
|
||||||
# These limits allow unprivileged users to start smallish VMs, such as
|
|
||||||
# those used by libguestfs.
|
|
||||||
#
|
|
||||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1293024
|
|
||||||
#
|
|
||||||
* hard memlock 65536
|
|
||||||
* soft memlock 65536
|
|
@ -1,2 +0,0 @@
|
|||||||
SUBSYSTEM=="virtio-ports", ATTR{name}=="org.qemu.guest_agent.0", \
|
|
||||||
TAG+="systemd" ENV{SYSTEMD_WANTS}="qemu-guest-agent.service"
|
|
21
Makefile
Normal file
21
Makefile
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Makefile for source rpm: qemu
|
||||||
|
# $Id$
|
||||||
|
NAME := qemu
|
||||||
|
SPECFILE = $(firstword $(wildcard *.spec))
|
||||||
|
|
||||||
|
define find-makefile-common
|
||||||
|
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$d/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
|
||||||
|
endef
|
||||||
|
|
||||||
|
MAKEFILE_COMMON := $(shell $(find-makefile-common))
|
||||||
|
|
||||||
|
ifeq ($(MAKEFILE_COMMON),)
|
||||||
|
# attept a checkout
|
||||||
|
define checkout-makefile-common
|
||||||
|
test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2
|
||||||
|
endef
|
||||||
|
|
||||||
|
MAKEFILE_COMMON := $(shell $(checkout-makefile-common))
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(MAKEFILE_COMMON)
|
63
block-vvfat.c-fix-warnings-with-_FORTIFY_SOURCE.patch
Normal file
63
block-vvfat.c-fix-warnings-with-_FORTIFY_SOURCE.patch
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
From e69a45b96be09d25429175fa8f0f85e3d7fab5a8 Mon Sep 17 00:00:00 2001
|
||||||
|
Message-Id: <e69a45b96be09d25429175fa8f0f85e3d7fab5a8.1277191832.git.amit.shah@redhat.com>
|
||||||
|
From: Kirill A. Shutemov <kirill@shutemov.name>
|
||||||
|
Date: Wed, 20 Jan 2010 00:56:14 +0100
|
||||||
|
Subject: [PATCH] block/vvfat.c: fix warnings with _FORTIFY_SOURCE
|
||||||
|
|
||||||
|
CC block/vvfat.o
|
||||||
|
cc1: warnings being treated as errors
|
||||||
|
block/vvfat.c: In function 'commit_one_file':
|
||||||
|
block/vvfat.c:2259: error: ignoring return value of 'ftruncate', declared with attribute warn_unused_result
|
||||||
|
make: *** [block/vvfat.o] Error 1
|
||||||
|
CC block/vvfat.o
|
||||||
|
In file included from /usr/include/stdio.h:912,
|
||||||
|
from ./qemu-common.h:19,
|
||||||
|
from block/vvfat.c:27:
|
||||||
|
In function 'snprintf',
|
||||||
|
inlined from 'init_directories' at block/vvfat.c:871,
|
||||||
|
inlined from 'vvfat_open' at block/vvfat.c:1068:
|
||||||
|
/usr/include/bits/stdio2.h:65: error: call to __builtin___snprintf_chk will always overflow destination buffer
|
||||||
|
make: *** [block/vvfat.o] Error 1
|
||||||
|
|
||||||
|
Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
|
||||||
|
Signed-off-by: Juan Quintela <quintela@redhat.com>
|
||||||
|
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||||
|
(cherry picked from commit 2dedf83ef0cc3463783d6b71bf1b25476f691f3a)
|
||||||
|
|
||||||
|
This fixes Fedora bug 605202.
|
||||||
|
|
||||||
|
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||||
|
---
|
||||||
|
block/vvfat.c | 9 +++++++--
|
||||||
|
1 files changed, 7 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/block/vvfat.c b/block/vvfat.c
|
||||||
|
index c1acb35..592d6e6 100644
|
||||||
|
--- a/block/vvfat.c
|
||||||
|
+++ b/block/vvfat.c
|
||||||
|
@@ -868,7 +868,8 @@ static int init_directories(BDRVVVFATState* s,
|
||||||
|
{
|
||||||
|
direntry_t* entry=array_get_next(&(s->directory));
|
||||||
|
entry->attributes=0x28; /* archive | volume label */
|
||||||
|
- snprintf((char*)entry->name,11,"QEMU VVFAT");
|
||||||
|
+ memcpy(entry->name,"QEMU VVF",8);
|
||||||
|
+ memcpy(entry->extension,"AT ",3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now build FAT, and write back information into directory */
|
||||||
|
@@ -2256,7 +2257,11 @@ static int commit_one_file(BDRVVVFATState* s,
|
||||||
|
c = c1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ftruncate(fd, size);
|
||||||
|
+ if (ftruncate(fd, size)) {
|
||||||
|
+ perror("ftruncate()");
|
||||||
|
+ close(fd);
|
||||||
|
+ return -4;
|
||||||
|
+ }
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return commit_mappings(s, first_cluster, dir_index);
|
||||||
|
--
|
||||||
|
1.7.0.1
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
allow virbr0
|
|
96
ksm.init
Normal file
96
ksm.init
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# ksm Kernel Samepage Merging
|
||||||
|
#
|
||||||
|
# Author: Dan Kenigsberg <danken@redhat.com>
|
||||||
|
#
|
||||||
|
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
|
||||||
|
# Released under the GPL
|
||||||
|
#
|
||||||
|
# chkconfig: 345 84 16
|
||||||
|
# description: The KSM init script starts and stops the ksm kernel thread.
|
||||||
|
# config: /etc/sysconfig/ksm
|
||||||
|
#
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: ksm
|
||||||
|
# Required-Start:
|
||||||
|
# Required-Stop:
|
||||||
|
# Should-Start:
|
||||||
|
# Default-Start: 3 4 5
|
||||||
|
# Short-Description: start and stop ksm
|
||||||
|
# Description: The KSM init script starts and stops the ksm kernel thread.
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
. /etc/rc.d/init.d/functions
|
||||||
|
|
||||||
|
if [ -f /etc/sysconfig/ksm ]; then
|
||||||
|
. /etc/sysconfig/ksm
|
||||||
|
fi
|
||||||
|
|
||||||
|
prog=ksm
|
||||||
|
RETVAL=0
|
||||||
|
|
||||||
|
# unless KSM_MAX_KERNEL_PAGES is set, let ksm munch up to half of total memory.
|
||||||
|
default_max_kernel_pages () {
|
||||||
|
local total pagesize
|
||||||
|
total=`awk '/^MemTotal:/ {print $2}' /proc/meminfo`
|
||||||
|
pagesize=`getconf PAGESIZE`
|
||||||
|
echo $[total * 1024 / pagesize / 2]
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
echo -n $"Starting $prog: "
|
||||||
|
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"
|
||||||
|
echo
|
||||||
|
return $RETVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
echo -n $"Stopping $prog: "
|
||||||
|
echo 0 > /sys/kernel/mm/ksm/run
|
||||||
|
RETVAL=$?
|
||||||
|
[ $RETVAL = 0 ] && success $"$prog shutdown" || failure $"$prog shutdown"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
status() {
|
||||||
|
if [ ! -f /sys/kernel/mm/ksm/run ] ; then
|
||||||
|
echo $"$prog not supported"
|
||||||
|
RETVAL=1
|
||||||
|
else if [ "$(cat /sys/kernel/mm/ksm/run 2>/dev/null)" != "1" ]; then
|
||||||
|
echo $"$prog is not running"
|
||||||
|
RETVAL=1
|
||||||
|
else
|
||||||
|
echo $"$prog is running"
|
||||||
|
RETVAL=0
|
||||||
|
fi; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
condrestart)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo $"Usage: $prog {start|stop|restart|condrestart|status|help}"
|
||||||
|
RETVAL=3
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $RETVAL
|
4
ksm.sysconfig
Normal file
4
ksm.sysconfig
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# The maximum number of unswappable kernel pages
|
||||||
|
# which may be allocated by ksm (0 for unlimited)
|
||||||
|
# If unset, defaults to half of total memory
|
||||||
|
# KSM_MAX_KERNEL_PAGES=
|
137
ksmtuned
Normal file
137
ksmtuned
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
|
||||||
|
# Released under the GPL
|
||||||
|
#
|
||||||
|
# Author: Dan Kenigsberg <danken@redhat.com>
|
||||||
|
#
|
||||||
|
# ksmtuned - a simple script that controls whether (and with what vigor) ksm
|
||||||
|
# should search for duplicated pages.
|
||||||
|
#
|
||||||
|
# starts ksm when memory commited to qemu processes exceeds a threshold, and
|
||||||
|
# make ksm work harder and harder untill memory load falls below that
|
||||||
|
# threshold.
|
||||||
|
#
|
||||||
|
# send SIGUSR1 to this process right after a new qemu process is started, or
|
||||||
|
# following its death, to retune ksm accordingly
|
||||||
|
#
|
||||||
|
# needs testing and ironing. contact danken@redhat.com if something breaks.
|
||||||
|
|
||||||
|
if [ -f /etc/ksmtuned.conf ]; then
|
||||||
|
. /etc/ksmtuned.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
debug() {
|
||||||
|
if [ -n "$DEBUG" ]; then
|
||||||
|
s="`/bin/date`: $*"
|
||||||
|
[ -n "$LOGFILE" ] && echo "$s" >> "$LOGFILE" || echo "$s"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KSM_MONITOR_INTERVAL=${KSM_MONITOR_INTERVAL:-60}
|
||||||
|
KSM_NPAGES_BOOST=${KSM_NPAGES_BOOST:-300}
|
||||||
|
KSM_NPAGES_DECAY=${KSM_NPAGES_DECAY:--50}
|
||||||
|
|
||||||
|
KSM_NPAGES_MIN=${KSM_NPAGES_MIN:-64}
|
||||||
|
KSM_NPAGES_MAX=${KSM_NPAGES_MAX:-1250}
|
||||||
|
# millisecond sleep between ksm scans for 16Gb server. Smaller servers sleep
|
||||||
|
# more, bigger sleep less.
|
||||||
|
KSM_SLEEP_MSEC=${KSM_SLEEP_MSEC:-10}
|
||||||
|
|
||||||
|
KSM_THRES_COEF=${KSM_THRES_COEF:-20}
|
||||||
|
KSM_THRES_CONST=${KSM_THRES_CONST:-2048}
|
||||||
|
|
||||||
|
total=`awk '/^MemTotal:/ {print $2}' /proc/meminfo`
|
||||||
|
debug total $total
|
||||||
|
|
||||||
|
npages=0
|
||||||
|
sleep=$[KSM_SLEEP_MSEC * 16 * 1024 * 1024 / total]
|
||||||
|
[ $sleep -le 10 ] && sleep=10
|
||||||
|
debug sleep $sleep
|
||||||
|
thres=$[total * KSM_THRES_COEF / 100]
|
||||||
|
if [ $KSM_THRES_CONST -gt $thres ]; then
|
||||||
|
thres=$KSM_THRES_CONST
|
||||||
|
fi
|
||||||
|
debug thres $thres
|
||||||
|
|
||||||
|
KSMCTL () {
|
||||||
|
case x$1 in
|
||||||
|
xstop)
|
||||||
|
echo 0 > /sys/kernel/mm/ksm/run
|
||||||
|
;;
|
||||||
|
xstart)
|
||||||
|
echo $2 > /sys/kernel/mm/ksm/pages_to_scan
|
||||||
|
echo $3 > /sys/kernel/mm/ksm/sleep_millisecs
|
||||||
|
echo 1 > /sys/kernel/mm/ksm/run
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
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 }'
|
||||||
|
}
|
||||||
|
|
||||||
|
free_memory () {
|
||||||
|
awk '/^(MemFree|Buffers|MemCached):/ {free += $2}; END {print free}' \
|
||||||
|
/proc/meminfo
|
||||||
|
}
|
||||||
|
|
||||||
|
increase_npages() {
|
||||||
|
local delta
|
||||||
|
delta=${1:-0}
|
||||||
|
npages=$[npages + delta]
|
||||||
|
if [ $npages -lt $KSM_NPAGES_MIN ]; then
|
||||||
|
npages=$KSM_NPAGES_MIN
|
||||||
|
elif [ $npages -gt $KSM_NPAGES_MAX ]; then
|
||||||
|
npages=$KSM_NPAGES_MAX
|
||||||
|
fi
|
||||||
|
echo $npages
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
adjust () {
|
||||||
|
local free committed
|
||||||
|
free=`free_memory`
|
||||||
|
committed=`committed_memory`
|
||||||
|
debug committed $committed free $free
|
||||||
|
if [ $[committed + thres] -lt $total -a $free -gt $thres ]; then
|
||||||
|
KSMCTL stop
|
||||||
|
debug "$[committed + thres] < $total and free > $thres, stop ksm"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
debug "$[committed + thres] > $total, start ksm"
|
||||||
|
if [ $free -lt $thres ]; then
|
||||||
|
npages=`increase_npages $KSM_NPAGES_BOOST`
|
||||||
|
debug "$free < $thres, boost"
|
||||||
|
else
|
||||||
|
npages=`increase_npages $KSM_NPAGES_DECAY`
|
||||||
|
debug "$free > $thres, decay"
|
||||||
|
fi
|
||||||
|
KSMCTL start $npages $sleep
|
||||||
|
debug "KSMCTL start $npages $sleep"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function nothing () {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
loop () {
|
||||||
|
trap nothing SIGUSR1
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
sleep $KSM_MONITOR_INTERVAL &
|
||||||
|
wait $!
|
||||||
|
adjust
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
PIDFILE=${PIDFILE-/var/run/ksmtune.pid}
|
||||||
|
if touch "$PIDFILE"; then
|
||||||
|
loop &
|
||||||
|
echo $! > "$PIDFILE"
|
||||||
|
fi
|
21
ksmtuned.conf
Normal file
21
ksmtuned.conf
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Configuration file for ksmtuned.
|
||||||
|
|
||||||
|
# How long ksmtuned should sleep between tuning adjustments
|
||||||
|
# KSM_MONITOR_INTERVAL=60
|
||||||
|
|
||||||
|
# Millisecond sleep between ksm scans for 16Gb server.
|
||||||
|
# Smaller servers sleep more, bigger sleep less.
|
||||||
|
# KSM_SLEEP_MSEC=10
|
||||||
|
|
||||||
|
# KSM_NPAGES_BOOST=300
|
||||||
|
# KSM_NPAGES_DECAY=-50
|
||||||
|
# KSM_NPAGES_MIN=64
|
||||||
|
# KSM_NPAGES_MAX=1250
|
||||||
|
|
||||||
|
# KSM_THRES_COEF=20
|
||||||
|
# KSM_THRES_CONST=2048
|
||||||
|
|
||||||
|
# uncomment the following if you want ksmtuned debug info
|
||||||
|
|
||||||
|
# LOGFILE=/var/log/ksmtuned
|
||||||
|
# DEBUG=1
|
88
ksmtuned.init
Normal file
88
ksmtuned.init
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# ksmtuned Kernel Samepage Merging (KSM) Tuning Daemon
|
||||||
|
#
|
||||||
|
# Author: Dan Kenigsberg <danken@redhat.com>
|
||||||
|
#
|
||||||
|
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
|
||||||
|
# Released under the GPL
|
||||||
|
#
|
||||||
|
# chkconfig: 345 85 15
|
||||||
|
# description: The KSM tuning daemon controls whether (and with what vigor) \
|
||||||
|
# ksm should ksm search duplicated pages.
|
||||||
|
# processname: ksmtuned
|
||||||
|
# config: /etc/ksmtuned.conf
|
||||||
|
# pidfile: /var/run/ksmtuned.pid
|
||||||
|
#
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: ksmtuned
|
||||||
|
# Required-Start:
|
||||||
|
# Required-Stop:
|
||||||
|
# Should-Start:
|
||||||
|
# Default-Start: 3 4 5
|
||||||
|
# Short-Description: tune the speed of ksm
|
||||||
|
# Description: The Kernel Samepage Merging control Daemon is a simple script
|
||||||
|
# that controls whether (and with what vigor) should ksm search duplicated
|
||||||
|
# memory pages.
|
||||||
|
# needs testing and ironing. contact danken@redhat.com if something breaks.
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
. /etc/rc.d/init.d/functions
|
||||||
|
|
||||||
|
prog=ksmtuned
|
||||||
|
ksmtuned=/usr/sbin/ksmtuned
|
||||||
|
pidfile=${PIDFILE-/var/run/ksmtune.pid}
|
||||||
|
RETVAL=0
|
||||||
|
|
||||||
|
start() {
|
||||||
|
echo -n $"Starting $prog: "
|
||||||
|
daemon --pidfile=${pidfile} $ksmtuned
|
||||||
|
RETVAL=$?
|
||||||
|
echo
|
||||||
|
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
echo -n $"Stopping $prog: "
|
||||||
|
killproc -p ${pidfile}
|
||||||
|
RETVAL=$?
|
||||||
|
echo
|
||||||
|
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
|
||||||
|
}
|
||||||
|
|
||||||
|
restart() {
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
}
|
||||||
|
|
||||||
|
condrestart() {
|
||||||
|
[ -e /var/lock/subsys/$prog ] && restart || :
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status -p ${pidfile} $prog
|
||||||
|
RETVAL=$?
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
restart
|
||||||
|
;;
|
||||||
|
condrestart)
|
||||||
|
condrestart
|
||||||
|
;;
|
||||||
|
retune)
|
||||||
|
kill -SIGUSR1 `cat ${pidfile}`
|
||||||
|
RETVAL=$?
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo $"Usage: $prog {start|stop|restart|condrestart|status|retune|help}"
|
||||||
|
RETVAL=3
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $RETVAL
|
@ -1,11 +0,0 @@
|
|||||||
###
|
|
||||||
### This configuration file was provided by the qemu package.
|
|
||||||
### Feel free to update as needed.
|
|
||||||
###
|
|
||||||
|
|
||||||
###
|
|
||||||
### Set these options to enable nested virtualization
|
|
||||||
###
|
|
||||||
|
|
||||||
#options kvm_intel nested=1
|
|
||||||
#options kvm_amd nested=1
|
|
9
kvm.modules
Executable file
9
kvm.modules
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if [ $(grep -c vmx /proc/cpuinfo) -ne 0 ]; then
|
||||||
|
modprobe -b kvm-intel >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $(grep -c svm /proc/cpuinfo) -ne 0 ]; then
|
||||||
|
modprobe -b kvm-amd >/dev/null 2>&1
|
||||||
|
fi
|
44
qemu-Move-virtio-serial-to-Makefile.objs.patch
Normal file
44
qemu-Move-virtio-serial-to-Makefile.objs.patch
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
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
|
||||||
|
|
199
qemu-exec-memory-notifiers.patch
Normal file
199
qemu-exec-memory-notifiers.patch
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
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
|
135
qemu-fix-linux-user-build-on-ppc.patch
Normal file
135
qemu-fix-linux-user-build-on-ppc.patch
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
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
|
||||||
|
|
140
qemu-fix-qcow2-backing-file-with-virtio.patch
Normal file
140
qemu-fix-qcow2-backing-file-with-virtio.patch
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
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,19 +0,0 @@
|
|||||||
# This is a systemd environment file, not a shell script.
|
|
||||||
# It provides settings for "/lib/systemd/system/qemu-guest-agent.service".
|
|
||||||
|
|
||||||
# Comma-separated blacklist of RPCs to disable, or empty list to enable all.
|
|
||||||
#
|
|
||||||
# You can get the list of RPC commands using "qemu-ga --blacklist='?'".
|
|
||||||
# There should be no spaces between commas and commands in the blacklist.
|
|
||||||
#BLACKLIST_RPC=guest-file-open,guest-file-close,guest-file-read,guest-file-write,guest-file-seek,guest-file-flush,guest-exec,guest-exec-status
|
|
||||||
|
|
||||||
# Fsfreeze hook script specification.
|
|
||||||
#
|
|
||||||
# FSFREEZE_HOOK_PATHNAME=/dev/null : disables the feature.
|
|
||||||
#
|
|
||||||
# FSFREEZE_HOOK_PATHNAME=/path/to/executable : enables the feature with the
|
|
||||||
# specified binary or shell script.
|
|
||||||
#
|
|
||||||
# FSFREEZE_HOOK_PATHNAME= : enables the feature with the
|
|
||||||
# default value (invoke "qemu-ga --help" to interrogate).
|
|
||||||
FSFREEZE_HOOK_PATHNAME=/etc/qemu-ga/fsfreeze-hook
|
|
@ -1,19 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=QEMU Guest Agent
|
|
||||||
BindsTo=dev-virtio\x2dports-org.qemu.guest_agent.0.device
|
|
||||||
After=dev-virtio\x2dports-org.qemu.guest_agent.0.device
|
|
||||||
IgnoreOnIsolate=True
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
UMask=0077
|
|
||||||
EnvironmentFile=/etc/sysconfig/qemu-ga
|
|
||||||
ExecStart=/usr/bin/qemu-ga \
|
|
||||||
--method=virtio-serial \
|
|
||||||
--path=/dev/virtio-ports/org.qemu.guest_agent.0 \
|
|
||||||
--blacklist=${BLACKLIST_RPC} \
|
|
||||||
-F${FSFREEZE_HOOK_PATHNAME}
|
|
||||||
Restart=always
|
|
||||||
RestartSec=0
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=dev-virtio\x2dports-org.qemu.guest_agent.0.device
|
|
81
qemu-kvm-add-API-to-set-ioeventfd.patch
Normal file
81
qemu-kvm-add-API-to-set-ioeventfd.patch
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
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
|
147
qemu-kvm-add-vhost.h-header.patch
Normal file
147
qemu-kvm-add-vhost.h-header.patch
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
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
|
59
qemu-kvm-irqfd-support.patch
Normal file
59
qemu-kvm-irqfd-support.patch
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
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
|
10
qemu-kvm.sh
10
qemu-kvm.sh
@ -1,10 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Libvirt introspects the binary using -M none. In that case, don't try
|
|
||||||
# to init KVM, which will fail and be noisy if the host has kvm disabled
|
|
||||||
opts="-machine accel=kvm"
|
|
||||||
if echo "$@" | grep -q " -M none "; then
|
|
||||||
opts=
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec /usr/bin/qemu-system-x86_64 $opts "$@"
|
|
121
qemu-msix-add-mask-unmask-notifiers.patch
Normal file
121
qemu-msix-add-mask-unmask-notifiers.patch
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
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
|
68
qemu-net-add-API-to-disable-enable-polling.patch
Normal file
68
qemu-net-add-API-to-disable-enable-polling.patch
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
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
|
122
qemu-notifier-event-notifier-implementation.patch
Normal file
122
qemu-notifier-event-notifier-implementation.patch
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
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
|
156
qemu-qdev-add-bit-property-type.patch
Normal file
156
qemu-qdev-add-bit-property-type.patch
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
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
|
24
qemu-qdev-fix-thinko-leading-to-guest-crashes.patch
Normal file
24
qemu-qdev-fix-thinko-leading-to-guest-crashes.patch
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
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
|
37
qemu-tap-add-API-to-retrieve-vhost-net-header.patch
Normal file
37
qemu-tap-add-API-to-retrieve-vhost-net-header.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
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
|
39
qemu-tap-add-interface-to-get-device-fd.patch
Normal file
39
qemu-tap-add-interface-to-get-device-fd.patch
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
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
|
117
qemu-tap-add-vhost-vhostfd-options.patch
Normal file
117
qemu-tap-add-vhost-vhostfd-options.patch
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
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
|
@ -0,0 +1,41 @@
|
|||||||
|
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
|
||||||
|
|
118
qemu-vhost-add-configure-check.patch
Normal file
118
qemu-vhost-add-configure-check.patch
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
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
|
869
qemu-vhost-vhost-net-support.patch
Normal file
869
qemu-vhost-vhost-net-support.patch
Normal file
@ -0,0 +1,869 @@
|
|||||||
|
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
|
@ -0,0 +1,47 @@
|
|||||||
|
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
|
||||||
|
|
111
qemu-virtio-add-APIs-for-queue-fields.patch
Normal file
111
qemu-virtio-add-APIs-for-queue-fields.patch
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
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
|
400
qemu-virtio-add-features-as-qdev-properties.patch
Normal file
400
qemu-virtio-add-features-as-qdev-properties.patch
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
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 */
|
78
qemu-virtio-add-notifier-support.patch
Normal file
78
qemu-virtio-add-notifier-support.patch
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
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
|
76
qemu-virtio-add-status-change-callback.patch
Normal file
76
qemu-virtio-add-status-change-callback.patch
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
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
|
25
qemu-virtio-avoid-crash-with-non-tap-backends.patch
Normal file
25
qemu-virtio-avoid-crash-with-non-tap-backends.patch
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
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
|
341
qemu-virtio-console-Rename-virtio-serial.c-back-to-virti.patch
Normal file
341
qemu-virtio-console-Rename-virtio-serial.c-back-to-virti.patch
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
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
|
||||||
|
|
1366
qemu-virtio-console-qdev-conversion-new-virtio-serial-b.patch
Normal file
1366
qemu-virtio-console-qdev-conversion-new-virtio-serial-b.patch
Normal file
File diff suppressed because it is too large
Load Diff
34
qemu-virtio-move-typedef-to-qemu-common.patch
Normal file
34
qemu-virtio-move-typedef-to-qemu-common.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
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
|
40
qemu-virtio-net-mac-property-is-mandatory.patch
Normal file
40
qemu-virtio-net-mac-property-is-mandatory.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
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
|
153
qemu-virtio-net-vhost-net-support.patch
Normal file
153
qemu-virtio-net-vhost-net-support.patch
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
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
|
98
qemu-virtio-pci-fill-in-notifier-support.patch
Normal file
98
qemu-virtio-pci-fill-in-notifier-support.patch
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
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
|
34
qemu-virtio-pci-irqfd-fix-nonkvm-build.patch
Normal file
34
qemu-virtio-pci-irqfd-fix-nonkvm-build.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
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))
|
70
qemu-virtio-pci-irqfd-support.patch
Normal file
70
qemu-virtio-pci-irqfd-support.patch
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
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
|
149
qemu-virtio-rename-features-guest_features.patch
Normal file
149
qemu-virtio-rename-features-guest_features.patch
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
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
|
63
qemu-virtio-serial-Add-a-virtserialport-device-for-gen.patch
Normal file
63
qemu-virtio-serial-Add-a-virtserialport-device-for-gen.patch
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
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
|
||||||
|
|
45
qemu-virtio-serial-Use-MSI-vectors-for-port-virtqueues.patch
Normal file
45
qemu-virtio-serial-Use-MSI-vectors-for-port-virtqueues.patch
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
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
|
||||||
|
|
116
qemu-virtio-serial-bus-Add-a-port-name-property-for-po.patch
Normal file
116
qemu-virtio-serial-bus-Add-a-port-name-property-for-po.patch
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
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
|
||||||
|
|
40
qemu-virtio-serial-bus-Add-ability-to-hot-unplug-ports.patch
Normal file
40
qemu-virtio-serial-bus-Add-ability-to-hot-unplug-ports.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
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
|
||||||
|
|
232
qemu-virtio-serial-bus-Maintain-guest-and-host-port-open.patch
Normal file
232
qemu-virtio-serial-bus-Maintain-guest-and-host-port-open.patch
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
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
|
||||||
|
|
25
qemu-virtio-serial-features-build-fix.patch
Normal file
25
qemu-virtio-serial-features-build-fix.patch
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
--- 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 */
|
102
qemu.init
Executable file
102
qemu.init
Executable file
@ -0,0 +1,102 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# qemu Allow users to run non-native Linux programs by just clicking on them
|
||||||
|
# (or typing ./file.exe)
|
||||||
|
#
|
||||||
|
# chkconfig: 2345 35 98
|
||||||
|
# description: Allow users to run non-native Linux programs by just clicking \
|
||||||
|
# on them (or typing ./file.exe)
|
||||||
|
|
||||||
|
. /etc/rc.d/init.d/functions
|
||||||
|
RETVAL=0
|
||||||
|
QEMU=/usr/bin
|
||||||
|
|
||||||
|
start() {
|
||||||
|
cpu=`uname -m`
|
||||||
|
case "$cpu" in
|
||||||
|
i386|i486|i586|i686|i86pc|BePC)
|
||||||
|
cpu="i386"
|
||||||
|
;;
|
||||||
|
"Power Macintosh"|ppc|ppc64)
|
||||||
|
cpu="ppc"
|
||||||
|
;;
|
||||||
|
armv4l|armv5l)
|
||||||
|
cpu="arm"
|
||||||
|
;;
|
||||||
|
sh4)
|
||||||
|
cpu="sh4"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo -n $"Registering binary handler for qemu applications"
|
||||||
|
/sbin/modprobe binfmt_misc &>/dev/null
|
||||||
|
if [ "$cpu" != i386 -a -x $QEMU/qemu-i386 -a -d /usr/qemu-i386 ] ; then
|
||||||
|
echo ":qemu-i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-i386:" > /proc/sys/fs/binfmt_misc/register
|
||||||
|
echo ":qemu-i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-i386:" > /proc/sys/fs/binfmt_misc/register
|
||||||
|
fi
|
||||||
|
if [ "$cpu" != arm -a -x $QEMU/qemu-arm -a -d /usr/qemu-arm ] ; then
|
||||||
|
echo ":qemu-arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-arm:" > /proc/sys/fs/binfmt_misc/register
|
||||||
|
fi
|
||||||
|
if [ "$cpu" != ppc -a -x $QEMU/qemu-ppc -a -d /usr/qemu-ppc ] ; then
|
||||||
|
echo ":ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-ppc:" > /proc/sys/fs/binfmt_misc/register
|
||||||
|
echo do ppc
|
||||||
|
fi
|
||||||
|
if [ "$cpu" != sparc -a -x $QEMU/qemu-sparc -a -d /usr/qemu-sparc ] ; then
|
||||||
|
echo ":qemu-sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-sparc:" > /proc/sys/fs/binfmt_misc/register
|
||||||
|
fi
|
||||||
|
if [ "$cpu" != sh4 -a -x $QEMU/qemu-sh4 -a -d /usr/qemu-sh4 ] ; then
|
||||||
|
echo ":qemu-sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-sh4:" > /proc/sys/fs/binfmt_misc/register
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
echo -n $"Unregistering binary handler for qemu applications"
|
||||||
|
for a in i386 i486 ppc arm sparc sh4 ] ; do
|
||||||
|
[ -r /proc/sys/fs/binfmt_misc/qemu-$a ] && echo "-1" >/proc/sys/fs/binfmt_misc/qemu-$a
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_status() {
|
||||||
|
if ls /proc/sys/fs/binfmt_misc/qemu-* &>/dev/null; then
|
||||||
|
echo $"qemu binary format handlers are registered."
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo $"qemu binary format handlers are not registered."
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
qemu_status
|
||||||
|
RETVAL=$?
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
condrestart)
|
||||||
|
if qemu_status &>/dev/null; then
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo $"Usage: $prog {start|stop|status|restart|condrestart}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
exit $RETVAL
|
||||||
|
|
Loading…
Reference in New Issue
Block a user