* 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
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQEcBAABCAAGBQJVsihAAAoJEL/70l94x66DXccIAJqoO5t7b8nA3W1gkJBJxgUy
 OPAEP7N+v1qZNtYtbmC0p29JaaMPiauNnOQGYQ/hRj3Ccv3bcWg4gbhlxHdjZT5e
 fh5aYxZr4K0D8dWbnFhGuvATiaiddfwRB3YCDx2CW1DPgL2xwzdwmYNXPvpnA2hj
 3LDqC74v3lppCRpKPa4//xvpkwz0SJrJjbxvKBPRdVSAi8ovRJF27ArM2bVXYpYS
 uWhXxhqw0Sx6nqZoz+EpfRsHHirGtsj8iGxGgRre3kqFTLYmjtg0wSBrSvCU3Eaw
 1kmceS7ggJq82mIOFnjYE1Sf+JPOySSieHdKEPDEWezsQkBzBsQ9KaSQJnmLCa8=
 =0FIR
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2015-07-24 13:07:10 +01:00
commit f793d97e45
23 changed files with 216 additions and 70 deletions

6
cpus.c
View File

@ -954,6 +954,8 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
CPUState *cpu = arg; CPUState *cpu = arg;
int r; int r;
rcu_register_thread();
qemu_mutex_lock_iothread(); qemu_mutex_lock_iothread();
qemu_thread_get_self(cpu->thread); qemu_thread_get_self(cpu->thread);
cpu->thread_id = qemu_get_thread_id(); cpu->thread_id = qemu_get_thread_id();
@ -995,6 +997,8 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
sigset_t waitset; sigset_t waitset;
int r; int r;
rcu_register_thread();
qemu_mutex_lock_iothread(); qemu_mutex_lock_iothread();
qemu_thread_get_self(cpu->thread); qemu_thread_get_self(cpu->thread);
cpu->thread_id = qemu_get_thread_id(); cpu->thread_id = qemu_get_thread_id();
@ -1034,6 +1038,8 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
{ {
CPUState *cpu = arg; CPUState *cpu = arg;
rcu_register_thread();
qemu_mutex_lock_iothread(); qemu_mutex_lock_iothread();
qemu_tcg_init_cpu_signals(); qemu_tcg_init_cpu_signals();
qemu_thread_get_self(cpu->thread); qemu_thread_get_self(cpu->thread);

5
exec.c
View File

@ -954,7 +954,10 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
iotlb |= PHYS_SECTION_ROM; iotlb |= PHYS_SECTION_ROM;
} }
} else { } 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; iotlb += xlat;
} }

View File

