diff options
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | acl.c | 4 | ||||
-rwxr-xr-x | configure | 7 | ||||
-rw-r--r-- | cpu-all.h | 4 | ||||
-rw-r--r-- | cpus.c | 14 | ||||
-rw-r--r-- | cpus.h | 1 | ||||
-rw-r--r-- | darwin-user/main.c | 2 | ||||
-rw-r--r-- | docs/qapi-code-gen.txt | 4 | ||||
-rw-r--r-- | exec.c | 13 | ||||
-rw-r--r-- | hw/fw_cfg.c | 102 | ||||
-rw-r--r-- | hw/opencores_eth.c | 29 | ||||
-rw-r--r-- | hw/qxl-render.c | 36 | ||||
-rw-r--r-- | hw/qxl.c | 26 | ||||
-rw-r--r-- | hw/qxl.h | 3 | ||||
-rw-r--r-- | hw/sysbus.c | 2 | ||||
-rw-r--r-- | ia64-dis.c | 3 | ||||
-rw-r--r-- | migration-fd.c | 23 | ||||
-rw-r--r-- | migration.c | 2 | ||||
-rw-r--r-- | net/tap-linux.c | 6 | ||||
-rw-r--r-- | oslib-posix.c | 22 | ||||
-rw-r--r-- | qemu-barrier.h | 2 | ||||
-rw-r--r-- | qemu-tls.h | 52 |
24 files changed, 253 insertions, 124 deletions
diff --git a/.gitignore b/.gitignore index 6d2acab09a..406f75f2b6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,10 @@ libhw64 libuser linux-headers/asm qapi-generated +qapi-types.[ch] +qapi-visit.[ch] +qmp-commands.h +qmp-marshal.c qemu-doc.html qemu-tech.html qemu-doc.info diff --git a/MAINTAINERS b/MAINTAINERS index 4535eeb61f..bccdd4f78f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -303,9 +303,9 @@ M: Alexander Graf <agraf@suse.de> S: Maintained F: hw/ppc_oldworld.c -Prep -M: qemu-devel@nongnu.org -S: Orphan +PReP +M: Andreas Färber <andreas.faerber@web.de> +S: Odd Fixes F: hw/ppc_prep.c SH4 Machines @@ -75,7 +75,7 @@ defconfig: -include config-all-devices.mak -build-all: $(DOCS) $(TOOLS) recurse-all +build-all: $(DOCS) $(TOOLS) $(CHECKS) recurse-all config-host.h: config-host.h-timestamp config-host.h-timestamp: config-host.mak @@ -219,7 +219,7 @@ clean: # avoid old build problems by removing potentially incorrect old files rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h rm -f qemu-options.def - rm -f *.o *.d *.a *.lo $(TOOLS) qemu-ga TAGS cscope.* *.pod *~ */*~ + rm -f *.o *.d *.a *.lo $(TOOLS) $(CHECKS) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -Rf .libs rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d qapi/*.o qapi/*.d qga/*.o qga/*.d rm -f qemu-img-cmds.h @@ -305,6 +305,12 @@ endif test speed: all $(MAKE) -C tests $@ +.PHONY: check +check: $(patsubst %,run-check-%,$(CHECKS)) + +run-check-%: % + ./$< + .PHONY: TAGS TAGS: find "$(SRC_PATH)" -name '*.[hc]' -print0 | xargs -0 etags @@ -95,13 +95,13 @@ int qemu_acl_party_is_allowed(qemu_acl *acl, void qemu_acl_reset(qemu_acl *acl) { - qemu_acl_entry *entry; + qemu_acl_entry *entry, *next_entry; /* Put back to deny by default, so there is no window * of "open access" while the user re-initializes the * access control list */ acl->defaultDeny = 1; - QTAILQ_FOREACH(entry, &acl->entries, next) { + QTAILQ_FOREACH_SAFE(entry, &acl->entries, next, next_entry) { QTAILQ_REMOVE(&acl->entries, entry, next); free(entry->match); free(entry); @@ -169,7 +169,7 @@ mixemu="no" aix="no" blobs="yes" pkgversion="" -check_utests="no" +check_utests="" user_pie="no" zero_malloc="" trace_backend="nop" @@ -2668,8 +2668,8 @@ if test "$softmmu" = yes ; then tools="qemu-ga\$(EXESUF) $tools" fi if [ "$check_utests" = "yes" ]; then - tools="check-qint check-qstring check-qdict check-qlist $tools" - tools="check-qfloat check-qjson $tools" + checks="check-qint check-qstring check-qdict check-qlist" + checks="check-qfloat check-qjson test-coroutine $checks" fi fi fi @@ -3143,6 +3143,7 @@ if test "$trace_default" = "yes"; then fi echo "TOOLS=$tools" >> $config_host_mak +echo "CHECKS=$checks" >> $config_host_mak echo "ROMS=$roms" >> $config_host_mak echo "MAKE=$make" >> $config_host_mak echo "INSTALL=$install" >> $config_host_mak @@ -20,6 +20,7 @@ #define CPU_ALL_H #include "qemu-common.h" +#include "qemu-tls.h" #include "cpu-common.h" /* some important defines: @@ -334,7 +335,8 @@ void cpu_dump_statistics(CPUState *env, FILE *f, fprintf_function cpu_fprintf, void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...) GCC_FMT_ATTR(2, 3); extern CPUState *first_cpu; -extern CPUState *cpu_single_env; +DECLARE_TLS(CPUState *,cpu_single_env); +#define cpu_single_env get_tls(cpu_single_env) /* Flags for use in ENV->INTERRUPT_PENDING. @@ -748,6 +748,8 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) return NULL; } +static void tcg_exec_all(void); + static void *qemu_tcg_cpu_thread_fn(void *arg) { CPUState *env = arg; @@ -769,7 +771,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) } while (1) { - cpu_exec_all(); + tcg_exec_all(); if (use_icount && qemu_clock_deadline(vm_clock) <= 0) { qemu_notify_event(); } @@ -1016,7 +1018,7 @@ static int tcg_cpu_exec(CPUState *env) return ret; } -bool cpu_exec_all(void) +static void tcg_exec_all(void) { int r; @@ -1033,12 +1035,7 @@ bool cpu_exec_all(void) (env->singlestep_enabled & SSTEP_NOTIMER) == 0); if (cpu_can_run(env)) { - if (kvm_enabled()) { - r = kvm_cpu_exec(env); - qemu_kvm_eat_signals(env); - } else { - r = tcg_cpu_exec(env); - } + r = tcg_cpu_exec(env); if (r == EXCP_DEBUG) { cpu_handle_guest_debug(env); break; @@ -1048,7 +1045,6 @@ bool cpu_exec_all(void) } } exit_request = 0; - return !all_cpu_threads_idle(); } void set_numa_modes(void) @@ -14,7 +14,6 @@ void cpu_synchronize_all_post_init(void); /* vl.c */ extern int smp_cores; extern int smp_threads; -bool cpu_exec_all(void); void set_numa_modes(void); void set_cpu_log(const char *optarg); void set_cpu_log_filename(const char *optarg); diff --git a/darwin-user/main.c b/darwin-user/main.c index 1a881a0a60..c0f14f8260 100644 --- a/darwin-user/main.c +++ b/darwin-user/main.c @@ -729,8 +729,6 @@ static void usage(void) /* XXX: currently only used for async signals (see signal.c) */ CPUState *global_env; -/* used only if single thread */ -CPUState *cpu_single_env = NULL; /* used to free thread contexts */ TaskState *first_task_state; diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index f345866f57..c0a9325db8 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -41,7 +41,7 @@ dictionary. This corresponds to a struct in C or an Object in JSON. An example of a complex type is: { 'type': 'MyType', - 'data' { 'member1': 'str', 'member2': 'int', '*member3': 'str } } + 'data': { 'member1': 'str', 'member2': 'int', '*member3': 'str' } } The use of '*' as a prefix to the name means the member is optional. Optional members should always be added to the end of the dictionary to preserve @@ -63,7 +63,7 @@ An example command is: { 'command': 'my-command', 'data': { 'arg1': 'str', '*arg2': 'str' }, - 'returns': 'str' ] + 'returns': 'str' } Command names should be all lower case with words separated by a hyphen. @@ -120,7 +120,7 @@ static MemoryRegion *system_io; CPUState *first_cpu; /* current CPU in the current thread. It is only valid inside cpu_exec() */ -CPUState *cpu_single_env; +DEFINE_TLS(CPUState *,cpu_single_env); /* 0 = Do not count executed instructions. 1 = Precise instruction counting. 2 = Adaptive rate instruction counting. */ @@ -2873,7 +2873,7 @@ static void *file_ram_alloc(RAMBlock *block, static ram_addr_t find_ram_offset(ram_addr_t size) { RAMBlock *block, *next_block; - ram_addr_t offset = 0, mingap = RAM_ADDR_MAX; + ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX; if (QLIST_EMPTY(&ram_list.blocks)) return 0; @@ -2889,10 +2889,17 @@ static ram_addr_t find_ram_offset(ram_addr_t size) } } if (next - end >= size && next - end < mingap) { - offset = end; + offset = end; mingap = next - end; } } + + if (offset == RAM_ADDR_MAX) { + fprintf(stderr, "Failed to find gap of requested size: %" PRIu64 "\n", + (uint64_t)size); + abort(); + } + return offset; } diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index 8df265c61d..dbcb888bbd 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -60,71 +60,55 @@ struct FWCfgState { #define JPG_FILE 0 #define BMP_FILE 1 -static FILE *probe_splashfile(char *filename, int *file_sizep, int *file_typep) +static char *read_splashfile(char *filename, int *file_sizep, int *file_typep) { - FILE *fp = NULL; - int fop_ret; - int file_size; + GError *err = NULL; + gboolean res; + gchar *content; int file_type = -1; - unsigned char buf[2] = {0, 0}; - unsigned int filehead_value = 0; + unsigned int filehead = 0; int bmp_bpp; - fp = fopen(filename, "rb"); - if (fp == NULL) { - error_report("failed to open file '%s'.", filename); - return fp; + res = g_file_get_contents(filename, &content, (gsize *)file_sizep, &err); + if (res == FALSE) { + error_report("failed to read splash file '%s'", filename); + g_error_free(err); + return NULL; } + /* check file size */ - fseek(fp, 0L, SEEK_END); - file_size = ftell(fp); - if (file_size < 2) { - error_report("file size is less than 2 bytes '%s'.", filename); - fclose(fp); - fp = NULL; - return fp; + if (*file_sizep < 30) { + goto error; } + /* check magic ID */ - fseek(fp, 0L, SEEK_SET); - fop_ret = fread(buf, 1, 2, fp); - if (fop_ret != 2) { - error_report("Could not read header from '%s': %s", - filename, strerror(errno)); - fclose(fp); - fp = NULL; - return fp; - } - filehead_value = (buf[0] + (buf[1] << 8)) & 0xffff; - if (filehead_value == 0xd8ff) { + filehead = ((content[0] & 0xff) + (content[1] << 8)) & 0xffff; + if (filehead == 0xd8ff) { file_type = JPG_FILE; + } else if (filehead == 0x4d42) { + file_type = BMP_FILE; } else { - if (filehead_value == 0x4d42) { - file_type = BMP_FILE; - } - } - if (file_type < 0) { - error_report("'%s' not jpg/bmp file,head:0x%x.", - filename, filehead_value); - fclose(fp); - fp = NULL; - return fp; + goto error; } + /* check BMP bpp */ if (file_type == BMP_FILE) { - fseek(fp, 28, SEEK_SET); - fop_ret = fread(buf, 1, 2, fp); - bmp_bpp = (buf[0] + (buf[1] << 8)) & 0xffff; + bmp_bpp = (content[28] + (content[29] << 8)) & 0xffff; if (bmp_bpp != 24) { - error_report("only 24bpp bmp file is supported."); - fclose(fp); - fp = NULL; - return fp; + goto error; } } + /* return values */ - *file_sizep = file_size; *file_typep = file_type; - return fp; + + return content; + +error: + error_report("splash file '%s' format not recognized; must be JPEG " + "or 24 bit BMP", filename); + g_free(content); + return NULL; } static void fw_cfg_bootsplash(FWCfgState *s) @@ -132,9 +116,7 @@ static void fw_cfg_bootsplash(FWCfgState *s) int boot_splash_time = -1; const char *boot_splash_filename = NULL; char *p; - char *filename; - FILE *fp; - int fop_ret; + char *filename, *file_data; int file_size; int file_type = -1; const char *temp; @@ -174,27 +156,19 @@ static void fw_cfg_bootsplash(FWCfgState *s) error_report("failed to find file '%s'.", boot_splash_filename); return; } - /* probing the file */ - fp = probe_splashfile(filename, &file_size, &file_type); - if (fp == NULL) { + + /* loading file data */ + file_data = read_splashfile(filename, &file_size, &file_type); + if (file_data == NULL) { g_free(filename); return; } - /* loading file data */ if (boot_splash_filedata != NULL) { g_free(boot_splash_filedata); } - boot_splash_filedata = g_malloc(file_size); + boot_splash_filedata = (uint8_t *)file_data; boot_splash_filedata_size = file_size; - fseek(fp, 0L, SEEK_SET); - fop_ret = fread(boot_splash_filedata, 1, file_size, fp); - if (fop_ret != file_size) { - error_report("failed to read data from '%s'.", - boot_splash_filename); - fclose(fp); - return; - } - fclose(fp); + /* insert data */ if (file_type == JPG_FILE) { fw_cfg_add_file(s, "bootsplash.jpg", diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c index 64b616ec1c..2c1e475395 100644 --- a/hw/opencores_eth.c +++ b/hw/opencores_eth.c @@ -382,6 +382,7 @@ static ssize_t open_eth_receive(VLANClientState *nc, OpenEthState *s = DO_UPCAST(NICState, nc, nc)->opaque; size_t maxfl = GET_REGFIELD(s, PACKETLEN, MAXFL); size_t minfl = GET_REGFIELD(s, PACKETLEN, MINFL); + size_t fcsl = 4; bool miss = true; trace_open_eth_receive((unsigned)size); @@ -418,6 +419,7 @@ static ssize_t open_eth_receive(VLANClientState *nc, #else { #endif + static const uint8_t zero[64] = {0}; desc *desc = rx_desc(s); size_t copy_size = GET_REGBIT(s, MODER, HUGEN) ? 65536 : maxfl; @@ -426,11 +428,13 @@ static ssize_t open_eth_receive(VLANClientState *nc, if (copy_size > size) { copy_size = size; + } else { + fcsl = 0; } if (miss) { desc->len_flags |= RXD_M; } - if (size > maxfl) { + if (GET_REGBIT(s, MODER, HUGEN) && size > maxfl) { desc->len_flags |= RXD_TL; } #ifdef USE_RECSMALL @@ -442,13 +446,28 @@ static ssize_t open_eth_receive(VLANClientState *nc, cpu_physical_memory_write(desc->buf_ptr, buf, copy_size); if (GET_REGBIT(s, MODER, PAD) && copy_size < minfl) { - static const uint8_t zero[65536] = {0}; + if (minfl - copy_size > fcsl) { + fcsl = 0; + } else { + fcsl -= minfl - copy_size; + } + while (copy_size < minfl) { + size_t zero_sz = minfl - copy_size < sizeof(zero) ? + minfl - copy_size : sizeof(zero); - cpu_physical_memory_write(desc->buf_ptr + copy_size, - zero, minfl - copy_size); - copy_size = minfl; + cpu_physical_memory_write(desc->buf_ptr + copy_size, + zero, zero_sz); + copy_size += zero_sz; + } } + /* There's no FCS in the frames handed to us by the QEMU, zero fill it. + * Don't do it if the frame is cut at the MAXFL or padded with 4 or + * more bytes to the MINFL. + */ + cpu_physical_memory_write(desc->buf_ptr + copy_size, zero, fcsl); + copy_size += fcsl; + SET_FIELD(desc->len_flags, RXD_LEN, copy_size); if ((desc->len_flags & RXD_WRAP) || s->rx_desc == 0x7f) { diff --git a/hw/qxl-render.c b/hw/qxl-render.c index c290739de0..2c51ba9806 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -28,16 +28,16 @@ static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect) int len, i; src += (qxl->guest_primary.surface.height - rect->top - 1) * - qxl->guest_primary.stride; - dst += rect->top * qxl->guest_primary.stride; + qxl->guest_primary.abs_stride; + dst += rect->top * qxl->guest_primary.abs_stride; src += rect->left * qxl->guest_primary.bytes_pp; dst += rect->left * qxl->guest_primary.bytes_pp; len = (rect->right - rect->left) * qxl->guest_primary.bytes_pp; for (i = rect->top; i < rect->bottom; i++) { memcpy(dst, src, len); - dst += qxl->guest_primary.stride; - src -= qxl->guest_primary.stride; + dst += qxl->guest_primary.abs_stride; + src -= qxl->guest_primary.abs_stride; } } @@ -45,7 +45,8 @@ void qxl_render_resize(PCIQXLDevice *qxl) { QXLSurfaceCreate *sc = &qxl->guest_primary.surface; - qxl->guest_primary.stride = sc->stride; + qxl->guest_primary.qxl_stride = sc->stride; + qxl->guest_primary.abs_stride = abs(sc->stride); qxl->guest_primary.resized++; switch (sc->format) { case SPICE_SURFACE_FMT_16_555: @@ -75,7 +76,14 @@ void qxl_render_update(PCIQXLDevice *qxl) VGACommonState *vga = &qxl->vga; QXLRect dirty[32], update; void *ptr; - int i; + int i, redraw = 0; + + if (!is_buffer_shared(vga->ds->surface)) { + dprint(qxl, 1, "%s: restoring shared displaysurface\n", __func__); + qxl->guest_primary.resized++; + qxl->guest_primary.commands++; + redraw = 1; + } if (qxl->guest_primary.resized) { qxl->guest_primary.resized = 0; @@ -87,11 +95,11 @@ void qxl_render_update(PCIQXLDevice *qxl) qemu_free_displaysurface(vga->ds); qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram); - if (qxl->guest_primary.stride < 0) { + if (qxl->guest_primary.qxl_stride < 0) { /* spice surface is upside down -> need extra buffer to flip */ - qxl->guest_primary.stride = -qxl->guest_primary.stride; - qxl->guest_primary.flipped = g_malloc(qxl->guest_primary.surface.width * - qxl->guest_primary.stride); + qxl->guest_primary.flipped = + g_malloc(qxl->guest_primary.surface.width * + qxl->guest_primary.abs_stride); ptr = qxl->guest_primary.flipped; } else { ptr = qxl->guest_primary.data; @@ -100,7 +108,7 @@ void qxl_render_update(PCIQXLDevice *qxl) __FUNCTION__, qxl->guest_primary.surface.width, qxl->guest_primary.surface.height, - qxl->guest_primary.stride, + qxl->guest_primary.qxl_stride, qxl->guest_primary.bytes_pp, qxl->guest_primary.bits_pp, qxl->guest_primary.flipped ? "yes" : "no"); @@ -108,7 +116,7 @@ void qxl_render_update(PCIQXLDevice *qxl) qemu_create_displaysurface_from(qxl->guest_primary.surface.width, qxl->guest_primary.surface.height, qxl->guest_primary.bits_pp, - qxl->guest_primary.stride, + qxl->guest_primary.abs_stride, ptr); dpy_resize(vga->ds); } @@ -126,6 +134,10 @@ void qxl_render_update(PCIQXLDevice *qxl) memset(dirty, 0, sizeof(dirty)); qxl_spice_update_area(qxl, 0, &update, dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC); + if (redraw) { + memset(dirty, 0, sizeof(dirty)); + dirty[0] = update; + } for (i = 0; i < ARRAY_SIZE(dirty); i++) { if (qemu_spice_rect_is_empty(dirty+i)) { @@ -1663,12 +1663,25 @@ static int qxl_pre_load(void *opaque) return 0; } +static void qxl_create_memslots(PCIQXLDevice *d) +{ + int i; + + for (i = 0; i < NUM_MEMSLOTS; i++) { + if (!d->guest_slots[i].active) { + continue; + } + dprint(d, 1, "%s: restoring guest slot %d\n", __func__, i); + qxl_add_memslot(d, i, 0, QXL_SYNC); + } +} + static int qxl_post_load(void *opaque, int version) { PCIQXLDevice* d = opaque; uint8_t *ram_start = d->vga.vram_ptr; QXLCommandExt *cmds; - int in, out, i, newmode; + int in, out, newmode; dprint(d, 1, "%s: start\n", __FUNCTION__); @@ -1685,19 +1698,16 @@ static int qxl_post_load(void *opaque, int version) qxl_mode_to_string(d->mode)); newmode = d->mode; d->mode = QXL_MODE_UNDEFINED; + switch (newmode) { case QXL_MODE_UNDEFINED: break; case QXL_MODE_VGA: + qxl_create_memslots(d); qxl_enter_vga_mode(d); break; case QXL_MODE_NATIVE: - for (i = 0; i < NUM_MEMSLOTS; i++) { - if (!d->guest_slots[i].active) { - continue; - } - qxl_add_memslot(d, i, 0, QXL_SYNC); - } + qxl_create_memslots(d); qxl_create_guest_primary(d, 1, QXL_SYNC); /* replay surface-create and cursor-set commands */ @@ -1722,6 +1732,8 @@ static int qxl_post_load(void *opaque, int version) break; case QXL_MODE_COMPAT: + /* note: no need to call qxl_create_memslots, qxl_set_mode + * creates the mem slot. */ qxl_set_mode(d, d->shadow_rom.mode, 1); break; } @@ -48,7 +48,8 @@ typedef struct PCIQXLDevice { QXLSurfaceCreate surface; uint32_t commands; uint32_t resized; - int32_t stride; + int32_t qxl_stride; + uint32_t abs_stride; uint32_t bits_pp; uint32_t bytes_pp; uint8_t *data, *flipped; diff --git a/hw/sysbus.c b/hw/sysbus.c index 4fab5a41b2..fd2fc6a51d 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -198,6 +198,7 @@ DeviceState *sysbus_create_varargs(const char *name, sysbus_connect_irq(s, n, irq); n++; } + va_end(va); return dev; } @@ -229,6 +230,7 @@ DeviceState *sysbus_try_create_varargs(const char *name, sysbus_connect_irq(s, n, irq); n++; } + va_end(va); return dev; } diff --git a/ia64-dis.c b/ia64-dis.c index 2886df3614..2a103e6b5c 100644 --- a/ia64-dis.c +++ b/ia64-dis.c @@ -781,6 +781,9 @@ ext_inc3 (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep) return 0; } +/* glib.h defines ABS so we must undefine it to avoid a clash */ +#undef ABS + #define CST IA64_OPND_CLASS_CST #define REG IA64_OPND_CLASS_REG #define IND IA64_OPND_CLASS_IND diff --git a/migration-fd.c b/migration-fd.c index d0aec89e8d..6211124a05 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -42,10 +42,31 @@ static int fd_write(MigrationState *s, const void * buf, size_t size) static int fd_close(MigrationState *s) { + struct stat st; + int ret; + DPRINTF("fd_close\n"); if (s->fd != -1) { - close(s->fd); + ret = fstat(s->fd, &st); + if (ret == 0 && S_ISREG(st.st_mode)) { + /* + * If the file handle is a regular file make sure the + * data is flushed to disk before signaling success. + */ + ret = fsync(s->fd); + if (ret != 0) { + ret = -errno; + perror("migration-fd: fsync"); + return ret; + } + } + ret = close(s->fd); s->fd = -1; + if (ret != 0) { + ret = -errno; + perror("migration-fd: close"); + return ret; + } } return 0; } diff --git a/migration.c b/migration.c index 3b4abbde64..4b17566857 100644 --- a/migration.c +++ b/migration.c @@ -216,7 +216,7 @@ static void migrate_fd_put_notify(void *opaque) qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); qemu_file_put_notify(s->file); - if (qemu_file_get_error(s->file)) { + if (s->file && qemu_file_get_error(s->file)) { migrate_fd_error(s); } } diff --git a/net/tap-linux.c b/net/tap-linux.c index ff8cad0ea0..41d581b734 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -73,7 +73,11 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required pstrcpy(ifr.ifr_name, IFNAMSIZ, "tap%d"); ret = ioctl(fd, TUNSETIFF, (void *) &ifr); if (ret != 0) { - error_report("could not configure %s (%s): %m", PATH_NET_TUN, ifr.ifr_name); + if (ifname[0] != '\0') { + error_report("could not configure %s (%s): %m", PATH_NET_TUN, ifr.ifr_name); + } else { + error_report("could not configure %s: %m", PATH_NET_TUN); + } close(fd); return -1; } diff --git a/oslib-posix.c b/oslib-posix.c index dbc8ee8960..6f297626c7 100644 --- a/oslib-posix.c +++ b/oslib-posix.c @@ -36,8 +36,11 @@ extern int daemon(int, int); #endif #if defined(__linux__) && defined(__x86_64__) - /* Use 2MB alignment so transparent hugepages can be used by KVM */ + /* Use 2 MiB alignment so transparent hugepages can be used by KVM. + Valgrind does not support alignments larger than 1 MiB, + therefore we need special code which handles running on Valgrind. */ # define QEMU_VMALLOC_ALIGN (512 * 4096) +# define CONFIG_VALGRIND #else # define QEMU_VMALLOC_ALIGN getpagesize() #endif @@ -47,7 +50,11 @@ extern int daemon(int, int); #include "trace.h" #include "qemu_socket.h" - +#if defined(CONFIG_VALGRIND) +static int running_on_valgrind = -1; +#else +# define running_on_valgrind 0 +#endif int qemu_daemon(int nochdir, int noclose) { @@ -89,7 +96,16 @@ void *qemu_vmalloc(size_t size) void *ptr; size_t align = QEMU_VMALLOC_ALIGN; - if (size < align) { +#if defined(CONFIG_VALGRIND) + if (running_on_valgrind < 0) { + /* First call, test whether we are running on Valgrind. + This is a substitute for RUNNING_ON_VALGRIND from valgrind.h. */ + const char *ld = getenv("LD_PRELOAD"); + running_on_valgrind = (ld != NULL && strstr(ld, "vgpreload")); + } +#endif + + if (size < align || running_on_valgrind) { align = getpagesize(); } ptr = qemu_memalign(align, size); diff --git a/qemu-barrier.h b/qemu-barrier.h index 735eea6cf9..c11bb2b59f 100644 --- a/qemu-barrier.h +++ b/qemu-barrier.h @@ -14,7 +14,7 @@ */ #define smp_wmb() barrier() -#elif defined(__powerpc__) +#elif defined(_ARCH_PPC) /* * We use an eieio() for a wmb() on powerpc. This assumes we don't diff --git a/qemu-tls.h b/qemu-tls.h new file mode 100644 index 0000000000..5b70f10f8f --- /dev/null +++ b/qemu-tls.h @@ -0,0 +1,52 @@ +/* + * Abstraction layer for defining and using TLS variables + * + * Copyright (c) 2011 Red Hat, Inc + * Copyright (c) 2011 Linaro Limited + * + * Authors: + * Paolo Bonzini <pbonzini@redhat.com> + * Peter Maydell <peter.maydell@linaro.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QEMU_TLS_H +#define QEMU_TLS_H + +/* Per-thread variables. Note that we only have implementations + * which are really thread-local on Linux; the dummy implementations + * define plain global variables. + * + * This means that for the moment use should be restricted to + * per-VCPU variables, which are OK because: + * - the only -user mode supporting multiple VCPU threads is linux-user + * - TCG system mode is single-threaded regarding VCPUs + * - KVM system mode is multi-threaded but limited to Linux + * + * TODO: proper implementations via Win32 .tls sections and + * POSIX pthread_getspecific. + */ +#ifdef __linux__ +#define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x) +#define DEFINE_TLS(type, x) __thread __typeof__(type) tls__##x +#define get_tls(x) tls__##x +#else +/* Dummy implementations which define plain global variables */ +#define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x) +#define DEFINE_TLS(type, x) __typeof__(type) tls__##x +#define get_tls(x) tls__##x +#endif + +#endif |