summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-07-24 13:07:10 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-07-24 13:07:10 +0100
commitf793d97e454a56d17e404004867985622ca1a63b (patch)
treef25e4df0fec7c44f1fe7bf53903e46491f8dedb9
parent30fdfae49d53cfc678859095e49ac60b79562d6f (diff)
parent178846bdd93994c1acafe4423f99ead8bb24cf38 (diff)
downloadqemu-f793d97e454a56d17e404004867985622ca1a63b.tar.gz
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* qemu-char fixes * SCSI fixes (including CVE-2015-5158) * RCU fixes * Framebuffer logic to set DIRTY_MEMORY_VGA * Fix compiler warning for --disable-vnc * qemu-doc fixes * x86 TCG pasto fix # gpg: Signature made Fri Jul 24 12:57:52 2015 BST using RSA key ID 78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: target-i386/FPU: a misprint in helper_fistll_ST0 qemu-doc: fix typos framebuffer: set DIRTY_MEMORY_VGA on RAM that is used for the framebuffer memory: count number of active VGA logging clients vl: Fix compiler warning for builds without VNC scsi: Handle no media case for scsi_get_configuration rcu: actually register threads that have RCU read-side critical sections scsi: fix buffer overflow in scsi_req_parse_cdb (CVE-2015-5158) vnc: fix memory leak qemu-char: Fix missed data on unix socket qemu-char: handle EINTR for TCP character devices exec.c: Use atomic_rcu_read() to access dispatch in memory_region_section_get_iotlb() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--cpus.c6
-rw-r--r--exec.c5
-rw-r--r--hw/display/framebuffer.c75
-rw-r--r--hw/display/framebuffer.h44
-rw-r--r--hw/display/milkymist-vgafb.c15
-rw-r--r--hw/display/omap_lcdc.c12
-rw-r--r--hw/display/pl110.c13
-rw-r--r--hw/display/pxa2xx_lcd.c29
-rw-r--r--hw/scsi/scsi-bus.c7
-rw-r--r--hw/scsi/scsi-disk.c16
-rw-r--r--include/exec/memory.h1
-rw-r--r--iothread.c5
-rw-r--r--memory.c7
-rw-r--r--migration/migration.c4
-rw-r--r--qemu-char.c26
-rw-r--r--qemu-doc.texi2
-rw-r--r--qemu-options.hx2
-rw-r--r--qemu-tech.texi2
-rw-r--r--target-i386/fpu_helper.c2
-rw-r--r--tests/test-rcu-list.c4
-rw-r--r--ui/vnc.c5
-rw-r--r--util/rcu.c2
-rw-r--r--vl.c2
23 files changed, 216 insertions, 70 deletions
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/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(&section->address_space->dispatch);
+ iotlb = section - d->map.sections;
iotlb += xlat;
}
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,
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);
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);
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/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/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;
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/qemu-char.c b/qemu-char.c
index 617e034455..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 {
@@ -2797,7 +2798,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 +2812,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
@@ -2847,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;
}
@@ -2860,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) {
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
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;
}
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/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;
}
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);
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);