@ -21,12 +21,40 @@
#include "ui/console.h" #include "ui/console.h"
#include "framebuffer.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. */ /* Render an image from a shared memory framebuffer. */
void framebuffer_update_display( void framebuffer_update_display(
DisplaySurface *ds, DisplaySurface *ds,
MemoryRegion *address_space, MemoryRegionSection *mem_section,
hwaddr base,
int cols, /* Width in pixels. */ int cols, /* Width in pixels. */
int rows, /* Height in pixels. */ int rows, /* Height in pixels. */
int src_width, /* Length of source line, in bytes. */ int src_width, /* Length of source line, in bytes. */
@ -41,51 +69,33 @@ void framebuffer_update_display(
hwaddr src_len; hwaddr src_len;
uint8_t *dest; uint8_t *dest;
uint8_t *src; uint8_t *src;
uint8_t *src_base;
int first, last = 0; int first, last = 0;
int dirty; int dirty;
int i; int i;
ram_addr_t addr; ram_addr_t addr;
MemoryRegionSection mem_section;
MemoryRegion *mem; MemoryRegion *mem;
i = *first_row; i = *first_row;
*first_row = -1; *first_row = -1;
src_len = src_width * rows; src_len = src_width * rows;
mem_section = memory_region_find(address_space, base, src_len); mem = mem_section->mr;
mem = mem_section.mr; if (!mem) {
if (int128_get64(mem_section.size) != src_len || return;
!memory_region_is_ram(mem_section.mr)) {
goto out;
} }
assert(mem);
assert(mem_section.offset_within_address_space == base);
memory_region_sync_dirty_bitmap(mem); 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); addr = mem_section->offset_within_region;
/* If we can't map the framebuffer then bail. We could try harder, src = memory_region_get_ram_ptr(mem) + addr;
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;
dest = surface_data(ds); dest = surface_data(ds);
if (dest_col_pitch < 0) if (dest_col_pitch < 0) {
dest -= dest_col_pitch * (cols - 1); dest -= dest_col_pitch * (cols - 1);
}
if (dest_row_pitch < 0) { if (dest_row_pitch < 0) {
dest -= dest_row_pitch * (rows - 1); dest -= dest_row_pitch * (rows - 1);
} }
first = -1; first = -1;
addr = mem_section.offset_within_region;
addr += i * src_width; addr += i * src_width;
src += i * src_width; src += i * src_width;
@ -104,14 +114,11 @@ void framebuffer_update_display(
src += src_width; src += src_width;
dest += dest_row_pitch; dest += dest_row_pitch;
} }
cpu_physical_memory_unmap(src_base, src_len, 0, 0);
if (first < 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); DIRTY_MEMORY_VGA);
*first_row = first; *first_row = first;
*last_row = last; *last_row = last;
out:
memory_region_unref(mem);
} }

View File

@ -7,10 +7,50 @@
typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int); 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( void framebuffer_update_display(
DisplaySurface *ds, DisplaySurface *ds,
MemoryRegion *address_space, MemoryRegionSection *mem_section,
hwaddr base,
int cols, int cols,
int rows, int rows,
int src_width, int src_width,

View File

@ -71,6 +71,7 @@ struct MilkymistVgafbState {
SysBusDevice parent_obj; SysBusDevice parent_obj;
MemoryRegion regs_region; MemoryRegion regs_region;
MemoryRegionSection fbsection;
QemuConsole *con; QemuConsole *con;
int invalidate; int invalidate;
@ -91,6 +92,7 @@ static void vgafb_update_display(void *opaque)
MilkymistVgafbState *s = opaque; MilkymistVgafbState *s = opaque;
SysBusDevice *sbd; SysBusDevice *sbd;
DisplaySurface *surface = qemu_console_surface(s->con); DisplaySurface *surface = qemu_console_surface(s->con);
int src_width;
int first = 0; int first = 0;
int last = 0; int last = 0;
drawfn fn; drawfn fn;
@ -129,11 +131,18 @@ static void vgafb_update_display(void *opaque)
break; break;
} }
framebuffer_update_display(surface, sysbus_address_space(sbd), src_width = s->regs[R_HRES] * 2;
s->regs[R_BASEADDRESS] + s->fb_offset, 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_HRES],
s->regs[R_VRES], s->regs[R_VRES],
s->regs[R_HRES] * 2, src_width,
dest_width, dest_width,
0, 0,
s->invalidate, s->invalidate,

View File

@ -25,6 +25,7 @@
struct omap_lcd_panel_s { struct omap_lcd_panel_s {
MemoryRegion *sysmem; MemoryRegion *sysmem;
MemoryRegion iomem; MemoryRegion iomem;
MemoryRegionSection fbsection;
qemu_irq irq; qemu_irq irq;
QemuConsole *con; QemuConsole *con;
@ -215,12 +216,19 @@ static void omap_update_display(void *opaque)
step = width * bpp >> 3; step = width * bpp >> 3;
linesize = surface_stride(surface); linesize = surface_stride(surface);
framebuffer_update_display(surface, omap_lcd->sysmem, if (omap_lcd->invalidate) {
frame_base, width, height, 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, step, linesize, 0,
omap_lcd->invalidate, omap_lcd->invalidate,
draw_line, omap_lcd->palette, draw_line, omap_lcd->palette,
&first, &last); &first, &last);
if (first >= 0) { if (first >= 0) {
dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1); dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1);
} }

View File

@ -46,6 +46,7 @@ typedef struct PL110State {
SysBusDevice parent_obj; SysBusDevice parent_obj;
MemoryRegion iomem; MemoryRegion iomem;
MemoryRegionSection fbsection;
QemuConsole *con; QemuConsole *con;
int version; int version;
@ -238,12 +239,20 @@ static void pl110_update_display(void *opaque)
} }
dest_width *= s->cols; dest_width *= s->cols;
first = 0; first = 0;
framebuffer_update_display(surface, sysbus_address_space(sbd), if (s->invalidate) {
s->upbase, s->cols, s->rows, 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, src_width, dest_width, 0,
s->invalidate, s->invalidate,
fn, s->palette, fn, s->palette,
&first, &last); &first, &last);
if (first >= 0) { if (first >= 0) {
dpy_gfx_update(s->con, 0, first, s->cols, last - first + 1); dpy_gfx_update(s->con, 0, first, s->cols, last - first + 1);
} }

View File

@ -35,6 +35,7 @@ struct DMAChannel {
struct PXA2xxLCDState { struct PXA2xxLCDState {
MemoryRegion *sysmem; MemoryRegion *sysmem;
MemoryRegion iomem; MemoryRegion iomem;
MemoryRegionSection fbsection;
qemu_irq irq; qemu_irq irq;
int irqlevel; int irqlevel;
@ -687,8 +688,11 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
dest_width = s->xres * s->dest_width; dest_width = s->xres * s->dest_width;
*miny = 0; *miny = 0;
framebuffer_update_display(surface, s->sysmem, if (s->invalidated) {
addr, s->xres, s->yres, 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, src_width, dest_width, s->dest_width,
s->invalidated, s->invalidated,
fn, s->dma_ch[0].palette, miny, maxy); 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; dest_width = s->yres * s->dest_width;
*miny = 0; *miny = 0;
framebuffer_update_display(surface, s->sysmem, if (s->invalidated) {
addr, s->xres, s->yres, 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, src_width, s->dest_width, -dest_width,
s->invalidated, s->invalidated,
fn, s->dma_ch[0].palette, 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; dest_width = s->xres * s->dest_width;
*miny = 0; *miny = 0;
framebuffer_update_display(surface, s->sysmem, if (s->invalidated) {
addr, s->xres, s->yres, 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, src_width, -dest_width, -s->dest_width,
s->invalidated, s->invalidated,
fn, s->dma_ch[0].palette, miny, maxy); 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; dest_width = s->yres * s->dest_width;
*miny = 0; *miny = 0;
framebuffer_update_display(surface, s->sysmem, if (s->invalidated) {
addr, s->xres, s->yres, 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, src_width, -s->dest_width, dest_width,
s->invalidated, s->invalidated,
fn, s->dma_ch[0].palette, fn, s->dma_ch[0].palette,

View File

@ -1239,10 +1239,15 @@ int scsi_cdb_length(uint8_t *buf) {
int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf) int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
{ {
int rc; int rc;
int len;
cmd->lba = -1; 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) { switch (dev->type) {
case TYPE_TAPE: case TYPE_TAPE:
rc = scsi_req_stream_xfer(cmd, dev, buf); rc = scsi_req_stream_xfer(cmd, dev, buf);

View File

@ -765,6 +765,9 @@ static inline bool media_is_dvd(SCSIDiskState *s)
if (!blk_is_inserted(s->qdev.conf.blk)) { if (!blk_is_inserted(s->qdev.conf.blk)) {
return false; return false;
} }
if (s->tray_open) {
return false;
}
blk_get_geometry(s->qdev.conf.blk, &nb_sectors); blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
return nb_sectors > CD_MAX_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)) { if (!blk_is_inserted(s->qdev.conf.blk)) {
return false; return false;
} }
if (s->tray_open) {
return false;
}
blk_get_geometry(s->qdev.conf.blk, &nb_sectors); blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
return nb_sectors <= CD_MAX_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) { if (s->qdev.type != TYPE_ROM) {
return -1; 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); memset(outbuf, 0, 40);
stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */ stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
stw_be_p(&outbuf[6], current); stw_be_p(&outbuf[6], current);

View File

@ -180,6 +180,7 @@ struct MemoryRegion {
bool warning_printed; /* For reservations */ bool warning_printed; /* For reservations */
bool flush_coalesced_mmio; bool flush_coalesced_mmio;
bool global_locking; bool global_locking;
uint8_t vga_logging_count;
MemoryRegion *alias; MemoryRegion *alias;
hwaddr alias_offset; hwaddr alias_offset;
int32_t priority; int32_t priority;

View File

@ -18,6 +18,7 @@
#include "sysemu/iothread.h" #include "sysemu/iothread.h"
#include "qmp-commands.h" #include "qmp-commands.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/rcu.h"
typedef ObjectClass IOThreadClass; typedef ObjectClass IOThreadClass;
@ -31,6 +32,8 @@ static void *iothread_run(void *opaque)
IOThread *iothread = opaque; IOThread *iothread = opaque;
bool blocking; bool blocking;
rcu_register_thread();
qemu_mutex_lock(&iothread->init_done_lock); qemu_mutex_lock(&iothread->init_done_lock);
iothread->thread_id = qemu_get_thread_id(); iothread->thread_id = qemu_get_thread_id();
qemu_cond_signal(&iothread->init_done_cond); qemu_cond_signal(&iothread->init_done_cond);
@ -45,6 +48,8 @@ static void *iothread_run(void *opaque)
} }
aio_context_release(iothread->ctx); aio_context_release(iothread->ctx);
} }
rcu_unregister_thread();
return NULL; return NULL;
} }

