From 0b8e2c1002afddc8ef3d52fa6fc29e4768429f98 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 20 Jul 2015 12:27:16 +0100 Subject: [PATCH 01/12] exec.c: Use atomic_rcu_read() to access dispatch in memory_region_section_get_iotlb() When accessing the dispatch pointer in an AddressSpace within an RCU critical section we should always use atomic_rcu_read(). Fix an access within memory_region_section_get_iotlb() which was incorrectly doing a direct pointer access. Signed-off-by: Peter Maydell Message-Id: <1437391637-31576-1-git-send-email-peter.maydell@linaro.org> Signed-off-by: Paolo Bonzini --- exec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 7d60e1530c..0a4a0c5af6 100644 --- a/exec.c +++ b/exec.c @@ -954,7 +954,10 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu, iotlb |= PHYS_SECTION_ROM; } } else { - iotlb = section - section->address_space->dispatch->map.sections; + AddressSpaceDispatch *d; + + d = atomic_rcu_read(§ion->address_space->dispatch); + iotlb = section - d->map.sections; iotlb += xlat; } From 9172f428afc1461b1d9b33ebca3a679b9adf7c3a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 21 Jul 2015 09:25:54 +0200 Subject: [PATCH 02/12] qemu-char: handle EINTR for TCP character devices Signed-off-by: Paolo Bonzini --- qemu-char.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 617e034455..3200200f0f 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2797,7 +2797,10 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) #ifdef MSG_CMSG_CLOEXEC flags |= MSG_CMSG_CLOEXEC; #endif - ret = recvmsg(s->fd, &msg, flags); + do { + ret = recvmsg(s->fd, &msg, flags); + } while (ret == -1 && errno == EINTR); + if (ret > 0 && s->is_unix) { unix_process_msgfd(chr, &msg); } @@ -2808,7 +2811,13 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) { TCPCharDriver *s = chr->opaque; - return qemu_recv(s->fd, buf, len, 0); + ssize_t ret; + + do { + ret = qemu_recv(s->fd, buf, len, 0); + } while (ret == -1 && socket_error() == EINTR); + + return ret; } #endif From 4bf1cb03fbc43b0055af60d4ff093d6894aa4338 Mon Sep 17 00:00:00 2001 From: Nils Carlson Date: Sun, 19 Jul 2015 20:39:56 +0000 Subject: [PATCH 03/12] qemu-char: Fix missed data on unix socket Commit 812c1057 introduced HUP detection on unix and tcp sockets prior to a read in tcp_chr_read. This unfortunately broke CloudStack 4.2 which relied on the old behaviour where data on a socket was readable even if a HUP was present. A working solution is to properly check the return values from recv, handling a closed socket once there is no more data to read. Also enable polling for G_IO_NVAL to ensure the callback is called for all possible events as these should now be possible to handle with the improved error detection. Signed-off-by: Nils Carlson Message-Id: <1437338396-22336-1-git-send-email-pyssling@ludd.ltu.se> [Do not handle EINTR; use socket_error(). - Paolo] Signed-off-by: Paolo Bonzini --- qemu-char.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 3200200f0f..d956f8db6c 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -807,7 +807,8 @@ static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_) } if (now_active) { - iwp->src = g_io_create_watch(iwp->channel, G_IO_IN | G_IO_ERR | G_IO_HUP); + iwp->src = g_io_create_watch(iwp->channel, + G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL); g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL); g_source_attach(iwp->src, NULL); } else { @@ -2856,12 +2857,6 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) uint8_t buf[READ_BUF_LEN]; int len, size; - if (cond & G_IO_HUP) { - /* connection closed */ - tcp_chr_disconnect(chr); - return TRUE; - } - if (!s->connected || s->max_size <= 0) { return TRUE; } @@ -2869,7 +2864,9 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) if (len > s->max_size) len = s->max_size; size = tcp_chr_recv(chr, (void *)buf, len); - if (size == 0) { + if (size == 0 || + (size < 0 && + socket_error() != EAGAIN && socket_error() != EWOULDBLOCK)) { /* connection closed */ tcp_chr_disconnect(chr); } else if (size > 0) { From 60928458e5eea3c77a7eb0a4194927872f463947 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Wed, 22 Jul 2015 17:08:53 +0800 Subject: [PATCH 04/12] vnc: fix memory leak If vnc's password is configured, it will leak memory which cipher variable pointed on every vnc connection. Cc: Daniel P. Berrange Reviewed-by: Daniel P. Berrange Signed-off-by: Gonglei Message-Id: <1437556133-11268-1-git-send-email-arei.gonglei@huawei.com> Signed-off-by: Paolo Bonzini --- ui/vnc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/vnc.c b/ui/vnc.c index 1483958c45..e26973a2b6 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -2520,7 +2520,7 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len) size_t i, pwlen; unsigned char key[8]; time_t now = time(NULL); - QCryptoCipher *cipher; + QCryptoCipher *cipher = NULL; Error *err = NULL; if (!vs->vd->password) { @@ -2573,6 +2573,8 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len) start_client_init(vs); } + + qcrypto_cipher_free(cipher); return 0; reject: @@ -2584,6 +2586,7 @@ reject: } vnc_flush(vs); vnc_client_error(vs); + qcrypto_cipher_free(cipher); return 0; } From c170aad8b057223b1139d72e5ce7acceafab4fa9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 21 Jul 2015 08:59:39 +0200 Subject: [PATCH 05/12] scsi: fix buffer overflow in scsi_req_parse_cdb (CVE-2015-5158) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a guest-triggerable buffer overflow present in QEMU 2.2.0 and newer. scsi_cdb_length returns -1 as an error value, but the caller does not check it. Luckily, the massive overflow means that QEMU will just SIGSEGV, making the impact much smaller. Reported-by: Zhu Donghai (朱东海) Fixes: 1894df02811f6b79ea3ffbf1084599d96f316173 Reviewed-by: Fam Zheng Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-bus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index f50b2f08af..f0ae4625ff 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -1239,10 +1239,15 @@ int scsi_cdb_length(uint8_t *buf) { int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf) { int rc; + int len; cmd->lba = -1; - cmd->len = scsi_cdb_length(buf); + len = scsi_cdb_length(buf); + if (len < 0) { + return -1; + } + cmd->len = len; switch (dev->type) { case TYPE_TAPE: rc = scsi_req_stream_xfer(cmd, dev, buf); From ab28bd23125fb4a0411c3a3f01c4edacbc261486 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 9 Jul 2015 08:55:38 +0200 Subject: [PATCH 06/12] rcu: actually register threads that have RCU read-side critical sections Otherwise, grace periods are detected too early! Signed-off-by: Paolo Bonzini --- cpus.c | 6 ++++++ iothread.c | 5 +++++ migration/migration.c | 4 ++++ tests/test-rcu-list.c | 4 ++++ util/rcu.c | 2 ++ 5 files changed, 21 insertions(+) diff --git a/cpus.c b/cpus.c index b00a42379b..a822ce3d80 100644 --- a/cpus.c +++ b/cpus.c @@ -954,6 +954,8 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) CPUState *cpu = arg; int r; + rcu_register_thread(); + qemu_mutex_lock_iothread(); qemu_thread_get_self(cpu->thread); cpu->thread_id = qemu_get_thread_id(); @@ -995,6 +997,8 @@ static void *qemu_dummy_cpu_thread_fn(void *arg) sigset_t waitset; int r; + rcu_register_thread(); + qemu_mutex_lock_iothread(); qemu_thread_get_self(cpu->thread); cpu->thread_id = qemu_get_thread_id(); @@ -1034,6 +1038,8 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) { CPUState *cpu = arg; + rcu_register_thread(); + qemu_mutex_lock_iothread(); qemu_tcg_init_cpu_signals(); qemu_thread_get_self(cpu->thread); diff --git a/iothread.c b/iothread.c index 6d2a33faf9..da6ce7b308 100644 --- a/iothread.c +++ b/iothread.c @@ -18,6 +18,7 @@ #include "sysemu/iothread.h" #include "qmp-commands.h" #include "qemu/error-report.h" +#include "qemu/rcu.h" typedef ObjectClass IOThreadClass; @@ -31,6 +32,8 @@ static void *iothread_run(void *opaque) IOThread *iothread = opaque; bool blocking; + rcu_register_thread(); + qemu_mutex_lock(&iothread->init_done_lock); iothread->thread_id = qemu_get_thread_id(); qemu_cond_signal(&iothread->init_done_cond); @@ -45,6 +48,8 @@ static void *iothread_run(void *opaque) } aio_context_release(iothread->ctx); } + + rcu_unregister_thread(); return NULL; } diff --git a/migration/migration.c b/migration/migration.c index 86ca099ac4..fd4f99b84e 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -22,6 +22,7 @@ #include "block/block.h" #include "qapi/qmp/qerror.h" #include "qemu/sockets.h" +#include "qemu/rcu.h" #include "migration/block.h" #include "qemu/thread.h" #include "qmp-commands.h" @@ -917,6 +918,8 @@ static void *migration_thread(void *opaque) int64_t start_time = initial_time; bool old_vm_running = false; + rcu_register_thread(); + qemu_savevm_state_header(s->file); qemu_savevm_state_begin(s->file, &s->params); @@ -1016,6 +1019,7 @@ static void *migration_thread(void *opaque) qemu_bh_schedule(s->cleanup_bh); qemu_mutex_unlock_iothread(); + rcu_unregister_thread(); return NULL; } diff --git a/tests/test-rcu-list.c b/tests/test-rcu-list.c index 4c5f62e996..daa8bf41db 100644 --- a/tests/test-rcu-list.c +++ b/tests/test-rcu-list.c @@ -108,6 +108,8 @@ static void *rcu_q_reader(void *arg) long long n_reads_local = 0; struct list_element *el; + rcu_register_thread(); + *(struct rcu_reader_data **)arg = &rcu_reader; atomic_inc(&nthreadsrunning); while (goflag == GOFLAG_INIT) { @@ -129,6 +131,8 @@ static void *rcu_q_reader(void *arg) qemu_mutex_lock(&counts_mutex); n_reads += n_reads_local; qemu_mutex_unlock(&counts_mutex); + + rcu_unregister_thread(); return NULL; } diff --git a/util/rcu.c b/util/rcu.c index 7270151bef..cdcad678b4 100644 --- a/util/rcu.c +++ b/util/rcu.c @@ -216,6 +216,8 @@ static void *call_rcu_thread(void *opaque) { struct rcu_head *node; + rcu_register_thread(); + for (;;) { int tries = 0; int n = atomic_read(&rcu_call_count); From 7d99f4c1b5d12de7644a5bd8c3d46bff05c9ca7c Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Wed, 15 Jul 2015 14:52:32 -0400 Subject: [PATCH 07/12] scsi: Handle no media case for scsi_get_configuration Currently, scsi_get_configuration always returns a current profile (DVD or CD), even when there is actually no media present. By comparison, ide/atapi uses a default profile of 0 (MMC_PROFILE_NONE) for this case and checks for tray_open, so let's do the same for scsi. This fixes a problem I'm seeing with Fedora 22 guests where systemd cdrom_id fails to unmount after a QEMU-initiated eject against a scsi cdrom device because it believes the media is still present (but unreadable). Signed-off-by: Matthew Rosato Message-Id: <1436986352-10695-1-git-send-email-mjrosato@linux.vnet.ibm.com> Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-disk.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 54d71f4c03..64f0694734 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -765,6 +765,9 @@ static inline bool media_is_dvd(SCSIDiskState *s) if (!blk_is_inserted(s->qdev.conf.blk)) { return false; } + if (s->tray_open) { + return false; + } blk_get_geometry(s->qdev.conf.blk, &nb_sectors); return nb_sectors > CD_MAX_SECTORS; } @@ -778,6 +781,9 @@ static inline bool media_is_cd(SCSIDiskState *s) if (!blk_is_inserted(s->qdev.conf.blk)) { return false; } + if (s->tray_open) { + return false; + } blk_get_geometry(s->qdev.conf.blk, &nb_sectors); return nb_sectors <= CD_MAX_SECTORS; } @@ -975,7 +981,15 @@ static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf) if (s->qdev.type != TYPE_ROM) { return -1; } - current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM; + + if (media_is_dvd(s)) { + current = MMC_PROFILE_DVD_ROM; + } else if (media_is_cd(s)) { + current = MMC_PROFILE_CD_ROM; + } else { + current = MMC_PROFILE_NONE; + } + memset(outbuf, 0, 40); stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */ stw_be_p(&outbuf[6], current); From fb4309695905de889d318caec8eb13d3b2c118d5 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 22 Jul 2015 19:53:30 +0200 Subject: [PATCH 08/12] vl: Fix compiler warning for builds without VNC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This regression was caused by commit 70b94331. CC vl.o vl.c: In function ‘select_display’: vl.c:2064:12: error: unused variable ‘err’ [-Werror=unused-variable] Error *err = NULL; ^ Reported-by: Claudio Fontana Signed-off-by: Stefan Weil Message-Id: <1437587610-26433-1-git-send-email-sw@weilnetz.de> Reviewed-by: Wen Congyang Signed-off-by: Paolo Bonzini --- vl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vl.c b/vl.c index 5856396d46..0adbbd6747 100644 --- a/vl.c +++ b/vl.c @@ -2061,7 +2061,6 @@ static void select_vgahw (const char *p) static DisplayType select_display(const char *p) { - Error *err = NULL; const char *opts; DisplayType display = DT_DEFAULT; @@ -2130,6 +2129,7 @@ static DisplayType select_display(const char *p) } else if (strstart(p, "vnc", &opts)) { #ifdef CONFIG_VNC if (*opts == '=') { + Error *err = NULL; if (vnc_parse(opts + 1, &err) == NULL) { error_report_err(err); exit(1); From deb809edb85334c8e90530e1071b98f4da25ebaa Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 14 Jul 2015 13:56:53 +0200 Subject: [PATCH 09/12] memory: count number of active VGA logging clients For a board that has multiple framebuffer devices, both of them might want to use DIRTY_MEMORY_VGA on the same memory region. The lack of reference counting in memory_region_set_log makes this very awkward to implement. Suggested-by: Peter Maydell Signed-off-by: Paolo Bonzini --- include/exec/memory.h | 1 + memory.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/include/exec/memory.h b/include/exec/memory.h index 139471500f..94d20eae05 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -180,6 +180,7 @@ struct MemoryRegion { bool warning_printed; /* For reservations */ bool flush_coalesced_mmio; bool global_locking; + uint8_t vga_logging_count; MemoryRegion *alias; hwaddr alias_offset; int32_t priority; diff --git a/memory.c b/memory.c index 0acebb1f22..5e5f32540e 100644 --- a/memory.c +++ b/memory.c @@ -1433,8 +1433,15 @@ void memory_region_notify_iommu(MemoryRegion *mr, void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) { uint8_t mask = 1 << client; + uint8_t old_logging; assert(client == DIRTY_MEMORY_VGA); + old_logging = mr->vga_logging_count; + mr->vga_logging_count += log ? 1 : -1; + if (!!old_logging == !!mr->vga_logging_count) { + return; + } + memory_region_transaction_begin(); mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask); memory_region_update_pending |= mr->enabled; From c1076c3e13a86140cc2ba29866512df8460cc7c2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 13 Jul 2015 12:00:29 +0200 Subject: [PATCH 10/12] framebuffer: set DIRTY_MEMORY_VGA on RAM that is used for the framebuffer The MemoryRegionSection contains enough information to access the RAM region underlying the framebuffer, and can be cached inside the display device. By doing this, the new framebuffer_update_memory_section function can enable dirty memory logging on the relevant RAM region. The function must be called whenever the stride or base of the framebuffer changes; a simple way to cover these cases is to call it on every full frame invalidation, which is a rare case. framebuffer_update_display now works entirely on a MemoryRegionSection, without going through cpu_physical_memory_map/unmap. Reviewed-by: Peter Maydell Signed-off-by: Paolo Bonzini --- hw/display/framebuffer.c | 75 ++++++++++++++++++++---------------- hw/display/framebuffer.h | 44 ++++++++++++++++++++- hw/display/milkymist-vgafb.c | 15 ++++++-- hw/display/omap_lcdc.c | 12 +++++- hw/display/pl110.c | 13 ++++++- hw/display/pxa2xx_lcd.c | 29 ++++++++++---- 6 files changed, 137 insertions(+), 51 deletions(-) diff --git a/hw/display/framebuffer.c b/hw/display/framebuffer.c index 2cabced208..7f075ce776 100644 --- a/hw/display/framebuffer.c +++ b/hw/display/framebuffer.c @@ -21,12 +21,40 @@ #include "ui/console.h" #include "framebuffer.h" +void framebuffer_update_memory_section( + MemoryRegionSection *mem_section, + MemoryRegion *root, + hwaddr base, + unsigned rows, + unsigned src_width) +{ + hwaddr src_len = (hwaddr)rows * src_width; + + if (mem_section->mr) { + memory_region_set_log(mem_section->mr, false, DIRTY_MEMORY_VGA); + memory_region_unref(mem_section->mr); + mem_section->mr = NULL; + } + + *mem_section = memory_region_find(root, base, src_len); + if (!mem_section->mr) { + return; + } + + if (int128_get64(mem_section->size) < src_len || + !memory_region_is_ram(mem_section->mr)) { + memory_region_unref(mem_section->mr); + mem_section->mr = NULL; + return; + } + + memory_region_set_log(mem_section->mr, true, DIRTY_MEMORY_VGA); +} + /* Render an image from a shared memory framebuffer. */ - void framebuffer_update_display( DisplaySurface *ds, - MemoryRegion *address_space, - hwaddr base, + MemoryRegionSection *mem_section, int cols, /* Width in pixels. */ int rows, /* Height in pixels. */ int src_width, /* Length of source line, in bytes. */ @@ -41,51 +69,33 @@ void framebuffer_update_display( hwaddr src_len; uint8_t *dest; uint8_t *src; - uint8_t *src_base; int first, last = 0; int dirty; int i; ram_addr_t addr; - MemoryRegionSection mem_section; MemoryRegion *mem; i = *first_row; *first_row = -1; src_len = src_width * rows; - mem_section = memory_region_find(address_space, base, src_len); - mem = mem_section.mr; - if (int128_get64(mem_section.size) != src_len || - !memory_region_is_ram(mem_section.mr)) { - goto out; + mem = mem_section->mr; + if (!mem) { + return; } - assert(mem); - assert(mem_section.offset_within_address_space == base); - memory_region_sync_dirty_bitmap(mem); - if (!memory_region_is_logging(mem, DIRTY_MEMORY_VGA)) { - invalidate = true; - } - src_base = cpu_physical_memory_map(base, &src_len, 0); - /* If we can't map the framebuffer then bail. We could try harder, - but it's not really worth it as dirty flag tracking will probably - already have failed above. */ - if (!src_base) - goto out; - if (src_len != src_width * rows) { - cpu_physical_memory_unmap(src_base, src_len, 0, 0); - goto out; - } - src = src_base; + addr = mem_section->offset_within_region; + src = memory_region_get_ram_ptr(mem) + addr; + dest = surface_data(ds); - if (dest_col_pitch < 0) + if (dest_col_pitch < 0) { dest -= dest_col_pitch * (cols - 1); + } if (dest_row_pitch < 0) { dest -= dest_row_pitch * (rows - 1); } first = -1; - addr = mem_section.offset_within_region; addr += i * src_width; src += i * src_width; @@ -104,14 +114,11 @@ void framebuffer_update_display( src += src_width; dest += dest_row_pitch; } - cpu_physical_memory_unmap(src_base, src_len, 0, 0); if (first < 0) { - goto out; + return; } - memory_region_reset_dirty(mem, mem_section.offset_within_region, src_len, + memory_region_reset_dirty(mem, mem_section->offset_within_region, src_len, DIRTY_MEMORY_VGA); *first_row = first; *last_row = last; -out: - memory_region_unref(mem); } diff --git a/hw/display/framebuffer.h b/hw/display/framebuffer.h index 6eae035b7d..38fa0dcec6 100644 --- a/hw/display/framebuffer.h +++ b/hw/display/framebuffer.h @@ -7,10 +7,50 @@ typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int); +/* framebuffer_update_memory_section: Update framebuffer + * #MemoryRegionSection, for example if the framebuffer is switched to + * a different memory area. + * + * @mem_section: Output #MemoryRegionSection, to be passed to + * framebuffer_update_display(). + * @root: #MemoryRegion within which the framebuffer lies + * @base: Base address of the framebuffer within @root. + * @rows: Height of the screen. + * @src_width: Number of bytes in framebuffer memory between two rows. + */ +void framebuffer_update_memory_section( + MemoryRegionSection *mem_section, + MemoryRegion *root, + hwaddr base, + unsigned rows, + unsigned src_width); + +/* framebuffer_update_display: Draw the framebuffer on a surface. + * + * @ds: #DisplaySurface to draw to. + * @mem_section: #MemoryRegionSection provided by + * framebuffer_update_memory_section(). + * @cols: Width the screen. + * @rows: Height of the screen. + * @src_width: Number of bytes in framebuffer memory between two rows. + * @dest_row_pitch: Number of bytes in the surface data between two rows. + * Negative if the framebuffer is stored in the opposite order (e.g. + * bottom-to-top) compared to the framebuffer. + * @dest_col_pitch: Number of bytes in the surface data between two pixels. + * Negative if the framebuffer is stored in the opposite order (e.g. + * right-to-left) compared to the framebuffer. + * @invalidate: True if the function should redraw the whole screen + * without checking the DIRTY_MEMORY_VGA dirty bitmap. + * @fn: Drawing function to be called for each row that has to be drawn. + * @opaque: Opaque pointer passed to @fn. + * @first_row: Pointer to an integer, receives the number of the first row + * that was drawn (either the first dirty row, or 0 if @invalidate is true). + * @last_row: Pointer to an integer, receives the number of the last row that + * was drawn (either the last dirty row, or @rows-1 if @invalidate is true). + */ void framebuffer_update_display( DisplaySurface *ds, - MemoryRegion *address_space, - hwaddr base, + MemoryRegionSection *mem_section, int cols, int rows, int src_width, diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c index 9b35e76ff1..ab3074fadc 100644 --- a/hw/display/milkymist-vgafb.c +++ b/hw/display/milkymist-vgafb.c @@ -71,6 +71,7 @@ struct MilkymistVgafbState { SysBusDevice parent_obj; MemoryRegion regs_region; + MemoryRegionSection fbsection; QemuConsole *con; int invalidate; @@ -91,6 +92,7 @@ static void vgafb_update_display(void *opaque) MilkymistVgafbState *s = opaque; SysBusDevice *sbd; DisplaySurface *surface = qemu_console_surface(s->con); + int src_width; int first = 0; int last = 0; drawfn fn; @@ -129,11 +131,18 @@ static void vgafb_update_display(void *opaque) break; } - framebuffer_update_display(surface, sysbus_address_space(sbd), - s->regs[R_BASEADDRESS] + s->fb_offset, + src_width = s->regs[R_HRES] * 2; + if (s->invalidate) { + framebuffer_update_memory_section(&s->fbsection, + sysbus_address_space(sbd), + s->regs[R_BASEADDRESS] + s->fb_offset, + s->regs[R_VRES], src_width); + } + + framebuffer_update_display(surface, &s->fbsection, s->regs[R_HRES], s->regs[R_VRES], - s->regs[R_HRES] * 2, + src_width, dest_width, 0, s->invalidate, diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c index fda81baff0..a7c6cd79b9 100644 --- a/hw/display/omap_lcdc.c +++ b/hw/display/omap_lcdc.c @@ -25,6 +25,7 @@ struct omap_lcd_panel_s { MemoryRegion *sysmem; MemoryRegion iomem; + MemoryRegionSection fbsection; qemu_irq irq; QemuConsole *con; @@ -215,12 +216,19 @@ static void omap_update_display(void *opaque) step = width * bpp >> 3; linesize = surface_stride(surface); - framebuffer_update_display(surface, omap_lcd->sysmem, - frame_base, width, height, + if (omap_lcd->invalidate) { + framebuffer_update_memory_section(&omap_lcd->fbsection, + omap_lcd->sysmem, frame_base, + height, step); + } + + framebuffer_update_display(surface, &omap_lcd->fbsection, + width, height, step, linesize, 0, omap_lcd->invalidate, draw_line, omap_lcd->palette, &first, &last); + if (first >= 0) { dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1); } diff --git a/hw/display/pl110.c b/hw/display/pl110.c index c574cf1a81..ef1a7b1a58 100644 --- a/hw/display/pl110.c +++ b/hw/display/pl110.c @@ -46,6 +46,7 @@ typedef struct PL110State { SysBusDevice parent_obj; MemoryRegion iomem; + MemoryRegionSection fbsection; QemuConsole *con; int version; @@ -238,12 +239,20 @@ static void pl110_update_display(void *opaque) } dest_width *= s->cols; first = 0; - framebuffer_update_display(surface, sysbus_address_space(sbd), - s->upbase, s->cols, s->rows, + if (s->invalidate) { + framebuffer_update_memory_section(&s->fbsection, + sysbus_address_space(sbd), + s->upbase, + s->rows, src_width); + } + + framebuffer_update_display(surface, &s->fbsection, + s->cols, s->rows, src_width, dest_width, 0, s->invalidate, fn, s->palette, &first, &last); + if (first >= 0) { dpy_gfx_update(s->con, 0, first, s->cols, last - first + 1); } diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c index ac3c018822..494700d07a 100644 --- a/hw/display/pxa2xx_lcd.c +++ b/hw/display/pxa2xx_lcd.c @@ -35,6 +35,7 @@ struct DMAChannel { struct PXA2xxLCDState { MemoryRegion *sysmem; MemoryRegion iomem; + MemoryRegionSection fbsection; qemu_irq irq; int irqlevel; @@ -687,8 +688,11 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s, dest_width = s->xres * s->dest_width; *miny = 0; - framebuffer_update_display(surface, s->sysmem, - addr, s->xres, s->yres, + if (s->invalidated) { + framebuffer_update_memory_section(&s->fbsection, s->sysmem, + addr, s->yres, src_width); + } + framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres, src_width, dest_width, s->dest_width, s->invalidated, fn, s->dma_ch[0].palette, miny, maxy); @@ -715,8 +719,11 @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s, dest_width = s->yres * s->dest_width; *miny = 0; - framebuffer_update_display(surface, s->sysmem, - addr, s->xres, s->yres, + if (s->invalidated) { + framebuffer_update_memory_section(&s->fbsection, s->sysmem, + addr, s->yres, src_width); + } + framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres, src_width, s->dest_width, -dest_width, s->invalidated, fn, s->dma_ch[0].palette, @@ -747,8 +754,11 @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s, dest_width = s->xres * s->dest_width; *miny = 0; - framebuffer_update_display(surface, s->sysmem, - addr, s->xres, s->yres, + if (s->invalidated) { + framebuffer_update_memory_section(&s->fbsection, s->sysmem, + addr, s->yres, src_width); + } + framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres, src_width, -dest_width, -s->dest_width, s->invalidated, fn, s->dma_ch[0].palette, miny, maxy); @@ -778,8 +788,11 @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s, dest_width = s->yres * s->dest_width; *miny = 0; - framebuffer_update_display(surface, s->sysmem, - addr, s->xres, s->yres, + if (s->invalidated) { + framebuffer_update_memory_section(&s->fbsection, s->sysmem, + addr, s->yres, src_width); + } + framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres, src_width, -s->dest_width, dest_width, s->invalidated, fn, s->dma_ch[0].palette, From d274e07c6df4cc8207b01892ff6f81118ea6083c Mon Sep 17 00:00:00 2001 From: Gonglei Date: Fri, 3 Jul 2015 17:50:57 +0800 Subject: [PATCH 11/12] qemu-doc: fix typos Signed-off-by: Gonglei Message-Id: <1435917057-9396-1-git-send-email-arei.gonglei@huawei.com> Reviewed-by: Peter Maydell Signed-off-by: Paolo Bonzini --- qemu-doc.texi | 2 +- qemu-options.hx | 2 +- qemu-tech.texi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qemu-doc.texi b/qemu-doc.texi index 0125bc7928..94af8c0f33 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -1061,7 +1061,7 @@ type is assumed. @var{server} specifies the server where the volume file specification for the given volume resides. This can be either hostname, ipv4 address or ipv6 address. ipv6 address needs to be within square brackets [ ]. -If transport type is unix, then @var{server} field should not be specifed. +If transport type is unix, then @var{server} field should not be specified. Instead @var{socket} field needs to be populated with the path to unix domain socket. diff --git a/qemu-options.hx b/qemu-options.hx index 8c9add9d25..77f5853d53 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -206,7 +206,7 @@ STEXI @item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off][,splash=@var{sp_name}][,splash-time=@var{sp_time}][,reboot-timeout=@var{rb_timeout}][,strict=on|off] @findex -boot Specify boot order @var{drives} as a string of drive letters. Valid -drive letters depend on the target achitecture. The x86 PC uses: a, b +drive letters depend on the target architecture. The x86 PC uses: a, b (floppy 1 and 2), c (first hard disk), d (first CD-ROM), n-p (Etherboot from network adapter 1-4), hard disk boot is the default. To apply a particular boot order only on the first startup, specify it via diff --git a/qemu-tech.texi b/qemu-tech.texi index 8aefa743a8..b6fcb2d61b 100644 --- a/qemu-tech.texi +++ b/qemu-tech.texi @@ -440,7 +440,7 @@ translator cannot deduce statically). @section Direct block chaining After each translated basic block is executed, QEMU uses the simulated -Program Counter (PC) and other cpu state informations (such as the CS +Program Counter (PC) and other cpu state information (such as the CS segment base value) to find the next basic block. In order to accelerate the most common cases where the new simulated PC From 178846bdd93994c1acafe4423f99ead8bb24cf38 Mon Sep 17 00:00:00 2001 From: Dmitry Poletaev Date: Wed, 8 Jul 2015 12:48:40 +0300 Subject: [PATCH 12/12] target-i386/FPU: a misprint in helper_fistll_ST0 There is a cut-and-paste mistake in the patch https://lists.gnu.org/archive/html/qemu-devel/2014-11/msg01657.html . It cause errors in guest work. Here is the bugfix. Signed-off-by: Dmitry Poletaev Reported-by: Kirill Batuzov Message-Id: <2692911436348920@web2m.yandex.ru> Signed-off-by: Paolo Bonzini --- target-i386/fpu_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c index 280adbac50..1f954e0c5c 100644 --- a/target-i386/fpu_helper.c +++ b/target-i386/fpu_helper.c @@ -272,7 +272,7 @@ int64_t helper_fistll_ST0(CPUX86State *env) old_exp_flags = get_float_exception_flags(&env->fp_status); set_float_exception_flags(0, &env->fp_status); - val = floatx80_to_int32(ST0, &env->fp_status); + val = floatx80_to_int64(ST0, &env->fp_status); if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { val = 0x8000000000000000ULL; }