mirror of https://gitee.com/openkylin/qemu.git
* 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:
commit
f793d97e45
6
cpus.c
6
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);
|
||||
|
|
5
exec.c
5
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
7
memory.c
7
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
26
qemu-char.c
26
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) {
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
5
ui/vnc.c
5
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
2
vl.c
2
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);
|
||||
|
|
Loading…
Reference in New Issue