View File

@ -1433,8 +1433,15 @@ void memory_region_notify_iommu(MemoryRegion *mr,
void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
{ {
uint8_t mask = 1 << client; uint8_t mask = 1 << client;
uint8_t old_logging;
assert(client == DIRTY_MEMORY_VGA); 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(); memory_region_transaction_begin();
mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask); mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
memory_region_update_pending |= mr->enabled; memory_region_update_pending |= mr->enabled;

View File

@ -22,6 +22,7 @@
#include "block/block.h" #include "block/block.h"
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "qemu/sockets.h" #include "qemu/sockets.h"
#include "qemu/rcu.h"
#include "migration/block.h" #include "migration/block.h"
#include "qemu/thread.h" #include "qemu/thread.h"
#include "qmp-commands.h" #include "qmp-commands.h"
@ -917,6 +918,8 @@ static void *migration_thread(void *opaque)
int64_t start_time = initial_time; int64_t start_time = initial_time;
bool old_vm_running = false; bool old_vm_running = false;
rcu_register_thread();
qemu_savevm_state_header(s->file); qemu_savevm_state_header(s->file);
qemu_savevm_state_begin(s->file, &s->params); 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_bh_schedule(s->cleanup_bh);
qemu_mutex_unlock_iothread(); qemu_mutex_unlock_iothread();
rcu_unregister_thread();
return NULL; return NULL;
} }

