diff --git a/.gitignore b/.gitignore index ab24db5..9b14986 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ qemu-kvm-0.13.0-25fdf4a.tar.gz /qemu-kvm-0.13.0.tar.gz /qemu-kvm-0.14.0-3593e6b.tar.gz /qemu-kvm-0.14.0-7aa8c46.tar.gz +/qemu-kvm-0.15.0-525e3df.tar.gz diff --git a/0001-qxl-spice-display-move-pipe-to-ssd.patch b/0001-qxl-spice-display-move-pipe-to-ssd.patch deleted file mode 100644 index b542f54..0000000 --- a/0001-qxl-spice-display-move-pipe-to-ssd.patch +++ /dev/null @@ -1,143 +0,0 @@ ->From fd04276a00b172e6fbba3e3c72b1d13a0f179414 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Wed, 16 Mar 2011 15:21:03 +0100 -Subject: [PATCH 1/4] qxl/spice-display: move pipe to ssd - -This moves the int pipe[2] and pthread_t main data from the -PCIQXLDevice struct to the SimpleSpiceDisplay. This will let us -reuse it in the next patch for both -spice with no -qxl usage and -for vga mode from qxl. - -Also move the pipe creation function (which is effectively completely rewritten -by this patch anyways) from hw/qxl.c to ui/spice-display.c, since -spice-display will depend on it after the next patch and qemu can be build -with ui/spice-display.c in combination with no hw/qxl.c. ---- - hw/qxl.c | 22 +++++----------------- - hw/qxl.h | 4 ---- - ui/spice-display.c | 21 +++++++++++++++++++++ - ui/spice-display.h | 8 ++++++++ - 4 files changed, 34 insertions(+), 21 deletions(-) - -diff --git a/hw/qxl.c b/hw/qxl.c -index fe4212b..201698f 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -1062,7 +1062,7 @@ static void pipe_read(void *opaque) - int len; - - do { -- len = read(d->pipe[0], &dummy, sizeof(dummy)); -+ len = read(d->ssd.pipe[0], &dummy, sizeof(dummy)); - } while (len == sizeof(dummy)); - qxl_set_irq(d); - } -@@ -1078,10 +1078,11 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events) - if ((old_pending & le_events) == le_events) { - return; - } -- if (pthread_self() == d->main) { -+ if (pthread_self() == d->ssd.main) { -+ /* running in io_thread thread */ - qxl_set_irq(d); - } else { -- if (write(d->pipe[1], d, 1) != 1) { -+ if (write(d->ssd.pipe[1], d, 1) != 1) { - dprint(d, 1, "%s: write to pipe failed\n", __FUNCTION__); - } - } -@@ -1089,20 +1090,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events) - - static void init_pipe_signaling(PCIQXLDevice *d) - { -- if (pipe(d->pipe) < 0) { -- dprint(d, 1, "%s: pipe creation failed\n", __FUNCTION__); -- return; -- } --#ifdef CONFIG_IOTHREAD -- fcntl(d->pipe[0], F_SETFL, O_NONBLOCK); --#else -- fcntl(d->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */); --#endif -- fcntl(d->pipe[1], F_SETFL, O_NONBLOCK); -- fcntl(d->pipe[0], F_SETOWN, getpid()); -- -- d->main = pthread_self(); -- qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d); -+ qxl_create_server_to_iothread_pipe(&d->ssd, pipe_read); - } - - /* graphics console */ -diff --git a/hw/qxl.h b/hw/qxl.h -index f6c450d..701245f 100644 ---- a/hw/qxl.h -+++ b/hw/qxl.h -@@ -55,10 +55,6 @@ typedef struct PCIQXLDevice { - } guest_surfaces; - QXLPHYSICAL guest_cursor; - -- /* thread signaling */ -- pthread_t main; -- int pipe[2]; -- - /* ram pci bar */ - QXLRam *ram; - VGACommonState vga; -diff --git a/ui/spice-display.c b/ui/spice-display.c -index 020b423..ec6e0cb 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -394,6 +394,27 @@ static DisplayChangeListener display_listener = { - .dpy_refresh = display_refresh, - }; - -+void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd, -+ IOHandler *pipe_read) -+{ -+ if (pipe(ssd->pipe) < 0) { -+ fprintf(stderr, "%s: pipe creation failed\n", __FUNCTION__); -+ return; -+ } -+ -+#ifdef CONFIG_IOTHREAD -+ fcntl(ssd->pipe[0], F_SETFL, O_NONBLOCK); -+#else -+ fcntl(ssd->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */); -+#endif -+ fcntl(ssd->pipe[1], F_SETFL, O_NONBLOCK); -+ -+ fcntl(ssd->pipe[0], F_SETOWN, getpid()); -+ -+ qemu_set_fd_handler(ssd->pipe[0], pipe_read, NULL, ssd); -+ ssd->main = pthread_self(); -+} -+ - void qemu_spice_display_init(DisplayState *ds) - { - assert(sdpy.ds == NULL); -diff --git a/ui/spice-display.h b/ui/spice-display.h -index aef0464..3e6cf7c 100644 ---- a/ui/spice-display.h -+++ b/ui/spice-display.h -@@ -43,6 +43,11 @@ typedef struct SimpleSpiceDisplay { - QXLRect dirty; - int notify; - int running; -+ -+ /* thread signaling - used both in qxl (in vga mode -+ * and in native mode) and without qxl */ -+ pthread_t main; -+ int pipe[2]; /* to iothread */ - } SimpleSpiceDisplay; - - typedef struct SimpleSpiceUpdate { -@@ -66,3 +71,6 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, - int x, int y, int w, int h); - void qemu_spice_display_resize(SimpleSpiceDisplay *ssd); - void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd); -+/* used by both qxl and spice-display */ -+void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd, -+ IOHandler *pipe_read); --- -1.7.3.2 - diff --git a/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch b/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch deleted file mode 100644 index d221d5f..0000000 --- a/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch +++ /dev/null @@ -1,312 +0,0 @@ ->From 97e291086fef45762e0278e85ab1d231a9902bbb Mon Sep 17 00:00:00 2001 -From: Uri Lublin -Date: Wed, 16 Mar 2011 15:43:45 +0100 -Subject: [PATCH 2/4] qxl: implement get_command in vga mode without locks - -This patch and the next drop the requirement to lose the global qemu -mutex during dispatcher calls. This patch enables it, the next drops -the unlock/lock pairs around dispatcher calls. - -The current solution of dropping the locks is buggy: - * it allows multiple dispatcher calls from two vcpu threads, the - dispatcher doesn't handle that by design (single fd, not locked, can't - handle writes from two threads) - * it requires us to keep track of cpu_single_env, which is magic. - -The solution implemented in this patch and the next (the next just -drops the locks, this patch allows that to work): - * the only operation that needed locking was qemu_create_simple_update, - * it required locking because it was called from the spice-server thread. - * do it in the iothread by reusing the existing pipe used for set_irq. - -The current flow implemented is now: -spice-server thread: - qxl.c:interface_get_command (called either by polling or from wakeup) - if update!=NULL: - waiting_for_update=0 - update=NULL - return update - else: - if not waiting_for_update: - waiting_for_update=1 - write to pipe, which is read by iothread (main thread) - -iothread: - wakeup from select, - qxl.c:pipe_read - update=qemu_create_simple_update() - wakeup spice-server thread by calling d.worker->wakeup(d.worker) ---- - hw/qxl.c | 81 +++++++++++++++++++++++++++++++++++++++------------ - ui/spice-display.c | 75 +++++++++++++++++++++++++++++++++++++++++++---- - ui/spice-display.h | 16 ++++++++++ - 3 files changed, 146 insertions(+), 26 deletions(-) - -diff --git a/hw/qxl.c b/hw/qxl.c -index 201698f..64580f1 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -340,7 +340,6 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info) - static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) - { - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); -- SimpleSpiceUpdate *update; - QXLCommandRing *ring; - QXLCommand *cmd; - int notify; -@@ -348,16 +347,25 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) - switch (qxl->mode) { - case QXL_MODE_VGA: - dprint(qxl, 2, "%s: vga\n", __FUNCTION__); -- update = qemu_spice_create_update(&qxl->ssd); -- if (update == NULL) { -- return false; -+ if (qxl_vga_mode_get_command(&qxl->ssd, ext)) { -+ qxl_log_command(qxl, "vga", ext); -+ return true; - } -- *ext = update->ext; -- qxl_log_command(qxl, "vga", ext); -- return true; -+ return false; - case QXL_MODE_COMPAT: - case QXL_MODE_NATIVE: - case QXL_MODE_UNDEFINED: -+ /* flush any existing updates that we didn't send to the guest. -+ * since update != NULL it means the server didn't get it, and -+ * because we changed mode to != QXL_MODE_VGA, it won't. */ -+ if (qxl->ssd.update != NULL) { -+ if (qxl->ssd.update != QXL_EMPTY_UPDATE) { -+ qemu_spice_destroy_update(&qxl->ssd, qxl->ssd.update); -+ } -+ qxl->ssd.update = NULL; -+ qxl->ssd.waiting_for_update = 0; -+ } -+ /* */ - dprint(qxl, 2, "%s: %s\n", __FUNCTION__, - qxl->cmdflags ? "compat" : "native"); - ring = &qxl->ram->cmd_ring; -@@ -1057,17 +1065,50 @@ static void qxl_map(PCIDevice *pci, int region_num, - - static void pipe_read(void *opaque) - { -- PCIQXLDevice *d = opaque; -- char dummy; -- int len; -- -- do { -- len = read(d->ssd.pipe[0], &dummy, sizeof(dummy)); -- } while (len == sizeof(dummy)); -- qxl_set_irq(d); -+ SimpleSpiceDisplay *ssd = opaque; -+ unsigned char cmd; -+ int len, set_irq = 0; -+ int create_update = 0; -+ -+ while (1) { -+ cmd = 0; -+ len = read(ssd->pipe[0], &cmd, sizeof(cmd)); -+ if (len < 0) { -+ if (errno == EINTR) { -+ continue; -+ } -+ if (errno == EAGAIN) { -+ break; -+ } -+ perror("qxl: pipe_read: read failed"); -+ break; -+ } -+ switch (cmd) { -+ case QXL_SERVER_SET_IRQ: -+ set_irq = 1; -+ break; -+ case QXL_SERVER_CREATE_UPDATE: -+ create_update = 1; -+ break; -+ default: -+ fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd); -+ abort(); -+ } -+ } -+ /* no need to do either operation more than once */ -+ if (create_update) { -+ assert(ssd->update == NULL); -+ ssd->update = qemu_spice_create_update(ssd); -+ if (ssd->update == NULL) { -+ ssd->update = QXL_EMPTY_UPDATE; -+ } -+ ssd->worker->wakeup(ssd->worker); -+ } -+ if (set_irq) { -+ qxl_set_irq(container_of(ssd, PCIQXLDevice, ssd)); -+ } - } - --/* called from spice server thread context only */ - static void qxl_send_events(PCIQXLDevice *d, uint32_t events) - { - uint32_t old_pending; -@@ -1082,9 +1123,11 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events) - /* running in io_thread thread */ - qxl_set_irq(d); - } else { -- if (write(d->ssd.pipe[1], d, 1) != 1) { -- dprint(d, 1, "%s: write to pipe failed\n", __FUNCTION__); -- } -+ /* called from spice-server thread */ -+ int ret; -+ unsigned char ack = QXL_SERVER_SET_IRQ; -+ ret = write(d->ssd.pipe[1], &ack, 1); -+ assert(ret == 1); - } - } - -diff --git a/ui/spice-display.c b/ui/spice-display.c -index ec6e0cb..bdd14b8 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -294,18 +294,39 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info) - info->n_surfaces = NUM_SURFACES; - } - -+/* Called from spice server thread context (via interface_get_command) */ -+int qxl_vga_mode_get_command( -+ SimpleSpiceDisplay *ssd, struct QXLCommandExt *ext) -+{ -+ SimpleSpiceUpdate *update; -+ unsigned char req; -+ int r; -+ -+ update = ssd->update; -+ if (update != NULL) { -+ ssd->waiting_for_update = 0; -+ ssd->update = NULL; -+ if (update != QXL_EMPTY_UPDATE) { -+ *ext = update->ext; -+ return true; -+ } -+ } else { -+ if (!ssd->waiting_for_update) { -+ ssd->waiting_for_update = 1; -+ req = QXL_SERVER_CREATE_UPDATE; -+ r = write(ssd->pipe[1], &req , 1); -+ assert(r == 1); -+ } -+ } -+ return false; -+} -+ - static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) - { - SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); -- SimpleSpiceUpdate *update; - - dprint(3, "%s:\n", __FUNCTION__); -- update = qemu_spice_create_update(ssd); -- if (update == NULL) { -- return false; -- } -- *ext = update->ext; -- return true; -+ return qxl_vga_mode_get_command(ssd, ext); - } - - static int interface_req_cmd_notification(QXLInstance *sin) -@@ -394,6 +415,45 @@ static DisplayChangeListener display_listener = { - .dpy_refresh = display_refresh, - }; - -+static void pipe_read(void *opaque) -+{ -+ SimpleSpiceDisplay *ssd = opaque; -+ unsigned char cmd; -+ int len, create_update = 0; -+ -+ while (1) { -+ cmd = 0; -+ len = read(ssd->pipe[0], &cmd, sizeof(cmd)); -+ if (len < 0) { -+ if (errno == EINTR) { -+ continue; -+ } -+ if (errno == EAGAIN) { -+ break; -+ } -+ perror("qxl: pipe_read: read failed"); -+ break; -+ } -+ switch (cmd) { -+ case QXL_SERVER_CREATE_UPDATE: -+ create_update = 1; -+ break; -+ default: -+ fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd); -+ abort(); -+ } -+ } -+ /* no need to do this more than once */ -+ if (create_update) { -+ assert(ssd->update == NULL); -+ ssd->update = qemu_spice_create_update(ssd); -+ if (ssd->update == NULL) { -+ ssd->update = QXL_EMPTY_UPDATE; -+ } -+ ssd->worker->wakeup(ssd->worker); -+ } -+} -+ - void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd, - IOHandler *pipe_read) - { -@@ -427,6 +487,7 @@ void qemu_spice_display_init(DisplayState *ds) - qemu_spice_add_interface(&sdpy.qxl.base); - assert(sdpy.worker); - -+ qxl_create_server_to_iothread_pipe(&sdpy, pipe_read); - qemu_add_vm_change_state_handler(qemu_spice_vm_change_state_handler, &sdpy); - qemu_spice_create_host_memslot(&sdpy); - qemu_spice_create_host_primary(&sdpy); -diff --git a/ui/spice-display.h b/ui/spice-display.h -index 3e6cf7c..2be6a34 100644 ---- a/ui/spice-display.h -+++ b/ui/spice-display.h -@@ -31,6 +31,15 @@ - - #define NUM_SURFACES 1024 - -+/* For commands/requests from server thread to iothread */ -+#define QXL_EMPTY_UPDATE ((void *)-1) -+enum { -+ QXL_SERVER_SET_IRQ = 1, -+ QXL_SERVER_CREATE_UPDATE, -+}; -+ -+struct SimpleSpiceUpdate; -+ - typedef struct SimpleSpiceDisplay { - DisplayState *ds; - void *buf; -@@ -48,6 +57,10 @@ typedef struct SimpleSpiceDisplay { - * and in native mode) and without qxl */ - pthread_t main; - int pipe[2]; /* to iothread */ -+ -+ /* ssd updates (one request/command at a time) */ -+ struct SimpleSpiceUpdate *update; -+ int waiting_for_update; - } SimpleSpiceDisplay; - - typedef struct SimpleSpiceUpdate { -@@ -71,6 +84,9 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, - int x, int y, int w, int h); - void qemu_spice_display_resize(SimpleSpiceDisplay *ssd); - void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd); -+/* shared with qxl.c in vga mode and ui/spice-display (no qxl mode) */ -+int qxl_vga_mode_get_command( -+ SimpleSpiceDisplay *ssd, struct QXLCommandExt *ext); - /* used by both qxl and spice-display */ - void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd, - IOHandler *pipe_read); --- -1.7.3.2 - diff --git a/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch b/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch deleted file mode 100644 index 92a148e..0000000 --- a/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch +++ /dev/null @@ -1,148 +0,0 @@ ->From d413b3c36cbd9820c5b9492b52caa421abccf745 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Wed, 16 Mar 2011 15:46:22 +0100 -Subject: [PATCH 3/4] qxl/spice: remove qemu_mutex_{un,}lock_iothread around dispatcher - -with the previous patch making sure get_command no longer needs to lock, -there is no reason to drop the qemu iothread mutex in qxl.c and in -ui/spice-display.c - -The only location where the lock remains are the cursor related callbacks, -that path is currently broken. It is only triggered if running spice and sdl, -which is broken already before that. ---- - hw/qxl.c | 8 -------- - ui/spice-display.c | 19 +++---------------- - 2 files changed, 3 insertions(+), 24 deletions(-) - -diff --git a/hw/qxl.c b/hw/qxl.c -index 64580f1..cf3c938 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -670,10 +670,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm) - dprint(d, 1, "%s: start%s\n", __FUNCTION__, - loadvm ? " (loadvm)" : ""); - -- qemu_mutex_unlock_iothread(); - d->ssd.worker->reset_cursor(d->ssd.worker); - d->ssd.worker->reset_image_cache(d->ssd.worker); -- qemu_mutex_lock_iothread(); - qxl_reset_surfaces(d); - qxl_reset_memslots(d); - -@@ -803,9 +801,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) - { - dprint(d, 1, "%s:\n", __FUNCTION__); - d->mode = QXL_MODE_UNDEFINED; -- qemu_mutex_unlock_iothread(); - d->ssd.worker->destroy_surfaces(d->ssd.worker); -- qemu_mutex_lock_iothread(); - memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds)); - } - -@@ -874,9 +870,7 @@ static void qxl_destroy_primary(PCIQXLDevice *d) - dprint(d, 1, "%s\n", __FUNCTION__); - - d->mode = QXL_MODE_UNDEFINED; -- qemu_mutex_unlock_iothread(); - d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0); -- qemu_mutex_lock_iothread(); - } - - static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm) -@@ -946,10 +940,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) - case QXL_IO_UPDATE_AREA: - { - QXLRect update = d->ram->update_area; -- qemu_mutex_unlock_iothread(); - d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface, - &update, NULL, 0, 0); -- qemu_mutex_lock_iothread(); - break; - } - case QXL_IO_NOTIFY_CMD: -diff --git a/ui/spice-display.c b/ui/spice-display.c -index bdd14b8..ecb22cc 100644 ---- a/ui/spice-display.c -+++ b/ui/spice-display.c -@@ -62,13 +62,7 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r) - dest->right = MAX(dest->right, r->right); - } - --/* -- * Called from spice server thread context (via interface_get_command). -- * -- * We must aquire the global qemu mutex here to make sure the -- * DisplayState (+DisplaySurface) we are accessing doesn't change -- * underneath us. -- */ -+/* Called from io-thread context (via pipe_read) */ - SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) - { - SimpleSpiceUpdate *update; -@@ -78,9 +72,7 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) - uint8_t *src, *dst; - int by, bw, bh; - -- qemu_mutex_lock_iothread(); - if (qemu_spice_rect_is_empty(&ssd->dirty)) { -- qemu_mutex_unlock_iothread(); - return NULL; - }; - -@@ -141,7 +133,6 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) - cmd->data = (intptr_t)drawable; - - memset(&ssd->dirty, 0, sizeof(ssd->dirty)); -- qemu_mutex_unlock_iothread(); - return update; - } - -@@ -169,6 +160,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd) - ssd->worker->add_memslot(ssd->worker, &memslot); - } - -+/* called from iothread (main) or a vcpu-thread */ - void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) - { - QXLDevSurfaceCreate surface; -@@ -186,18 +178,14 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) - surface.mem = (intptr_t)ssd->buf; - surface.group_id = MEMSLOT_GROUP_HOST; - -- qemu_mutex_unlock_iothread(); - ssd->worker->create_primary_surface(ssd->worker, 0, &surface); -- qemu_mutex_lock_iothread(); - } - - void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) - { - dprint(1, "%s:\n", __FUNCTION__); - -- qemu_mutex_unlock_iothread(); - ssd->worker->destroy_primary_surface(ssd->worker, 0); -- qemu_mutex_lock_iothread(); - } - - void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) -@@ -207,9 +195,7 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) - if (running) { - ssd->worker->start(ssd->worker); - } else { -- qemu_mutex_unlock_iothread(); - ssd->worker->stop(ssd->worker); -- qemu_mutex_lock_iothread(); - } - ssd->running = running; - } -@@ -233,6 +219,7 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, - qemu_spice_rect_union(&ssd->dirty, &update_area); - } - -+/* called only from iothread (main) */ - void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) - { - dprint(1, "%s:\n", __FUNCTION__); --- -1.7.3.2 - diff --git a/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch b/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch deleted file mode 100644 index 03daba4..0000000 --- a/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch +++ /dev/null @@ -1,249 +0,0 @@ ->From 1a33e5f2fa6de800047517a6f3251dc7191c97b5 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Wed, 16 Mar 2011 16:02:16 +0100 -Subject: [PATCH 4/4] hw/qxl-render: drop cursor locks, replace with pipe - -Switching locking protection of ds->cursor_set/cursor_move to moving -every call to these functions into the iothread and using the ssd->pipe -to transfer that, adding QXL_SERVER_CURSOR_SET, QXL_SERVER_CURSOR_MOVE. - -This is tested with both -vnc :0 -spice and -sdl -spice. ---- - hw/qxl-render.c | 25 +++++++++----- - hw/qxl.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - hw/qxl.h | 4 ++ - ui/spice-display.h | 13 +++++++- - 4 files changed, 122 insertions(+), 10 deletions(-) - -diff --git a/hw/qxl-render.c b/hw/qxl-render.c -index 58965e0..6759edb 100644 ---- a/hw/qxl-render.c -+++ b/hw/qxl-render.c -@@ -178,7 +178,6 @@ fail: - return NULL; - } - -- - /* called from spice server thread context only */ - void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) - { -@@ -209,18 +208,26 @@ void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) - if (c == NULL) { - c = cursor_builtin_left_ptr(); - } -- qemu_mutex_lock_iothread(); -- qxl->ssd.ds->cursor_define(c); -- qxl->ssd.ds->mouse_set(x, y, 1); -- qemu_mutex_unlock_iothread(); -- cursor_put(c); -+ qxl_server_request_cursor_set(qxl, c, x, y); - break; - case QXL_CURSOR_MOVE: - x = cmd->u.position.x; - y = cmd->u.position.y; -- qemu_mutex_lock_iothread(); -- qxl->ssd.ds->mouse_set(x, y, 1); -- qemu_mutex_unlock_iothread(); -+ qxl_server_request_cursor_move(qxl, x, y); - break; - } - } -+ -+/* called from iothread only (via qxl.c:pipe_read) */ -+void qxl_render_cursor_set(SimpleSpiceDisplay *ssd, QEMUCursor *c, int x, int y) -+{ -+ ssd->ds->cursor_define(c); -+ ssd->ds->mouse_set(x, y, 1); -+ cursor_put(c); -+} -+ -+/* called from iothread only (via qxl.c:pipe_read) */ -+void qxl_render_cursor_move(SimpleSpiceDisplay *ssd, int x, int y) -+{ -+ ssd->ds->mouse_set(x, y, 1); -+} -diff --git a/hw/qxl.c b/hw/qxl.c -index cf3c938..4c27deb 100644 ---- a/hw/qxl.c -+++ b/hw/qxl.c -@@ -117,6 +117,27 @@ static QXLMode qxl_modes[] = { - #endif - }; - -+typedef struct __attribute__ ((__packed__)) { -+ QEMUCursor *c; -+ int x; -+ int y; -+} QXLServerCursorSet; -+ -+typedef struct __attribute__ ((__packed__)) { -+ int x; -+ int y; -+} QXLServerCursorMove; -+ -+typedef struct __attribute__ ((__packed__)) { -+ unsigned char req; -+ QXLServerCursorMove data; -+} QXLServerCursorMoveRequest; -+ -+typedef struct __attribute__ ((__packed__)) { -+ unsigned char req; -+ QXLServerCursorSet data; -+} QXLServerCursorSetRequest; -+ - static PCIQXLDevice *qxl0; - - static void qxl_send_events(PCIQXLDevice *d, uint32_t events); -@@ -337,6 +358,33 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info) - } - - /* called from spice server thread context only */ -+void qxl_server_request_cursor_set(PCIQXLDevice *qxl, QEMUCursor *c, int x, int y) -+{ -+ QXLServerCursorSetRequest req; -+ int r; -+ -+ req.req = QXL_SERVER_CURSOR_SET; -+ req.data.c = c; -+ req.data.x = x; -+ req.data.y = y; -+ r = write(qxl->ssd.pipe[1], &req, sizeof(req)); -+ assert(r == sizeof(req)); -+} -+ -+/* called from spice server thread context only */ -+void qxl_server_request_cursor_move(PCIQXLDevice *qxl, int x, int y) -+{ -+ QXLServerCursorMoveRequest req; -+ int r; -+ -+ req.req = QXL_SERVER_CURSOR_MOVE; -+ req.data.x = x; -+ req.data.y = y; -+ r = write(qxl->ssd.pipe[1], &req, sizeof(req)); -+ assert(r == sizeof(req)); -+} -+ -+/* called from spice server thread context only */ - static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) - { - PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); -@@ -1055,12 +1103,37 @@ static void qxl_map(PCIDevice *pci, int region_num, - } - } - -+static void read_bytes(int fd, void *buf, int len_requested) -+{ -+ int len; -+ int total_len = 0; -+ -+ do { -+ len = read(fd, buf, len_requested - total_len); -+ if (len < 0) { -+ if (errno == EINTR || errno == EAGAIN) { -+ continue; -+ } -+ perror("qxl: pipe_read: read failed"); -+ /* will abort once it's out of the while loop */ -+ break; -+ } -+ total_len += len; -+ buf = (uint8_t *)buf + len; -+ } while (total_len < len_requested); -+ assert(total_len == len_requested); -+} -+ - static void pipe_read(void *opaque) - { - SimpleSpiceDisplay *ssd = opaque; - unsigned char cmd; - int len, set_irq = 0; - int create_update = 0; -+ int cursor_set = 0; -+ int cursor_move = 0; -+ QXLServerCursorSet cursor_set_data; -+ QXLServerCursorMove cursor_move_data; - - while (1) { - cmd = 0; -@@ -1082,6 +1155,17 @@ static void pipe_read(void *opaque) - case QXL_SERVER_CREATE_UPDATE: - create_update = 1; - break; -+ case QXL_SERVER_CURSOR_SET: -+ if (cursor_set == 1) { -+ cursor_put(cursor_set_data.c); -+ } -+ cursor_set = 1; -+ read_bytes(ssd->pipe[0], &cursor_set_data, sizeof(cursor_set_data)); -+ break; -+ case QXL_SERVER_CURSOR_MOVE: -+ cursor_move = 1; -+ read_bytes(ssd->pipe[0], &cursor_move_data, sizeof(cursor_move_data)); -+ break; - default: - fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd); - abort(); -@@ -1099,6 +1183,12 @@ static void pipe_read(void *opaque) - if (set_irq) { - qxl_set_irq(container_of(ssd, PCIQXLDevice, ssd)); - } -+ if (cursor_move) { -+ qxl_render_cursor_move(ssd, cursor_move_data.x, cursor_move_data.y); -+ } -+ if (cursor_set) { -+ qxl_render_cursor_set(ssd, cursor_set_data.c, cursor_set_data.x, cursor_set_data.y); -+ } - } - - static void qxl_send_events(PCIQXLDevice *d, uint32_t events) -diff --git a/hw/qxl.h b/hw/qxl.h -index 701245f..f4f99ec 100644 ---- a/hw/qxl.h -+++ b/hw/qxl.h -@@ -93,6 +93,8 @@ typedef struct PCIQXLDevice { - - /* qxl.c */ - void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); -+void qxl_server_request_cursor_set(PCIQXLDevice *qxl, QEMUCursor *c, int x, int y); -+void qxl_server_request_cursor_move(PCIQXLDevice *qxl, int x, int y); - - /* qxl-logger.c */ - void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id); -@@ -102,3 +104,5 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext); - void qxl_render_resize(PCIQXLDevice *qxl); - void qxl_render_update(PCIQXLDevice *qxl); - void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext); -+void qxl_render_cursor_set(SimpleSpiceDisplay *ssd, QEMUCursor *c, int x, int y); -+void qxl_render_cursor_move(SimpleSpiceDisplay *ssd, int x, int y); -diff --git a/ui/spice-display.h b/ui/spice-display.h -index 2be6a34..bbfd689 100644 ---- a/ui/spice-display.h -+++ b/ui/spice-display.h -@@ -31,11 +31,22 @@ - - #define NUM_SURFACES 1024 - --/* For commands/requests from server thread to iothread */ -+/* -+ * Commands/requests from server thread to iothread. -+ * Note that CREATE_UPDATE is used both with qxl and without it (spice-display) -+ * the others are only used with the qxl device. -+ * -+ * SET_IRQ - just the request is sent (1 byte) -+ * CREATE_UPDATE - jus the request is sent (1 byte) -+ * CURSOR_SET - send QXLServerRequestCursorSet -+ * CURSOR_MOVE - send QXLServerRequestCursorMove -+ */ - #define QXL_EMPTY_UPDATE ((void *)-1) - enum { - QXL_SERVER_SET_IRQ = 1, - QXL_SERVER_CREATE_UPDATE, -+ QXL_SERVER_CURSOR_SET, -+ QXL_SERVER_CURSOR_MOVE - }; - - struct SimpleSpiceUpdate; --- -1.7.3.2 - diff --git a/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch b/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch deleted file mode 100644 index 0ec25a0..0000000 --- a/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch +++ /dev/null @@ -1,56 +0,0 @@ ->From b248befcd93bcd713971b15147fcaa217a3d1bb7 Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 21:57:47 +0100 -Subject: [PATCH 05/17] char: Split out tcp socket close code in a separate function - -Signed-off-by: Amit Shah ---- - qemu-char.c | 25 ++++++++++++++++--------- - 1 files changed, 16 insertions(+), 9 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index bd4e944..4b57af9 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -1911,6 +1911,21 @@ typedef struct { - - static void tcp_chr_accept(void *opaque); - -+static void tcp_closed(void *opaque) -+{ -+ CharDriverState *chr = opaque; -+ TCPCharDriver *s = chr->opaque; -+ -+ s->connected = 0; -+ if (s->listen_fd >= 0) { -+ qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); -+ } -+ qemu_set_fd_handler(s->fd, NULL, NULL, NULL); -+ closesocket(s->fd); -+ s->fd = -1; -+ qemu_chr_event(chr, CHR_EVENT_CLOSED); -+} -+ - static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - TCPCharDriver *s = chr->opaque; -@@ -2061,15 +2076,7 @@ static void tcp_chr_read(void *opaque) - len = s->max_size; - size = tcp_chr_recv(chr, (void *)buf, len); - if (size == 0) { -- /* connection closed */ -- s->connected = 0; -- if (s->listen_fd >= 0) { -- qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); -- } -- qemu_set_fd_handler(s->fd, NULL, NULL, NULL); -- closesocket(s->fd); -- s->fd = -1; -- qemu_chr_event(chr, CHR_EVENT_CLOSED); -+ tcp_closed(chr); - } else if (size > 0) { - if (s->do_telnetopt) - tcp_chr_process_IAC_bytes(chr, s, buf, &size); --- -1.7.3.2 - diff --git a/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch b/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch deleted file mode 100644 index 095e7ff..0000000 --- a/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch +++ /dev/null @@ -1,673 +0,0 @@ ->From 003cc09f8fc34e7571ebd4a89ea6aa6324a80b54 Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 20:31:45 +0100 -Subject: [PATCH 06/19] char: Add a QemuChrHandlers struct to initialise chardev handlers - -Instead of passing each handler in the qemu_add_handlers() function, -create a struct of handlers that can be passed to the function instead. - -Signed-off-by: Amit Shah ---- - gdbstub.c | 9 +++++++-- - hw/debugcon.c | 2 +- - hw/escc.c | 9 +++++++-- - hw/etraxfs_ser.c | 13 +++++++++---- - hw/grlib_apbuart.c | 12 +++++++----- - hw/ivshmem.c | 28 ++++++++++++++++++++++------ - hw/mcf_uart.c | 9 +++++++-- - hw/pl011.c | 9 +++++++-- - hw/pxa2xx.c | 13 +++++++++---- - hw/serial.c | 9 +++++++-- - hw/sh_serial.c | 12 +++++++++--- - hw/syborg_serial.c | 9 +++++++-- - hw/usb-serial.c | 9 +++++++-- - hw/virtio-console.c | 9 +++++++-- - hw/xen_console.c | 16 +++++++++++----- - hw/xilinx_uartlite.c | 11 +++++++++-- - monitor.c | 18 ++++++++++++++---- - net/slirp.c | 8 ++++++-- - qemu-char.c | 30 +++++++++++++++++++++--------- - qemu-char.h | 13 +++++++++---- - 20 files changed, 183 insertions(+), 65 deletions(-) - -diff --git a/gdbstub.c b/gdbstub.c -index 14e8b9b..4190ac7 100644 ---- a/gdbstub.c -+++ b/gdbstub.c -@@ -2634,6 +2634,12 @@ static void gdb_sigterm_handler(int signal) - } - #endif - -+static const QemuChrHandlers gdb_handlers = { -+ .fd_can_read = gdb_chr_can_receive, -+ .fd_read = gdb_chr_receive, -+ .fd_event = gdb_chr_event, -+}; -+ - int gdbserver_start(const char *device) - { - GDBState *s; -@@ -2663,8 +2669,7 @@ int gdbserver_start(const char *device) - if (!chr) - return -1; - -- qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, -- gdb_chr_event, NULL); -+ qemu_chr_add_handlers(chr, &gdb_handlers, NULL); - } - - s = gdbserver_state; -diff --git a/hw/debugcon.c b/hw/debugcon.c -index 5ee6821..e79a595 100644 ---- a/hw/debugcon.c -+++ b/hw/debugcon.c -@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s) - exit(1); - } - -- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s); -+ qemu_chr_add_handlers(s->chr, NULL, s); - } - - static int debugcon_isa_initfn(ISADevice *dev) -diff --git a/hw/escc.c b/hw/escc.c -index f6fd919..dfa329a 100644 ---- a/hw/escc.c -+++ b/hw/escc.c -@@ -898,6 +898,12 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq, - sysbus_mmio_map(s, 0, base); - } - -+static const QemuChrHandlers serial_handlers = { -+ .fd_can_read = serial_can_receive, -+ .fd_read = serial_receive1, -+ .fd_event = serial_event, -+}; -+ - static int escc_init1(SysBusDevice *dev) - { - SerialState *s = FROM_SYSBUS(SerialState, dev); -@@ -911,8 +917,7 @@ static int escc_init1(SysBusDevice *dev) - s->chn[i].chn = 1 - i; - s->chn[i].clock = s->frequency / 2; - if (s->chn[i].chr) { -- qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive, -- serial_receive1, serial_event, &s->chn[i]); -+ qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]); - } - } - s->chn[0].otherchn = &s->chn[1]; -diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c -index 2787ebd..406121c 100644 ---- a/hw/etraxfs_ser.c -+++ b/hw/etraxfs_ser.c -@@ -190,6 +190,12 @@ static void serial_event(void *opaque, int event) - - } - -+static const QemuChrHandlers serial_handlers = { -+ .fd_can_read = serial_can_receive, -+ .fd_read = serial_receive, -+ .fd_event = serial_event, -+}; -+ - static int etraxfs_ser_init(SysBusDevice *dev) - { - struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev); -@@ -204,10 +210,9 @@ static int etraxfs_ser_init(SysBusDevice *dev) - DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, R_MAX * 4, ser_regs); - s->chr = qdev_init_chardev(&dev->qdev); -- if (s->chr) -- qemu_chr_add_handlers(s->chr, -- serial_can_receive, serial_receive, -- serial_event, s); -+ if (s->chr) { -+ qemu_chr_add_handlers(s->chr, &serial_handlers, s); -+ } - return 0; - } - -diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c -index 101b150..40d6968 100644 ---- a/hw/grlib_apbuart.c -+++ b/hw/grlib_apbuart.c -@@ -144,16 +144,18 @@ static CPUWriteMemoryFunc * const grlib_apbuart_write[] = { - NULL, NULL, grlib_apbuart_writel, - }; - -+static const QemuChrHandlers grlib_handlers = { -+ .fd_can_read = grlib_apbuart_can_receive, -+ .fd_read = grlib_apbuart_receive, -+ .fd_event = grlib_apbuart_event, -+}; -+ - static int grlib_apbuart_init(SysBusDevice *dev) - { - UART *uart = FROM_SYSBUS(typeof(*uart), dev); - int uart_regs = 0; - -- qemu_chr_add_handlers(uart->chr, -- grlib_apbuart_can_receive, -- grlib_apbuart_receive, -- grlib_apbuart_event, -- uart); -+ qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart); - - sysbus_init_irq(dev, &uart->irq); - -diff --git a/hw/ivshmem.c b/hw/ivshmem.c -index 7b19a81..ef8e5ce 100644 ---- a/hw/ivshmem.c -+++ b/hw/ivshmem.c -@@ -312,6 +312,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) { - msix_notify(pdev, entry->vector); - } - -+static const QemuChrHandlers ivshmem_handlers = { -+ .fd_can_read = ivshmem_can_receive, -+ .fd_read = ivshmem_receive, -+ .fd_event = ivshmem_event, -+}; -+ -+static const QemuChrHandlers ivshmem_msi_handlers = { -+ .fd_can_read = ivshmem_can_receive, -+ .fd_read = fake_irqfd, -+ .fd_event = ivshmem_event, -+}; -+ - static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd, - int vector) - { -@@ -331,11 +343,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd, - s->eventfd_table[vector].pdev = &s->dev; - s->eventfd_table[vector].vector = vector; - -- qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd, -- ivshmem_event, &s->eventfd_table[vector]); -+ qemu_chr_add_handlers(chr, &ivshmem_msi_handlers, -+ &s->eventfd_table[vector]); - } else { -- qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive, -- ivshmem_event, s); -+ qemu_chr_add_handlers(chr, &ivshmem_handlers, s); - } - - return chr; -@@ -666,6 +677,12 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id) - return 0; - } - -+static const QemuChrHandlers ivshmem_server_handlers = { -+ .fd_can_read = ivshmem_can_receive, -+ .fd_read = ivshmem_read, -+ .fd_event = ivshmem_event, -+}; -+ - static int pci_ivshmem_init(PCIDevice *dev) - { - IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev); -@@ -754,8 +771,7 @@ static int pci_ivshmem_init(PCIDevice *dev) - - s->eventfd_chr = qemu_mallocz(s->vectors * sizeof(CharDriverState *)); - -- qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read, -- ivshmem_event, s); -+ qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s); - } else { - /* just map the file immediately, we're not using a server */ - int fd; -diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c -index db57096..9928c11 100644 ---- a/hw/mcf_uart.c -+++ b/hw/mcf_uart.c -@@ -268,6 +268,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size) - mcf_uart_push_byte(s, buf[0]); - } - -+static const QemuChrHandlers mcf_uart_handlers = { -+ .fd_can_read = mcf_uart_can_receive, -+ .fd_read = mcf_uart_receive, -+ .fd_event = mcf_uart_event, -+}; -+ - void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) - { - mcf_uart_state *s; -@@ -276,8 +282,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) - s->chr = chr; - s->irq = irq; - if (chr) { -- qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive, -- mcf_uart_event, s); -+ qemu_chr_add_handlers(chr, &mcf_uart_handlers, s); - } - mcf_uart_reset(s); - return s; -diff --git a/hw/pl011.c b/hw/pl011.c -index 77f0dbf..d93c655 100644 ---- a/hw/pl011.c -+++ b/hw/pl011.c -@@ -286,6 +286,12 @@ static int pl011_load(QEMUFile *f, void *opaque, int version_id) - return 0; - } - -+static const QemuChrHandlers pl011_handlers = { -+ .fd_can_read = pl011_can_receive, -+ .fd_read = pl011_receive, -+ .fd_event = pl011_event, -+}; -+ - static int pl011_init(SysBusDevice *dev, const unsigned char *id) - { - int iomemtype; -@@ -304,8 +310,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id) - s->cr = 0x300; - s->flags = 0x90; - if (s->chr) { -- qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive, -- pl011_event, s); -+ qemu_chr_add_handlers(s->chr, &pl011_handlers, s); - } - register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s); - return 0; -diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c -index d966846..d7ebf33 100644 ---- a/hw/pxa2xx.c -+++ b/hw/pxa2xx.c -@@ -1995,6 +1995,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id) - return 0; - } - -+static const QemuChrHandlers pxa2xx_handlers = { -+ .fd_can_read = pxa2xx_fir_is_empty, -+ .fd_read = pxa2xx_fir_rx, -+ .fd_event = pxa2xx_fir_event, -+}; -+ - static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base, - qemu_irq irq, PXA2xxDMAState *dma, - CharDriverState *chr) -@@ -2013,10 +2019,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base, - pxa2xx_fir_writefn, s, DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(base, 0x1000, iomemtype); - -- if (chr) -- qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty, -- pxa2xx_fir_rx, pxa2xx_fir_event, s); -- -+ if (chr) { -+ qemu_chr_add_handlers(chr, &pxa2xx_handlers, s); -+ } - register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save, - pxa2xx_fir_load, s); - -diff --git a/hw/serial.c b/hw/serial.c -index 2c4af61..65265e2 100644 ---- a/hw/serial.c -+++ b/hw/serial.c -@@ -727,6 +727,12 @@ static void serial_reset(void *opaque) - qemu_irq_lower(s->irq); - } - -+static const QemuChrHandlers serial_handlers = { -+ .fd_can_read = serial_can_receive1, -+ .fd_read = serial_receive1, -+ .fd_event = serial_event, -+}; -+ - static void serial_init_core(SerialState *s) - { - if (!s->chr) { -@@ -741,8 +747,7 @@ static void serial_init_core(SerialState *s) - - qemu_register_reset(serial_reset, s); - -- qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1, -- serial_event, s); -+ qemu_chr_add_handlers(s->chr, &serial_handlers, s); - } - - /* Change the main reference oscillator frequency. */ -diff --git a/hw/sh_serial.c b/hw/sh_serial.c -index 191f4a6..8b6460d 100644 ---- a/hw/sh_serial.c -+++ b/hw/sh_serial.c -@@ -350,6 +350,12 @@ static CPUWriteMemoryFunc * const sh_serial_writefn[] = { - &sh_serial_write, - }; - -+static const QemuChrHandlers sh_serial_handlers = { -+ .fd_can_read = sh_serial_can_receive1, -+ .fd_read = sh_serial_receive1, -+ .fd_event = sh_serial_event, -+}; -+ - void sh_serial_init (target_phys_addr_t base, int feat, - uint32_t freq, CharDriverState *chr, - qemu_irq eri_source, -@@ -389,9 +395,9 @@ void sh_serial_init (target_phys_addr_t base, int feat, - - s->chr = chr; - -- if (chr) -- qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1, -- sh_serial_event, s); -+ if (chr) { -+ qemu_chr_add_handlers(chr, &sh_serial_handlers, s); -+ } - - s->eri = eri_source; - s->rxi = rxi_source; -diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c -index 34ce076..124b636 100644 ---- a/hw/syborg_serial.c -+++ b/hw/syborg_serial.c -@@ -315,6 +315,12 @@ static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id) - return 0; - } - -+static const QemuChrHandlers syborg_serial_handlers = { -+ .fd_can_read = syborg_serial_can_receive, -+ .fd_read = syborg_serial_receive, -+ .fd_event = syborg_serial_event, -+}; -+ - static int syborg_serial_init(SysBusDevice *dev) - { - SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev); -@@ -327,8 +333,7 @@ static int syborg_serial_init(SysBusDevice *dev) - sysbus_init_mmio(dev, 0x1000, iomemtype); - s->chr = qdev_init_chardev(&dev->qdev); - if (s->chr) { -- qemu_chr_add_handlers(s->chr, syborg_serial_can_receive, -- syborg_serial_receive, syborg_serial_event, s); -+ qemu_chr_add_handlers(s->chr, &syborg_serial_handlers, s); - } - if (s->fifo_size <= 0) { - fprintf(stderr, "syborg_serial: fifo too small\n"); -diff --git a/hw/usb-serial.c b/hw/usb-serial.c -index 6763d52..2435d9d 100644 ---- a/hw/usb-serial.c -+++ b/hw/usb-serial.c -@@ -475,6 +475,12 @@ static void usb_serial_event(void *opaque, int event) - } - } - -+static const QemuChrHandlers usb_serial_handlers = { -+ .fd_can_read = usb_serial_can_read, -+ .fd_read = usb_serial_read, -+ .fd_event = usb_serial_event, -+}; -+ - static int usb_serial_initfn(USBDevice *dev) - { - USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev); -@@ -486,8 +492,7 @@ static int usb_serial_initfn(USBDevice *dev) - return -1; - } - -- qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read, -- usb_serial_event, s); -+ qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s); - usb_serial_handle_reset(dev); - return 0; - } -diff --git a/hw/virtio-console.c b/hw/virtio-console.c -index 62624ec..22cf28c 100644 ---- a/hw/virtio-console.c -+++ b/hw/virtio-console.c -@@ -57,13 +57,18 @@ static void chr_event(void *opaque, int event) - } - } - -+static const QemuChrHandlers chr_handlers = { -+ .fd_can_read = chr_can_read, -+ .fd_read = chr_read, -+ .fd_event = chr_event, -+}; -+ - static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev) - { - vcon->port.info = dev->info; - - if (vcon->chr) { -- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, -- vcon); -+ qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon); - vcon->port.info->have_data = flush_buf; - } - return 0; -diff --git a/hw/xen_console.c b/hw/xen_console.c -index d2261f4..8327e4e 100644 ---- a/hw/xen_console.c -+++ b/hw/xen_console.c -@@ -202,6 +202,11 @@ static int con_init(struct XenDevice *xendev) - return 0; - } - -+static const QemuChrHandlers xencons_handlers = { -+ .fd_can_read = xencons_can_receive, -+ .fd_read = xencons_receive, -+}; -+ - static int con_connect(struct XenDevice *xendev) - { - struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); -@@ -222,9 +227,9 @@ static int con_connect(struct XenDevice *xendev) - return -1; - - xen_be_bind_evtchn(&con->xendev); -- if (con->chr) -- qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive, -- NULL, con); -+ if (con->chr) { -+ qemu_chr_add_handlers(con->chr, &xencons_handlers, con); -+ } - - xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n", - con->ring_ref, -@@ -238,8 +243,9 @@ static void con_disconnect(struct XenDevice *xendev) - { - struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); - -- if (con->chr) -- qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL); -+ if (con->chr) { -+ qemu_chr_add_handlers(con->chr, NULL, NULL); -+ } - xen_be_unbind_evtchn(&con->xendev); - - if (con->sring) { -diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c -index 9b94e98..1845577 100644 ---- a/hw/xilinx_uartlite.c -+++ b/hw/xilinx_uartlite.c -@@ -193,6 +193,12 @@ static void uart_event(void *opaque, int event) - - } - -+static const QemuChrHandlers uart_handlers = { -+ .fd_can_read = uart_can_rx, -+ .fd_read = uart_rx, -+ .fd_event = uart_event, -+}; -+ - static int xilinx_uartlite_init(SysBusDevice *dev) - { - struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev); -@@ -206,8 +212,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev) - sysbus_init_mmio(dev, R_MAX * 4, uart_regs); - - s->chr = qdev_init_chardev(&dev->qdev); -- if (s->chr) -- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); -+ if (s->chr) { -+ qemu_chr_add_handlers(s->chr, &uart_handlers, s); -+ } - return 0; - } - -diff --git a/monitor.c b/monitor.c -index 096d42b..a00a233 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -5179,6 +5179,18 @@ static void monitor_event(void *opaque, int event) - * End: - */ - -+static const QemuChrHandlers monitor_handlers = { -+ .fd_can_read = monitor_can_read, -+ .fd_read = monitor_read, -+ .fd_event = monitor_event, -+}; -+ -+static const QemuChrHandlers monitor_control_handlers = { -+ .fd_can_read = monitor_can_read, -+ .fd_read = monitor_control_read, -+ .fd_event = monitor_control_event, -+}; -+ - void monitor_init(CharDriverState *chr, int flags) - { - static int is_first_init = 1; -@@ -5201,12 +5213,10 @@ void monitor_init(CharDriverState *chr, int flags) - if (monitor_ctrl_mode(mon)) { - mon->mc = qemu_mallocz(sizeof(MonitorControl)); - /* Control mode requires special handlers */ -- qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read, -- monitor_control_event, mon); -+ qemu_chr_add_handlers(chr, &monitor_control_handlers, mon); - qemu_chr_set_echo(chr, true); - } else { -- qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, -- monitor_event, mon); -+ qemu_chr_add_handlers(chr, &monitor_handlers, mon); - } - - QLIST_INSERT_HEAD(&mon_list, mon, entry); -diff --git a/net/slirp.c b/net/slirp.c -index b41c60a..437be46 100644 ---- a/net/slirp.c -+++ b/net/slirp.c -@@ -577,6 +577,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size) - slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size); - } - -+static const QemuChrHandlers guestfwd_handlers = { -+ .fd_can_read = guestfwd_can_read, -+ .fd_read = guestfwd_read, -+}; -+ - static int slirp_guestfwd(SlirpState *s, const char *config_str, - int legacy_format) - { -@@ -633,8 +638,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, - fwd->port = port; - fwd->slirp = s->slirp; - -- qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, -- NULL, fwd); -+ qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd); - return 0; - - fail_syntax: -diff --git a/qemu-char.c b/qemu-char.c -index 4b57af9..3a31d8b 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -191,15 +191,22 @@ void qemu_chr_send_event(CharDriverState *s, int event) - s->chr_send_event(s, event); - } - -+static const QemuChrHandlers null_handlers = { -+ /* All handlers are initialised to NULL */ -+}; -+ - void qemu_chr_add_handlers(CharDriverState *s, -- IOCanReadHandler *fd_can_read, -- IOReadHandler *fd_read, -- IOEventHandler *fd_event, -- void *opaque) --{ -- s->chr_can_read = fd_can_read; -- s->chr_read = fd_read; -- s->chr_event = fd_event; -+ const QemuChrHandlers *handlers, void *opaque) -+{ -+ if (!s) { -+ return; -+ } -+ if (!handlers) { -+ handlers = &null_handlers; -+ } -+ s->chr_can_read = handlers->fd_can_read; -+ s->chr_read = handlers->fd_read; -+ s->chr_event = handlers->fd_event; - s->handler_opaque = opaque; - if (s->chr_update_read_handler) - s->chr_update_read_handler(s); -@@ -437,6 +444,12 @@ static void mux_chr_event(void *opaque, int event) - mux_chr_send_event(d, i, event); - } - -+static const QemuChrHandlers mux_chr_handlers = { -+ .fd_can_read = mux_chr_can_read, -+ .fd_read = mux_chr_read, -+ .fd_event = mux_chr_event, -+}; -+ - static void mux_chr_update_read_handler(CharDriverState *chr) - { - MuxDriver *d = chr->opaque; -@@ -451,8 +464,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr) - d->chr_event[d->mux_cnt] = chr->chr_event; - /* Fix up the real driver with mux routines */ - if (d->mux_cnt == 0) { -- qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read, -- mux_chr_event, chr); -+ qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr); - } - if (d->focus != -1) { - mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); -diff --git a/qemu-char.h b/qemu-char.h -index 56d9954..7a1924c 100644 ---- a/qemu-char.h -+++ b/qemu-char.h -@@ -1,6 +1,7 @@ - #ifndef QEMU_CHAR_H - #define QEMU_CHAR_H - -+#include - #include "qemu-common.h" - #include "qemu-queue.h" - #include "qemu-option.h" -@@ -73,6 +74,13 @@ struct CharDriverState { - QTAILQ_ENTRY(CharDriverState) next; - }; - -+typedef struct QemuChrHandlers { -+ IOCanReadHandler *fd_can_read; -+ IOReadHandler *fd_read; -+ IOHandler *fd_write_unblocked; -+ IOEventHandler *fd_event; -+} QemuChrHandlers; -+ - QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename); - CharDriverState *qemu_chr_open_opts(QemuOpts *opts, - void (*init)(struct CharDriverState *s)); -@@ -83,10 +91,7 @@ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...) - GCC_FMT_ATTR(2, 3); - int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len); - void qemu_chr_send_event(CharDriverState *s, int event); --void qemu_chr_add_handlers(CharDriverState *s, -- IOCanReadHandler *fd_can_read, -- IOReadHandler *fd_read, -- IOEventHandler *fd_event, -+void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers, - void *opaque); - int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg); - void qemu_chr_generic_open(CharDriverState *s); --- -1.7.4.1 - diff --git a/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch b/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch deleted file mode 100644 index 336c582..0000000 --- a/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch +++ /dev/null @@ -1,76 +0,0 @@ ->From da7e6cd863ed0cffe885cd2d3639f92c82baf6e2 Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 20:32:58 +0100 -Subject: [PATCH 07/17] iohandlers: Add enable/disable_write_fd_handler() functions - -These will be used to provide a cleaner API for the nonblocking case. - -Signed-off-by: Amit Shah ---- - qemu-char.h | 3 +++ - vl.c | 35 +++++++++++++++++++++++++++++++++++ - 2 files changed, 38 insertions(+), 0 deletions(-) - -diff --git a/qemu-char.h b/qemu-char.h -index 7a1924c..185377c 100644 ---- a/qemu-char.h -+++ b/qemu-char.h -@@ -116,6 +116,9 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr); - - /* async I/O support */ - -+void enable_write_fd_handler(int fd, IOHandler *fd_write); -+void disable_write_fd_handler(int fd); -+ - int qemu_set_fd_handler2(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, -diff --git a/vl.c b/vl.c -index 85c36e3..95f51cb 100644 ---- a/vl.c -+++ b/vl.c -@@ -1044,6 +1044,41 @@ typedef struct IOHandlerRecord { - static QLIST_HEAD(, IOHandlerRecord) io_handlers = - QLIST_HEAD_INITIALIZER(io_handlers); - -+static IOHandlerRecord *find_iohandler(int fd) -+{ -+ IOHandlerRecord *ioh; -+ -+ QLIST_FOREACH(ioh, &io_handlers, next) { -+ if (ioh->fd == fd) { -+ return ioh; -+ } -+ } -+ return NULL; -+} -+ -+void enable_write_fd_handler(int fd, IOHandler *fd_write) -+{ -+ IOHandlerRecord *ioh; -+ -+ ioh = find_iohandler(fd); -+ if (!ioh) { -+ return; -+ } -+ -+ ioh->fd_write = fd_write; -+} -+ -+void disable_write_fd_handler(int fd) -+{ -+ IOHandlerRecord *ioh; -+ -+ ioh = find_iohandler(fd); -+ if (!ioh) { -+ return; -+ } -+ -+ ioh->fd_write = NULL; -+} - - /* XXX: fd_read_poll should be suppressed, but an API change is - necessary in the character devices to suppress fd_can_read(). */ --- -1.7.3.2 - diff --git a/0008-char-Add-framework-for-a-write-unblocked-callback.patch b/0008-char-Add-framework-for-a-write-unblocked-callback.patch deleted file mode 100644 index ab3eb1f..0000000 --- a/0008-char-Add-framework-for-a-write-unblocked-callback.patch +++ /dev/null @@ -1,62 +0,0 @@ ->From daf37480ffe37b3e7a781ff010beb4fa89821c29 Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 21:41:42 +0100 -Subject: [PATCH 08/17] char: Add framework for a 'write unblocked' callback - -The char layer can let users know that the driver will block on further -input. For users interested in not blocking, they can assign a function -pointer that will be called back when the driver becomes writable. This -patch just adds the function pointers to the CharDriverState structure, -future patches will enable the nonblocking and callback functionality. - -Signed-off-by: Amit Shah ---- - qemu-char.c | 3 +++ - qemu-char.h | 5 +++++ - 2 files changed, 8 insertions(+), 0 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index 3a31d8b..ce76411 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -206,11 +206,14 @@ void qemu_chr_add_handlers(CharDriverState *s, - } - s->chr_can_read = handlers->fd_can_read; - s->chr_read = handlers->fd_read; -+ s->chr_write_unblocked = handlers->fd_write_unblocked; - s->chr_event = handlers->fd_event; - s->handler_opaque = opaque; - if (s->chr_update_read_handler) - s->chr_update_read_handler(s); - -+ s->write_blocked = false; -+ - /* We're connecting to an already opened device, so let's make sure we - also get the open event */ - if (s->opened) { -diff --git a/qemu-char.h b/qemu-char.h -index 185377c..bf06da0 100644 ---- a/qemu-char.h -+++ b/qemu-char.h -@@ -61,6 +61,9 @@ struct CharDriverState { - IOEventHandler *chr_event; - IOCanReadHandler *chr_can_read; - IOReadHandler *chr_read; -+ IOHandler *chr_write_unblocked; -+ void (*chr_enable_write_fd_handler)(struct CharDriverState *chr); -+ void (*chr_disable_write_fd_handler)(struct CharDriverState *chr); - void *handler_opaque; - void (*chr_send_event)(struct CharDriverState *chr, int event); - void (*chr_close)(struct CharDriverState *chr); -@@ -71,6 +74,8 @@ struct CharDriverState { - char *label; - char *filename; - int opened; -+ /* Are we in a blocked state? */ -+ bool write_blocked; - QTAILQ_ENTRY(CharDriverState) next; - }; - --- -1.7.3.2 - diff --git a/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch b/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch deleted file mode 100644 index db6f85b..0000000 --- a/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch +++ /dev/null @@ -1,199 +0,0 @@ -From 8f5b96bd3bdd4fe7aa80f2f27d51bece8f64f20f Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 22:00:27 +0100 -Subject: [PATCH 09/30] char: Update send_all() to handle nonblocking chardev - write requests - -The send_all function is modified to return to the caller in case the -driver cannot handle any more data. It returns -EAGAIN or -WSAEWOULDBLOCK on non-Windows and Windows platforms respectively. This -is only done when the caller sets a callback function handler indicating -it's not interested in blocking till the driver has written out all the -data. - -Currently there's no driver or caller that supports this. Future -commits will add such capability. - -Signed-off-by: Amit Shah ---- - net/socket.c | 4 +- - qemu-char.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- - qemu_socket.h | 2 +- - 3 files changed, 77 insertions(+), 9 deletions(-) - -diff --git a/net/socket.c b/net/socket.c -index 3182b37..5dedd78 100644 ---- a/net/socket.c -+++ b/net/socket.c -@@ -56,8 +56,8 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_ - uint32_t len; - len = htonl(size); - -- send_all(s->fd, (const uint8_t *)&len, sizeof(len)); -- return send_all(s->fd, buf, size); -+ send_all(NULL, s->fd, (const uint8_t *)&len, sizeof(len)); -+ return send_all(NULL, s->fd, buf, size); - } - - static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size) -diff --git a/qemu-char.c b/qemu-char.c -index ce76411..3f665c9 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -500,7 +500,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) - - - #ifdef _WIN32 --int send_all(int fd, const void *buf, int len1) -+static int do_send(int fd, const void *buf, int len1, bool nonblock) - { - int ret, len; - -@@ -508,9 +508,14 @@ int send_all(int fd, const void *buf, int len1) - while (len > 0) { - ret = send(fd, buf, len, 0); - if (ret < 0) { -+ if (nonblock && len1 - len) { -+ return len1 - len; -+ } - errno = WSAGetLastError(); - if (errno != WSAEWOULDBLOCK) { - return -1; -+ } else if (errno == WSAEWOULDBLOCK && nonblock) { -+ return WSAEWOULDBLOCK; - } - } else if (ret == 0) { - break; -@@ -524,7 +529,7 @@ int send_all(int fd, const void *buf, int len1) - - #else - --int send_all(int fd, const void *_buf, int len1) -+static int do_send(int fd, const void *_buf, int len1, bool nonblock) - { - int ret, len; - const uint8_t *buf = _buf; -@@ -533,8 +538,15 @@ int send_all(int fd, const void *_buf, int len1) - while (len > 0) { - ret = write(fd, buf, len); - if (ret < 0) { -- if (errno != EINTR && errno != EAGAIN) -+ if (nonblock && len1 - len) { -+ return len1 - len; -+ } -+ if (errno == EAGAIN && nonblock) { -+ return -EAGAIN; -+ } -+ if (errno != EINTR && errno != EAGAIN) { - return -1; -+ } - } else if (ret == 0) { - break; - } else { -@@ -546,6 +558,55 @@ int send_all(int fd, const void *_buf, int len1) - } - #endif /* !_WIN32 */ - -+int send_all(CharDriverState *chr, int fd, const void *_buf, int len1) -+{ -+ int ret, eagain_errno; -+ bool nonblock; -+ -+ if (chr && chr->write_blocked) { -+ /* -+ * We don't handle this situation: the caller should not send -+ * us data while we're blocked. -+ * -+ * We could buffer this data here but that'll only encourage -+ * bad behaviour on part of the callers. -+ * -+ * Also, the data already in fd's buffers isn't easily -+ * migratable. If we want full migration support, all the -+ * data landing here needs to be buffered and on migration, -+ * anything that's unsent needs to be transferred to the -+ * dest. machine (which again isn't a very good way of solving -+ * the problem, as the src may become writable just during -+ * migration and the reader could receive some data twice, -+ * essentially corrupting the data). -+ */ -+ abort(); -+ } -+ -+ nonblock = false; -+ /* -+ * Ensure the char backend is able to receive and handle the -+ * 'write unblocked' event before we turn on nonblock support. -+ */ -+ if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) { -+ nonblock = true; -+ } -+ ret = do_send(fd, _buf, len1, nonblock); -+ -+#ifdef _WIN32 -+ eagain_errno = WSAEWOULDBLOCK; -+#else -+ eagain_errno = -EAGAIN; -+#endif -+ -+ if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) { -+ /* Update fd handler to wake up when chr becomes writable */ -+ chr->chr_enable_write_fd_handler(chr); -+ chr->write_blocked = true; -+ } -+ return ret; -+} -+ - #ifndef _WIN32 - - typedef struct { -@@ -559,7 +620,7 @@ static int stdio_nb_clients = 0; - static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - FDCharDriver *s = chr->opaque; -- return send_all(s->fd_out, buf, len); -+ return send_all(chr, s->fd_out, buf, len); - } - - static int fd_chr_read_poll(void *opaque) -@@ -875,7 +936,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - pty_chr_update_read_handler(chr); - return 0; - } -- return send_all(s->fd, buf, len); -+ return send_all(chr, s->fd, buf, len); - } - - static int pty_chr_read_poll(void *opaque) -@@ -1944,8 +2005,15 @@ static void tcp_closed(void *opaque) - static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - TCPCharDriver *s = chr->opaque; -+ - if (s->connected) { -- return send_all(s->fd, buf, len); -+ int ret; -+ -+ ret = send_all(chr, s->fd, buf, len); -+ if (ret == -1 && errno == EPIPE) { -+ tcp_closed(chr); -+ } -+ return ret; - } else { - /* XXX: indicate an error ? */ - return len; -diff --git a/qemu_socket.h b/qemu_socket.h -index 897a8ae..97dd24a 100644 ---- a/qemu_socket.h -+++ b/qemu_socket.h -@@ -36,7 +36,7 @@ int inet_aton(const char *cp, struct in_addr *ia); - int qemu_socket(int domain, int type, int protocol); - int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); - void socket_set_nonblock(int fd); --int send_all(int fd, const void *buf, int len1); -+int send_all(CharDriverState *chr, int fd, const void *buf, int len1); - - /* New, ipv6-ready socket helper functions, see qemu-sockets.c */ - int inet_listen_opts(QemuOpts *opts, int port_offset); --- -1.7.5 - diff --git a/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch b/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch deleted file mode 100644 index f08d700..0000000 --- a/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch +++ /dev/null @@ -1,80 +0,0 @@ ->From 7d8cbead9454da6dbfdc050c6828faae39621a1b Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 22:02:47 +0100 -Subject: [PATCH 10/17] char: Equip the unix/tcp backend to handle nonblocking writes# - -Now that the infrastructure is in place to return -EAGAIN to callers, -individual char drivers can set their update_fd_handlers() function to -set or remove an fd's write handler. This handler checks if the driver -became writable. - -A generic callback routine is used for unblocking writes and letting -users of chardevs know that a driver became writable again. - -Signed-off-by: Amit Shah ---- - qemu-char.c | 34 ++++++++++++++++++++++++++++++++++ - 1 files changed, 34 insertions(+), 0 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index eed61d6..7517f64 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -107,6 +107,19 @@ - static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs = - QTAILQ_HEAD_INITIALIZER(chardevs); - -+/* -+ * Generic routine that gets called when chardev becomes writable. -+ * Lets chardev user know it's OK to send more data. -+ */ -+static void char_write_unblocked(void *opaque) -+{ -+ CharDriverState *chr = opaque; -+ -+ chr->write_blocked = false; -+ chr->chr_disable_write_fd_handler(chr); -+ chr->chr_write_unblocked(chr->handler_opaque); -+} -+ - static void qemu_chr_event(CharDriverState *s, int event) - { - /* Keep track if the char device is open */ -@@ -2261,6 +2274,25 @@ static void tcp_chr_close(CharDriverState *chr) - qemu_chr_event(chr, CHR_EVENT_CLOSED); - } - -+static void tcp_enable_write_fd_handler(CharDriverState *chr) -+{ -+ TCPCharDriver *s = chr->opaque; -+ -+ /* -+ * This function is called only after tcp_chr_connect() is called -+ * (either in 'server' mode or client mode. So we're sure of -+ * s->fd being initialised. -+ */ -+ enable_write_fd_handler(s->fd, char_write_unblocked); -+} -+ -+static void tcp_disable_write_fd_handler(CharDriverState *chr) -+{ -+ TCPCharDriver *s = chr->opaque; -+ -+ disable_write_fd_handler(s->fd); -+} -+ - static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) - { - CharDriverState *chr = NULL; -@@ -2313,6 +2345,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) - chr->chr_write = tcp_chr_write; - chr->chr_close = tcp_chr_close; - chr->get_msgfd = tcp_get_msgfd; -+ chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler; -+ chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler; - - if (is_listen) { - s->listen_fd = fd; --- -1.7.3.2 - diff --git a/0011-char-Throttle-when-host-connection-is-down.patch b/0011-char-Throttle-when-host-connection-is-down.patch deleted file mode 100644 index 5d52d18..0000000 --- a/0011-char-Throttle-when-host-connection-is-down.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 6a758a4f301d3f8450983d6ef82f3b6dbe0644f4 Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 22:05:10 +0100 -Subject: [PATCH 11/30] char: Throttle when host connection is down# - -When the host-side connection goes down, throttle the virtio-serial bus -and later unthrottle when a connection gets established. This helps -prevent any lost IO (guest->host) while the host connection was down. - -Bugzilla: 621484 - -This commit actually helps the bug mentioned above as no writes will now -get lost because of the throttling done here. With just the patches -sent earlier for that bug, one write will end up getting lost in the -worst case (host d/c, guest write, host connect). - -Signed-off-by: Amit Shah ---- - qemu-char.c | 14 ++++++++++++++ - 1 files changed, 14 insertions(+), 0 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index 49e61ba..72c0ce8 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -141,6 +141,9 @@ static void qemu_chr_generic_open_bh(void *opaque) - { - CharDriverState *s = opaque; - qemu_chr_event(s, CHR_EVENT_OPENED); -+ if (s->write_blocked) { -+ char_write_unblocked(s); -+ } - qemu_bh_delete(s->bh); - s->bh = NULL; - } -@@ -2025,6 +2028,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - ret = send_all(chr, s->fd, buf, len); - if (ret == -1 && errno == EPIPE) { - tcp_closed(chr); -+ -+ if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) { -+ /* -+ * Since we haven't written out anything, let's say -+ * we're throttled. This will prevent any output from -+ * the guest getting lost if host-side chardev goes -+ * down. Unthrottle when we re-connect. -+ */ -+ chr->write_blocked = true; -+ return 0; -+ } - } - return ret; - } else { --- -1.7.5 - diff --git a/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch b/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch deleted file mode 100644 index 90f7629..0000000 --- a/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch +++ /dev/null @@ -1,48 +0,0 @@ ->From 94e8b44e4fdfbf312e54b78ca7bbb95271cc83ae Mon Sep 17 00:00:00 2001 -From: Amit Shah -Date: Mon, 21 Mar 2011 22:06:41 +0100 -Subject: [PATCH 12/17] virtio-console: Enable port throttling when chardev is slow to consume data - -When a chardev indicates it can't accept more data, we tell the -virtio-serial code to stop sending us any more data till we tell -otherwise. This helps in guests continuing to run normally while the vq -keeps getting full and eventually the guest stops queueing more data. -As soon as the chardev indicates it can accept more data, start pushing! - -Signed-off-by: Amit Shah ---- - hw/virtio-console.c | 11 +++++++++++ - 1 files changed, 11 insertions(+), 0 deletions(-) - -diff --git a/hw/virtio-console.c b/hw/virtio-console.c -index 22cf28c..eecbdf7 100644 ---- a/hw/virtio-console.c -+++ b/hw/virtio-console.c -@@ -18,6 +18,16 @@ typedef struct VirtConsole { - CharDriverState *chr; - } VirtConsole; - -+/* -+ * Callback function that's called from chardevs when backend becomes -+ * writable. -+ */ -+static void chr_write_unblocked(void *opaque) -+{ -+ VirtConsole *vcon = opaque; -+ -+ virtio_serial_throttle_port(&vcon->port, false); -+} - - /* Callback function that's called when the guest sends us data */ - static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len) -@@ -61,6 +71,7 @@ static const QemuChrHandlers chr_handlers = { - .fd_can_read = chr_can_read, - .fd_read = chr_read, - .fd_event = chr_event, -+ .fd_write_unblocked = chr_write_unblocked, - }; - - static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev) --- -1.7.3.2 - diff --git a/0013-spice-qemu-char.c-add-throttling.patch b/0013-spice-qemu-char.c-add-throttling.patch deleted file mode 100644 index 34cb283..0000000 --- a/0013-spice-qemu-char.c-add-throttling.patch +++ /dev/null @@ -1,133 +0,0 @@ ->From 06ad256d2939aea4086428dcb5e5e7d5f86eb335 Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Tue, 22 Mar 2011 12:27:59 +0200 -Subject: [PATCH 13/17] spice-qemu-char.c: add throttling - -BZ: 672191 - -upstream: not submitted (explained below) - -Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing: -1. spice-server: reds.c: read_from_vdi_port -2. qemu: spice-qemu-char.c: vmc_read -3. chr_write_unblocked - (calls virtio_serial_throttle_port(port, false)) -4. qemu: virtio ... -5. qemu: spice-qemu-char.c: spice_chr_write -6. qemu: spice-qemu-char.c: wakeup (calls into spice-server) -7. spice-server: ... -8. qemu: spice-qemu-char.c: vmc_read - -Instead, in vmc_read if we were throttled and we are just about to return -all the bytes we will set a timer to be triggered immediately to call -chr_write_unblocked. Then we return after 2 above, and 3 is called from the -timer callback. This also means we can later remove some ugly recursion protection -from spice-server. - -The other tricky point in this patch is not returning the leftover chunk twice. -When we throttle, by definition we have data that spice server didn't consume. -It is being kept by virtio-serial, and by us. The next vmc_read callback needs -to not return it, but just do unthrottling. Then virtio will give us the remaining -chunk as usual in spice_chr_write, and we will pass it to spice server in the -next vmc_read. - -This patch relies on Amit's series to expose throttling to chardev's, which -was not accepted upstream, and will not be accepted upstream until the mainloop -is reworked to use glib. ---- - spice-qemu-char.c | 39 +++++++++++++++++++++++++++++++++++---- - 1 files changed, 35 insertions(+), 4 deletions(-) - -diff --git a/spice-qemu-char.c b/spice-qemu-char.c -index 517f337..91467d5 100644 ---- a/spice-qemu-char.c -+++ b/spice-qemu-char.c -@@ -1,4 +1,6 @@ - #include "config-host.h" -+#include "qemu-common.h" -+#include "qemu-timer.h" - #include "trace.h" - #include "ui/qemu-spice.h" - #include -@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver { - uint8_t *datapos; - ssize_t bufsize, datalen; - uint32_t debug; -+ QEMUTimer *unblock_timer; - } SpiceCharDriver; - - static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) -@@ -51,6 +54,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) - return out; - } - -+static void spice_chr_unblock(void *opaque) -+{ -+ SpiceCharDriver *scd = opaque; -+ -+ if (scd->chr->chr_write_unblocked == NULL) { -+ dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__); -+ return; -+ } -+ scd->chr->chr_write_unblocked(scd->chr->handler_opaque); -+} -+ - static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) - { - SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); -@@ -62,9 +76,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) - scd->datapos += bytes; - scd->datalen -= bytes; - assert(scd->datalen >= 0); -- if (scd->datalen == 0) { -- scd->datapos = 0; -- } -+ } -+ if (scd->datalen == 0 && scd->chr->write_blocked) { -+ dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes); -+ scd->chr->write_blocked = false; -+ /* -+ * set a timer instead of calling scd->chr->chr_write_unblocked directly, -+ * because that will call back into spice_chr_write (see -+ * virtio-console.c:chr_write_unblocked), which is unwanted. -+ */ -+ qemu_mod_timer(scd->unblock_timer, 0); - } - trace_spice_vmc_read(bytes, len); - return bytes; -@@ -107,6 +128,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd) - static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - { - SpiceCharDriver *s = chr->opaque; -+ int read_bytes; - - dprintf(s, 2, "%s: %d\n", __func__, len); - vmc_register_interface(s); -@@ -119,7 +141,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - s->datapos = s->buffer; - s->datalen = len; - spice_server_char_device_wakeup(&s->sin); -- return len; -+ read_bytes = len - s->datalen; -+ if (read_bytes != len) { -+ dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__, -+ read_bytes, len, s->bufsize); -+ s->chr->write_blocked = true; -+ /* We'll get passed in the unconsumed data with the next call */ -+ s->datalen = 0; -+ } -+ return read_bytes; - } - - static void spice_chr_close(struct CharDriverState *chr) -@@ -183,6 +213,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts) - chr->opaque = s; - chr->chr_write = spice_chr_write; - chr->chr_close = spice_chr_close; -+ s->unblock_timer = qemu_new_timer(vm_clock, spice_chr_unblock, s); - - qemu_chr_generic_open(chr); - --- -1.7.3.2 - diff --git a/0014-spice-qemu-char.c-remove-intermediate-buffer.patch b/0014-spice-qemu-char.c-remove-intermediate-buffer.patch deleted file mode 100644 index 2f56ce6..0000000 --- a/0014-spice-qemu-char.c-remove-intermediate-buffer.patch +++ /dev/null @@ -1,71 +0,0 @@ ->From 6ce8a141a37387a5138d0361cbe92885130010fe Mon Sep 17 00:00:00 2001 -From: Alon Levy -Date: Tue, 22 Mar 2011 12:28:00 +0200 -Subject: [PATCH 14/17] spice-qemu-char.c: remove intermediate buffer - -BZ: 672191 -upstream: not submitted (explained below) - -virtio-serial's buffer is valid when it calls us, and we don't -access it otherwise: vmc_read is only called in response to wakeup, -or else we set datalen=0 and throttle. Then vmc_read is called back, -we return 0 (not accessing the buffer) and set the timer to unthrottle. - -Also make datalen int and not ssize_t (to fit spice_chr_write signature). - -This relied on the previous patch that introduces throttling, which -can't go upstream right now as explained in that patch. ---- - spice-qemu-char.c | 18 ++++++------------ - 1 files changed, 6 insertions(+), 12 deletions(-) - -diff --git a/spice-qemu-char.c b/spice-qemu-char.c -index 91467d5..ed7851e 100644 ---- a/spice-qemu-char.c -+++ b/spice-qemu-char.c -@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver { - SpiceCharDeviceInstance sin; - char *subtype; - bool active; -- uint8_t *buffer; -- uint8_t *datapos; -- ssize_t bufsize, datalen; -+ const uint8_t *datapos; -+ int datalen; - uint32_t debug; - QEMUTimer *unblock_timer; - } SpiceCharDriver; -@@ -70,7 +69,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) - SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); - int bytes = MIN(len, scd->datalen); - -- dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen); -+ dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen); - if (bytes > 0) { - memcpy(buf, scd->datapos, bytes); - scd->datapos += bytes; -@@ -133,18 +132,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) - dprintf(s, 2, "%s: %d\n", __func__, len); - vmc_register_interface(s); - assert(s->datalen == 0); -- if (s->bufsize < len) { -- s->bufsize = len; -- s->buffer = qemu_realloc(s->buffer, s->bufsize); -- } -- memcpy(s->buffer, buf, len); -- s->datapos = s->buffer; -+ s->datapos = buf; - s->datalen = len; - spice_server_char_device_wakeup(&s->sin); - read_bytes = len - s->datalen; - if (read_bytes != len) { -- dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__, -- read_bytes, len, s->bufsize); -+ dprintf(s, 1, "%s: throttling: %d < %d\n", __func__, -+ read_bytes, len); - s->chr->write_blocked = true; - /* We'll get passed in the unconsumed data with the next call */ - s->datalen = 0; --- -1.7.3.2 - diff --git a/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch b/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch deleted file mode 100644 index bae63b8..0000000 --- a/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch +++ /dev/null @@ -1,76 +0,0 @@ ->From c8cb28f0791ab38945c7facb5a63e445b4b6f41f Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Fri, 18 Mar 2011 15:23:21 +0100 -Subject: [PATCH 15/17] chardev: Allow frontends to notify backends of guest open / close - -Some frontends know when the guest has opened the "channel" and is actively -listening to it, for example virtio-serial. This patch adds 2 new qemu-chardev -functions which can be used by frontends to signal guest open / close, and -allows interested backends to listen to this. - -Signed-off-by: Hans de Goede ---- - qemu-char.c | 17 +++++++++++++++++ - qemu-char.h | 4 ++++ - 2 files changed, 21 insertions(+), 0 deletions(-) - -diff --git a/qemu-char.c b/qemu-char.c -index 2ef972f..d52eb51 100644 ---- a/qemu-char.c -+++ b/qemu-char.c -@@ -507,6 +507,9 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) - chr->chr_write = mux_chr_write; - chr->chr_update_read_handler = mux_chr_update_read_handler; - chr->chr_accept_input = mux_chr_accept_input; -+ /* Frontend guest-open / -close notification is not support with muxes */ -+ chr->chr_guest_open = NULL; -+ chr->chr_guest_close = NULL; - - /* Muxes are always open on creation */ - qemu_chr_generic_open(chr); -@@ -2712,6 +2715,20 @@ void qemu_chr_set_echo(struct CharDriverState *chr, bool echo) - } - } - -+void qemu_chr_guest_open(struct CharDriverState *chr) -+{ -+ if (chr->chr_guest_open) { -+ chr->chr_guest_open(chr); -+ } -+} -+ -+void qemu_chr_guest_close(struct CharDriverState *chr) -+{ -+ if (chr->chr_guest_close) { -+ chr->chr_guest_close(chr); -+ } -+} -+ - void qemu_chr_close(CharDriverState *chr) - { - QTAILQ_REMOVE(&chardevs, chr, next); -diff --git a/qemu-char.h b/qemu-char.h -index bf06da0..f3b9bf4 100644 ---- a/qemu-char.h -+++ b/qemu-char.h -@@ -69,6 +69,8 @@ struct CharDriverState { - void (*chr_close)(struct CharDriverState *chr); - void (*chr_accept_input)(struct CharDriverState *chr); - void (*chr_set_echo)(struct CharDriverState *chr, bool echo); -+ void (*chr_guest_open)(struct CharDriverState *chr); -+ void (*chr_guest_close)(struct CharDriverState *chr); - void *opaque; - QEMUBH *bh; - char *label; -@@ -91,6 +93,8 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts, - void (*init)(struct CharDriverState *s)); - CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s)); - void qemu_chr_set_echo(struct CharDriverState *chr, bool echo); -+void qemu_chr_guest_open(struct CharDriverState *chr); -+void qemu_chr_guest_close(struct CharDriverState *chr); - void qemu_chr_close(CharDriverState *chr); - void qemu_chr_printf(CharDriverState *s, const char *fmt, ...) - GCC_FMT_ATTR(2, 3); --- -1.7.3.2 - diff --git a/0016-virtio-console-notify-backend-of-guest-open-close.patch b/0016-virtio-console-notify-backend-of-guest-open-close.patch deleted file mode 100644 index 0b3e3f8..0000000 --- a/0016-virtio-console-notify-backend-of-guest-open-close.patch +++ /dev/null @@ -1,49 +0,0 @@ ->From 3baf76e384c04f58f032632c078860d66c8c9db3 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Fri, 18 Mar 2011 15:30:45 +0100 -Subject: [PATCH 16/17] virtio-console: notify backend of guest open / close - -Signed-off-by: Hans de Goede ---- - hw/virtio-console.c | 18 ++++++++++++++++++ - 1 files changed, 18 insertions(+), 0 deletions(-) - -diff --git a/hw/virtio-console.c b/hw/virtio-console.c -index eecbdf7..828a1a3 100644 ---- a/hw/virtio-console.c -+++ b/hw/virtio-console.c -@@ -37,6 +37,22 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len) - return qemu_chr_write(vcon->chr, buf, len); - } - -+/* Callback function that's called when the guest opens the port */ -+static void guest_open(VirtIOSerialPort *port) -+{ -+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); -+ -+ qemu_chr_guest_open(vcon->chr); -+} -+ -+/* Callback function that's called when the guest closes the port */ -+static void guest_close(VirtIOSerialPort *port) -+{ -+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); -+ -+ qemu_chr_guest_close(vcon->chr); -+} -+ - /* Readiness of the guest to accept data on a port */ - static int chr_can_read(void *opaque) - { -@@ -81,6 +97,8 @@ static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev) - if (vcon->chr) { - qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon); - vcon->port.info->have_data = flush_buf; -+ vcon->port.info->guest_open = guest_open; -+ vcon->port.info->guest_close = guest_close; - } - return 0; - } --- -1.7.3.2 - diff --git a/0017-spice-chardev-listen-to-frontend-guest-open-close.patch b/0017-spice-chardev-listen-to-frontend-guest-open-close.patch deleted file mode 100644 index 1944bbc..0000000 --- a/0017-spice-chardev-listen-to-frontend-guest-open-close.patch +++ /dev/null @@ -1,49 +0,0 @@ ->From c169795bed5374f0071af201da2dd32b3c5a2417 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Fri, 18 Mar 2011 15:35:27 +0100 -Subject: [PATCH 17/17] spice-chardev: listen to frontend guest open / close - -Note the vmc_register_interface() in spice_chr_write is left in place -in case someone uses spice-chardev with a frontend which does not have -guest open / close notification. - -Signed-off-by: Hans de Goede ---- - spice-qemu-char.c | 14 ++++++++++++++ - 1 files changed, 14 insertions(+), 0 deletions(-) - -diff --git a/spice-qemu-char.c b/spice-qemu-char.c -index ed7851e..343146c 100644 ---- a/spice-qemu-char.c -+++ b/spice-qemu-char.c -@@ -155,6 +155,18 @@ static void spice_chr_close(struct CharDriverState *chr) - qemu_free(s); - } - -+static void spice_chr_guest_open(struct CharDriverState *chr) -+{ -+ SpiceCharDriver *s = chr->opaque; -+ vmc_register_interface(s); -+} -+ -+static void spice_chr_guest_close(struct CharDriverState *chr) -+{ -+ SpiceCharDriver *s = chr->opaque; -+ vmc_unregister_interface(s); -+} -+ - static void print_allowed_subtypes(void) - { - const char** psubtype; -@@ -207,6 +219,8 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts) - chr->opaque = s; - chr->chr_write = spice_chr_write; - chr->chr_close = spice_chr_close; -+ chr->chr_guest_open = spice_chr_guest_open; -+ chr->chr_guest_close = spice_chr_guest_close; - s->unblock_timer = qemu_new_timer(vm_clock, spice_chr_unblock, s); - - qemu_chr_generic_open(chr); --- -1.7.3.2 - diff --git a/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch b/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch deleted file mode 100644 index a6c2445..0000000 --- a/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch +++ /dev/null @@ -1,56 +0,0 @@ ->From 7a9e7aaa30abf42879d3f13b41679513045c31ec Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Tue, 22 Mar 2011 16:28:41 +0100 -Subject: [PATCH 18/18] spice-qemu-char: Fix flow control in client -> guest direction - -In the old spice-vmc device we used to have: -last_out = virtio_serial_write(&svc->port, p, MIN(len, VMC_MAX_HOST_WRITE)); -if (last_out > 0) - ... - -Now in the chardev backend we have: -last_out = MIN(len, VMC_MAX_HOST_WRITE); -qemu_chr_read(scd->chr, p, last_out); -if (last_out > 0) { - ... - -Which causes us to no longer detect if the virtio port is not ready -to receive data from us. chardev actually has a mechanism to detect this, -but it requires a separate call to qemu_chr_can_read, before calling -qemu_chr_read (which return void). - -This patch uses qemu_chr_can_read to fix the flow control from client to -guest. - -Signed-off-by: Hans de Goede ---- - spice-qemu-char.c | 11 +++++------ - 1 files changed, 5 insertions(+), 6 deletions(-) - -diff --git a/spice-qemu-char.c b/spice-qemu-char.c -index 343146c..def713a 100644 ---- a/spice-qemu-char.c -+++ b/spice-qemu-char.c -@@ -38,14 +38,13 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) - - while (len > 0) { - last_out = MIN(len, VMC_MAX_HOST_WRITE); -- qemu_chr_read(scd->chr, p, last_out); -- if (last_out > 0) { -- out += last_out; -- len -= last_out; -- p += last_out; -- } else { -+ if (qemu_chr_can_read(scd->chr) < last_out) { - break; - } -+ qemu_chr_read(scd->chr, p, last_out); -+ out += last_out; -+ len -= last_out; -+ p += last_out; - } - - dprintf(scd, 3, "%s: %lu/%zd\n", __func__, out, len + out); --- -1.7.3.2 - diff --git a/pc-add-a-Fedora-13-machine-type-for-backward-compat.patch b/pc-add-a-Fedora-13-machine-type-for-backward-compat.patch deleted file mode 100644 index bbd7551..0000000 --- a/pc-add-a-Fedora-13-machine-type-for-backward-compat.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Justin M. Forbes -Date: Thu, Aug 19 09:13:45 2010 -0500 -Subject: pc: Add a Fedora-13 machine type for backwards compatibility. - -In Fedora 13 a fedora-13 machine type was added as default to allow -interaction with upstream stable qemu which did not support the same -feature set. As a result we need to support this machine type through -the Fedora 15 release. - - -diff --git a/hw/pc_piix.c b/hw/pc_piix.c -index 9e4bac8..eb1ed05 100644 ---- a/hw/pc_piix.c -+++ b/hw/pc_piix.c -@@ -266,6 +266,14 @@ static QEMUMachine pc_machine_v0_13 = { - }, - }; - -+static QEMUMachine pc_machine_f13 = { -+ .name = "fedora-13", -+ .desc = "Standard PC", -+ .init = pc_init_pci, -+ .max_cpus = 255, -+ .is_default = 0, -+}; -+ - static QEMUMachine pc_machine_v0_12 = { - .name = "pc-0.12", - .desc = "Standard PC", -@@ -397,6 +405,7 @@ static QEMUMachine isapc_machine = { - static void pc_machine_init(void) - { - qemu_register_machine(&pc_machine); -+ qemu_register_machine(&pc_machine_f13); - qemu_register_machine(&pc_machine_v0_13); - qemu_register_machine(&pc_machine_v0_12); - qemu_register_machine(&pc_machine_v0_11); diff --git a/qemu.spec b/qemu.spec index 94237a8..c3e2579 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,7 +1,9 @@ +%define githead 525e3df + Summary: QEMU is a FAST! processor emulator Name: qemu -Version: 0.14.0 -Release: 9%{?dist} +Version: 0.15.0 +Release: 0.1.20110718%githead%{?dist} # Epoch because we pushed a qemu-1.0 package Epoch: 2 License: GPLv2+ and LGPLv2+ and BSD @@ -17,7 +19,12 @@ URL: http://www.qemu.org/ %define _smp_mflags %{nil} %endif -Source0: http://downloads.sourceforge.net/sourceforge/kvm/qemu-kvm-%{version}.tar.gz +# Source0: http://downloads.sourceforge.net/sourceforge/kvm/qemu-kvm-%{version}.tar.gz +# The source for this package was pulled from upstream's git. Use the +# following commands to generate the tarball: +# git archive --format=tar --prefix=qemu-kvm-0.15/ 525e3df | gzip > qemu-kvm-0.15.0-525e3df.tar.gz +Source0: qemu-kvm-%{version}-%{githead}.tar.gz + Source1: qemu.init # Loads kvm kernel modules at boot @@ -33,35 +40,6 @@ Source6: ksmtuned.init Source7: ksmtuned Source8: ksmtuned.conf -# This patch must be carried through F-15 to support guests created -# with F-13/ -Patch00: pc-add-a-Fedora-13-machine-type-for-backward-compat.patch - -# Patches from upstream: -Patch01: qemu-fix-non-PCI-target-build.patch -Patch02: qemu-vhost-fix-dirty-page-handling.patch - -# Spice fixes -Patch20: 0001-qxl-spice-display-move-pipe-to-ssd.patch -Patch21: 0002-qxl-implement-get_command-in-vga-mode-without-locks.patch -Patch22: 0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch -Patch23: 0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch -Patch24: 0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch -Patch25: 0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch -Patch26: 0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch -Patch27: 0008-char-Add-framework-for-a-write-unblocked-callback.patch -Patch28: 0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch -Patch29: 0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch -Patch30: 0011-char-Throttle-when-host-connection-is-down.patch -Patch31: 0012-virtio-console-Enable-port-throttling-when-chardev-i.patch -Patch32: 0013-spice-qemu-char.c-add-throttling.patch -Patch33: 0014-spice-qemu-char.c-remove-intermediate-buffer.patch -Patch34: 0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch -Patch35: 0016-virtio-console-notify-backend-of-guest-open-close.patch -Patch36: 0017-spice-chardev-listen-to-frontend-guest-open-close.patch -Patch37: 0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch - - BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: SDL-devel zlib-devel which texi2html gnutls-devel cyrus-sasl-devel BuildRequires: libaio-devel @@ -235,29 +213,6 @@ such as kvm_stat. %prep %setup -q -n qemu-kvm-%{version} -%patch00 -p1 -%patch01 -p1 -%patch02 -p1 - -%patch20 -p1 -%patch21 -p1 -%patch22 -p1 -%patch23 -p1 -%patch24 -p1 -%patch25 -p1 -%patch26 -p1 -%patch27 -p1 -%patch28 -p1 -%patch29 -p1 -%patch30 -p1 -%patch31 -p1 -%patch32 -p1 -%patch33 -p1 -%patch34 -p1 -%patch35 -p1 -%patch36 -p1 -%patch37 -p1 - %build # By default we build everything, but allow x86 to build a minimal version # with only similar arch target support @@ -297,6 +252,7 @@ sed -i.debug 's/"-g $CFLAGS"/"$CFLAGS"/g' configure %ifarch x86_64 --enable-spice \ %endif + --disable-werror \ --disable-xen echo "config-host.mak contents:" @@ -369,22 +325,25 @@ install -D -p -m 0644 -t ${RPM_BUILD_ROOT}%{qemudocdir} Changelog README TODO CO install -D -p -m 0644 qemu.sasl $RPM_BUILD_ROOT%{_sysconfdir}/sasl2/qemu.conf rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/pxe*bin +rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/pxe*rom rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/gpxe*rom rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/vgabios*bin rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/bios.bin rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/openbios-ppc rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/openbios-sparc32 rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/openbios-sparc64 -rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/petalogix-s3adsp1800.dtb +rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/petalogix*.dtb rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/s390-zipl.rom rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/bamboo.dtb +rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/slof.bin +rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/spapr-rtas.bin rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{name}/ppc_rom.bin # the pxe gpxe images will be symlinks to the images on # /usr/share/gpxe, as QEMU doesn't know how to look # for other paths, yet. pxe_link() { - ln -s ../gpxe/$2.rom %{buildroot}%{_datadir}/%{name}/pxe-$1.bin + ln -s ../gpxe/$2.rom %{buildroot}%{_datadir}/%{name}/pxe-$1.rom } pxe_link e1000 8086100e @@ -500,17 +459,18 @@ fi %{_datadir}/%{name}/bios.bin %{_datadir}/%{name}/linuxboot.bin %{_datadir}/%{name}/multiboot.bin +%{_datadir}/%{name}/mpc8544ds.dtb %{_datadir}/%{name}/vapic.bin %{_datadir}/%{name}/vgabios.bin %{_datadir}/%{name}/vgabios-cirrus.bin %{_datadir}/%{name}/vgabios-qxl.bin %{_datadir}/%{name}/vgabios-stdvga.bin %{_datadir}/%{name}/vgabios-vmware.bin -%{_datadir}/%{name}/pxe-e1000.bin -%{_datadir}/%{name}/pxe-virtio.bin -%{_datadir}/%{name}/pxe-pcnet.bin -%{_datadir}/%{name}/pxe-rtl8139.bin -%{_datadir}/%{name}/pxe-ne2k_pci.bin +%{_datadir}/%{name}/pxe-e1000.rom +%{_datadir}/%{name}/pxe-virtio.rom +%{_datadir}/%{name}/pxe-pcnet.rom +%{_datadir}/%{name}/pxe-rtl8139.rom +%{_datadir}/%{name}/pxe-ne2k_pci.rom %config(noreplace) %{_sysconfdir}/qemu/target-x86_64.conf %ifarch %{ix86} x86_64 @@ -561,6 +521,9 @@ fi %{_mandir}/man1/qemu-img.1* %changelog +* Mon Jul 18 2011 Justin M. Forbes - 2:0.15.0-0.1.20110718525e3df +- Update to git snapshot as we prepare for 0.15.0 release + * Wed Jun 22 2011 Richard W.M. Jones - 2:0.14.0-9 - Add BR libattr-devel. This caused the -fstype option to be disabled. https://www.redhat.com/archives/libvir-list/2011-June/thread.html#01017 diff --git a/sources b/sources index f8e717f..2826ce6 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -4ea6f412d85a826e0b0690f5c4c59f13 qemu-kvm-0.14.0.tar.gz +cbd0d49d1490ca90208609cd158eb080 qemu-kvm-0.15.0-525e3df.tar.gz