View File

@ -807,7 +807,8 @@ static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_)
} }
if (now_active) { 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_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL);
g_source_attach(iwp->src, NULL); g_source_attach(iwp->src, NULL);
} else { } else {
@ -2797,7 +2798,10 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
#ifdef MSG_CMSG_CLOEXEC #ifdef MSG_CMSG_CLOEXEC
flags |= MSG_CMSG_CLOEXEC; flags |= MSG_CMSG_CLOEXEC;
#endif #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) { if (ret > 0 && s->is_unix) {
unix_process_msgfd(chr, &msg); 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) static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
{ {
TCPCharDriver *s = chr->opaque; 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 #endif
@ -2847,12 +2857,6 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
uint8_t buf[READ_BUF_LEN]; uint8_t buf[READ_BUF_LEN];
int len, size; int len, size;
if (cond & G_IO_HUP) {
/* connection closed */
tcp_chr_disconnect(chr);
return TRUE;
}
if (!s->connected || s->max_size <= 0) { if (!s->connected || s->max_size <= 0) {
return TRUE; return TRUE;
} }
@ -2860,7 +2864,9 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
if (len > s->max_size) if (len > s->max_size)
len = s->max_size; len = s->max_size;
size = tcp_chr_recv(chr, (void *)buf, len); size = tcp_chr_recv(chr, (void *)buf, len);
if (size == 0) { if (size == 0 ||
(size < 0 &&
socket_error() != EAGAIN && socket_error() != EWOULDBLOCK)) {
/* connection closed */ /* connection closed */
tcp_chr_disconnect(chr); tcp_chr_disconnect(chr);
} else if (size > 0) { } else if (size > 0) {

View File

@ -1061,7 +1061,7 @@ type is assumed.
@var{server} specifies the server where the volume file specification for @var{server} specifies the server where the volume file specification for
the given volume resides. This can be either hostname, ipv4 address the given volume resides. This can be either hostname, ipv4 address
or ipv6 address. ipv6 address needs to be within square brackets [ ]. 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 Instead @var{socket} field needs to be populated with the path to unix domain
socket. socket.

View File

@ -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] @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 @findex -boot
Specify boot order @var{drives} as a string of drive letters. Valid 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 (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 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 particular boot order only on the first startup, specify it via

View File

@ -440,7 +440,7 @@ translator cannot deduce statically).
@section Direct block chaining @section Direct block chaining
After each translated basic block is executed, QEMU uses the simulated 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. segment base value) to find the next basic block.
In order to accelerate the most common cases where the new simulated PC In order to accelerate the most common cases where the new simulated PC

View File

@ -272,7 +272,7 @@ int64_t helper_fistll_ST0(CPUX86State *env)
old_exp_flags = get_float_exception_flags(&env->fp_status); old_exp_flags = get_float_exception_flags(&env->fp_status);
set_float_exception_flags(0, &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) { if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) {
val = 0x8000000000000000ULL; val = 0x8000000000000000ULL;
} }

View File

@ -108,6 +108,8 @@ static void *rcu_q_reader(void *arg)
long long n_reads_local = 0; long long n_reads_local = 0;
struct list_element *el; struct list_element *el;
rcu_register_thread();
*(struct rcu_reader_data **)arg = &rcu_reader; *(struct rcu_reader_data **)arg = &rcu_reader;
atomic_inc(&nthreadsrunning); atomic_inc(&nthreadsrunning);
while (goflag == GOFLAG_INIT) { while (goflag == GOFLAG_INIT) {
@ -129,6 +131,8 @@ static void *rcu_q_reader(void *arg)
qemu_mutex_lock(&counts_mutex); qemu_mutex_lock(&counts_mutex);
n_reads += n_reads_local; n_reads += n_reads_local;
qemu_mutex_unlock(&counts_mutex); qemu_mutex_unlock(&counts_mutex);
rcu_unregister_thread();
return NULL; return NULL;
} }

View File

@ -2520,7 +2520,7 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
size_t i, pwlen; size_t i, pwlen;
unsigned char key[8]; unsigned char key[8];
time_t now = time(NULL); time_t now = time(NULL);
QCryptoCipher *cipher; QCryptoCipher *cipher = NULL;
Error *err = NULL; Error *err = NULL;
if (!vs->vd->password) { 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); start_client_init(vs);
} }
qcrypto_cipher_free(cipher);
return 0; return 0;
reject: reject:
@ -2584,6 +2586,7 @@ reject:
} }
vnc_flush(vs); vnc_flush(vs);
vnc_client_error(vs); vnc_client_error(vs);
qcrypto_cipher_free(cipher);
return 0; return 0;
} }

View File

@ -216,6 +216,8 @@ static void *call_rcu_thread(void *opaque)
{ {
struct rcu_head *node; struct rcu_head *node;
rcu_register_thread();
for (;;) { for (;;) {
int tries = 0; int tries = 0;
int n = atomic_read(&rcu_call_count); int n = atomic_read(&rcu_call_count);

2
vl.c
View File

@ -2061,7 +2061,6 @@ static void select_vgahw (const char *p)
static DisplayType select_display(const char *p) static DisplayType select_display(const char *p)
{ {
Error *err = NULL;
const char *opts; const char *opts;
DisplayType display = DT_DEFAULT; DisplayType display = DT_DEFAULT;
@ -2130,6 +2129,7 @@ static DisplayType select_display(const char *p)
} else if (strstart(p, "vnc", &opts)) { } else if (strstart(p, "vnc", &opts)) {
#ifdef CONFIG_VNC #ifdef CONFIG_VNC
if (*opts == '=') { if (*opts == '=') {
Error *err = NULL;
if (vnc_parse(opts + 1, &err) == NULL) { if (vnc_parse(opts + 1, &err) == NULL) {
error_report_err(err); error_report_err(err);
exit(1); exit(1);