diff --git a/MAINTAINERS b/MAINTAINERS index ccee28b12d..45a45935ea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -970,6 +970,7 @@ M: Paolo Bonzini S: Supported F: include/hw/scsi/* F: hw/scsi/* +F: tests/scsi-disk-test.c F: tests/virtio-scsi-test.c T: git git://github.com/bonzini/qemu.git scsi-next @@ -1439,6 +1440,7 @@ F: qom/ X: qom/cpu.c F: tests/check-qom-interface.c F: tests/check-qom-proplist.c +F: tests/check-qom-props.c F: tests/qom-test.c QMP diff --git a/Makefile.target b/Makefile.target index 7f42c45db8..b5a3574059 100644 --- a/Makefile.target +++ b/Makefile.target @@ -36,6 +36,10 @@ endif PROGS=$(QEMU_PROG) $(QEMU_PROGW) STPFILES= +ifdef CONFIG_LINUX_USER +PROGS+=$(QEMU_PROG)-binfmt +endif + config-target.h: config-target.h-timestamp config-target.h-timestamp: config-target.mak @@ -121,6 +125,8 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) \ obj-y += linux-user/ obj-y += gdbstub.o thunk.o user-exec.o user-exec-stub.o +obj-binfmt-y += linux-user/ + endif #CONFIG_LINUX_USER ######################################################### @@ -162,7 +168,11 @@ endif # CONFIG_SOFTMMU # Workaround for http://gcc.gnu.org/PR55489, see configure. %/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS) +ifdef CONFIG_LINUX_USER +dummy := $(call unnest-vars,,obj-y obj-binfmt-y) +else dummy := $(call unnest-vars,,obj-y) +endif all-obj-y := $(obj-y) target-obj-y := @@ -203,6 +213,9 @@ ifdef CONFIG_DARWIN $(call quiet-command,SetFile -a C $@,"SETFILE","$(TARGET_DIR)$@") endif +$(QEMU_PROG)-binfmt: $(obj-binfmt-y) + $(call LINK,$^) + gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES),"GEN","$(TARGET_DIR)$@") diff --git a/chardev/baum.c b/chardev/baum.c index 302dd9666c..67fd783a59 100644 --- a/chardev/baum.c +++ b/chardev/baum.c @@ -643,6 +643,7 @@ static void baum_chr_open(Chardev *chr, error_setg(errp, "brlapi__openConnection: %s", brlapi_strerror(brlapi_error_location())); g_free(handle); + baum->brlapi = NULL; return; } baum->deferred_init = 0; diff --git a/chardev/char-fe.c b/chardev/char-fe.c index f3af6ae584..9683926048 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#define HW_POISON_H // avoid poison since we patch against rules it "enforces" #include "qemu/osdep.h" #include "qemu/error-report.h" #include "qapi/error.h" diff --git a/chardev/char-mux.c b/chardev/char-mux.c index 4cda5e7458..a6dc05c624 100644 --- a/chardev/char-mux.c +++ b/chardev/char-mux.c @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#define HW_POISON_H // avoid poison since we patch against rules it "enforces" #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" @@ -179,6 +180,15 @@ static void mux_chr_accept_input(Chardev *chr) be->chr_read(be->opaque, &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1); } + +#if defined(TARGET_S390X) + /* We're still not able to sync producer and consumer, so let's wait a bit + and try again by then. */ + if (d->prod[m] != d->cons[m]) { + qemu_mod_timer(d->accept_timer, qemu_get_clock_ns(vm_clock) + + (int64_t)100000); + } +#endif } static int mux_chr_can_read(void *opaque) @@ -314,6 +324,10 @@ static void qemu_chr_open_mux(Chardev *chr, } d->focus = -1; +#if defined(TARGET_S390X) + d->accept_timer = qemu_new_timer_ns(vm_clock, + (QEMUTimerCB*)mux_chr_accept_input, chr); +#endif /* only default to opened state if we've realized the initial * set of muxes */ diff --git a/chardev/char.c b/chardev/char.c index 5d283b90d3..d74fd7aeb9 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#define HW_POISON_H // avoid poison since we patch against rules it "enforces" #include "qemu/osdep.h" #include "qemu/cutils.h" #include "monitor/monitor.h" diff --git a/configure b/configure index dd73cce62f..f2b265681e 100755 --- a/configure +++ b/configure @@ -2040,6 +2040,9 @@ if test "$seccomp" != "no" ; then ppc|ppc64) libseccomp_minver="2.3.0" ;; + s390|s390x) + libseccomp_minver="2.2.0" + ;; *) libseccomp_minver="" ;; diff --git a/exec.c b/exec.c index d20c34ca83..b54fbb02c8 100644 --- a/exec.c +++ b/exec.c @@ -1950,11 +1950,13 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr, return NULL; } +#ifndef TARGET_PPC if (kvm_enabled() && !kvm_has_sync_mmu()) { error_setg(errp, "host lacks kvm mmu notifiers, -mem-path unsupported"); return NULL; } +#endif if (phys_mem_alloc != qemu_anon_ram_alloc) { /* diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index f276967365..85557a7fab 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -311,7 +311,7 @@ static const VMStateDescription vmstate_cpuhp_state = { static const VMStateDescription vmstate_acpi = { .name = "piix4_pm", .version_id = 3, - .minimum_version_id = 3, + .minimum_version_id = 2, /* qemu-kvm */ .minimum_version_id_old = 1, .load_state_old = acpi_load_old, .post_load = vmstate_acpi_post_load, diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c index d42ed7070d..0dc524903e 100644 --- a/hw/block/xen_disk.c +++ b/hw/block/xen_disk.c @@ -113,6 +113,7 @@ struct XenBlkDev { int requests_finished; unsigned int max_requests; + gboolean cache_unsafe; /* Persistent grants extension */ gboolean feature_discard; gboolean feature_persistent; @@ -947,6 +948,16 @@ static void blk_parse_discard(struct XenBlkDev *blkdev) } } +static void blk_parse_cache_unsafe(struct XenBlkDev *blkdev) +{ + int enable; + + blkdev->cache_unsafe = false; + + if (xenstore_read_be_int(&blkdev->xendev, "suse-diskcache-disable-flush", &enable) == 0) + blkdev->cache_unsafe = !!enable; +} + static int blk_init(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); @@ -1028,6 +1039,7 @@ static int blk_init(struct XenDevice *xendev) MAX_RING_PAGE_ORDER); blk_parse_discard(blkdev); + blk_parse_cache_unsafe(blkdev); g_free(directiosafe); return 0; @@ -1083,6 +1095,9 @@ static int blk_connect(struct XenDevice *xendev) qflags |= BDRV_O_UNMAP; } + if (blkdev->cache_unsafe) + qflags |= BDRV_O_NO_FLUSH; + /* init qemu block driver */ index = (blkdev->xendev.dev - 202 * 256) / 16; blkdev->dinfo = drive_get(IF_XEN, 0, index); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 46dfd2c954..e4ac76c905 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -789,7 +789,32 @@ DEFINE_I440FX_MACHINE(v1_0, "pc-1.0", pc_compat_1_2, #define PC_COMPAT_0_15 \ - PC_CPU_MODEL_IDS("0.15") + PC_CPU_MODEL_IDS("0.15")\ + {\ + .driver = "VGA",\ + .property = "vgamem_mb",\ + .value = stringify(16),\ + },{\ + .driver = "vmware-svga",\ + .property = "vgamem_mb",\ + .value = stringify(16),\ + },{\ + .driver = "qxl-vga",\ + .property = "vgamem_mb",\ + .value = stringify(16),\ + },{\ + .driver = "qxl",\ + .property = "vgamem_mb",\ + .value = stringify(16),\ + },{\ + .driver = "isa-cirrus-vga",\ + .property = "vgamem_mb",\ + .value = stringify(16),\ + },{\ + .driver = "cirrus-vga",\ + .property = "vgamem_mb",\ + .value = stringify(16),\ + }, static void pc_i440fx_0_15_machine_options(MachineClass *m) { diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c index 976d5200f1..f1d9b3cbe9 100644 --- a/hw/timer/i8254_common.c +++ b/hw/timer/i8254_common.c @@ -258,6 +258,12 @@ static int pit_dispatch_post_load(void *opaque, int version_id) return 0; } +static bool is_qemu_kvm(void *opaque, int version_id) +{ + /* HACK: We ignore incoming migration from upstream qemu */ + return version_id < 3; +} + static const VMStateDescription vmstate_pit_common = { .name = "i8254", .version_id = 3, @@ -267,6 +273,7 @@ static const VMStateDescription vmstate_pit_common = { .pre_save = pit_dispatch_pre_save, .post_load = pit_dispatch_post_load, .fields = (VMStateField[]) { + VMSTATE_UNUSED_TEST(is_qemu_kvm, 4), VMSTATE_UINT32_V(channels[0].irq_disabled, PITCommonState, 3), VMSTATE_STRUCT_ARRAY(channels, PITCommonState, 3, 2, vmstate_pit_channel, PITChannelState), diff --git a/include/chardev/char-mux.h b/include/chardev/char-mux.h index 8928977897..ee9bfe7205 100644 --- a/include/chardev/char-mux.h +++ b/include/chardev/char-mux.h @@ -36,6 +36,9 @@ typedef struct MuxChardev { Chardev parent; CharBackend *backends[MAX_MUX]; CharBackend chr; +#if defined(TARGET_S390X) + QEMUTimer *accept_timer; +#endif int focus; int mux_cnt; int term_got_escape; diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs index 8c93058100..607ca2dc92 100644 --- a/linux-user/Makefile.objs +++ b/linux-user/Makefile.objs @@ -6,3 +6,5 @@ obj-$(TARGET_HAS_BFLT) += flatload.o obj-$(TARGET_I386) += vm86.o obj-$(TARGET_ARM) += arm/nwfpe/ obj-$(TARGET_M68K) += m68k-sim.o + +obj-binfmt-y = binfmt.o diff --git a/linux-user/binfmt.c b/linux-user/binfmt.c new file mode 100644 index 0000000000..458f136fb4 --- /dev/null +++ b/linux-user/binfmt.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include + +#ifdef __x86_64__ +#define ARCH_NAME "x86_64" +#endif + +int main(int argc, char **argv, char **envp) +{ + char *binfmt; + char **new_argv; + + /* + * Check if our file name ends with -binfmt + */ + binfmt = argv[0] + strlen(argv[0]) - strlen("-binfmt"); + if (strcmp(binfmt, "-binfmt")) { + fprintf(stderr, "%s: Invalid executable name\n", argv[0]); + exit(1); + } + if (argc < 3) { + fprintf(stderr, "%s: Please use me through binfmt with P flag\n", + argv[0]); + exit(1); + } + + binfmt[0] = '\0'; + /* Now argv[0] is the real qemu binary name */ + +#ifdef ARCH_NAME + { + char *hostbin; + char *guestarch; + int r; + + guestarch = strrchr(argv[0], '-') ; + if (!guestarch) { + goto skip; + } + guestarch++; + r = asprintf(&hostbin, "/emul/" ARCH_NAME "-for-%s/%s", guestarch, argv[1]); + if ((r > 0) && !access(hostbin, X_OK)) { + /* + * We found a host binary replacement for the non-host binary. Let's + * use that instead! + */ + return execve(hostbin, &argv[2], envp); + } + } +skip: +#endif + + new_argv = (char **)malloc((argc + 2) * sizeof(*new_argv)); + if (argc > 3) { + memcpy(&new_argv[4], &argv[3], (argc - 3) * sizeof(*new_argv)); + } + new_argv[0] = argv[0]; + new_argv[1] = (char *)"-0"; + new_argv[2] = argv[2]; + new_argv[3] = argv[1]; + new_argv[argc + 1] = NULL; + + return execve(new_argv[0], new_argv, envp); +} diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 4edd7d0c08..25208645e9 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -196,10 +196,10 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src, void target_set_brk(abi_ulong new_brk); abi_long do_brk(abi_ulong new_brk); void syscall_init(void); -abi_long do_syscall(void *cpu_env, int num, abi_long arg1, - abi_long arg2, abi_long arg3, abi_long arg4, - abi_long arg5, abi_long arg6, abi_long arg7, - abi_long arg8); +abi_long do_syscall(void *cpu_env, int num, abi_ulong arg1, + abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, + abi_ulong arg5, abi_ulong arg6, abi_ulong arg7, + abi_ulong arg8); void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2); extern THREAD CPUState *thread_cpu; void cpu_loop(CPUArchState *env); diff --git a/linux-user/signal.c b/linux-user/signal.c index cc0c3fcee9..47f1a89860 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -560,6 +560,10 @@ static void QEMU_NORETURN dump_core_and_abort(int target_sig) trace_user_force_sig(env, target_sig, host_sig); gdb_signalled(env, target_sig); + if (target_sig == 6) { + goto no_core; + } + /* dump core if supported by target binary format */ if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) { stop_all_tasks(); @@ -577,6 +581,8 @@ static void QEMU_NORETURN dump_core_and_abort(int target_sig) target_sig, strsignal(host_sig), "core dumped" ); } +no_core: + /* The proper exit code for dying from an uncaught signal is * -. The kernel doesn't allow exit() or _exit() to pass * a negative value. To get the proper exit code we need to diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 9b6364a266..25b0a2ce69 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5080,6 +5080,11 @@ static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp, uint32_t outbufsz; int free_fm = 0; + if (1) { + /* XXX agraf: fiemap breaks for me */ + return -TARGET_EINVAL; + } + assert(arg_type[0] == TYPE_PTR); assert(ie->access == IOC_RW); arg_type++; @@ -5615,7 +5620,12 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg) ie = ioctl_entries; for(;;) { if (ie->target_cmd == 0) { - gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd); + int i; + gemu_log("Unsupported ioctl: cmd=0x%04lx (%x)\n", (unsigned long)cmd, (unsigned int)(cmd & (TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) >> TARGET_IOC_SIZESHIFT); + for (i = 0; ioctl_entries[i].target_cmd; i++) { + if ((ioctl_entries[i].target_cmd & ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) == (cmd & ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT))) + gemu_log("%p\t->\t%s (%x)\n", (void *)(unsigned long)ioctl_entries[i].host_cmd, ioctl_entries[i].name, (ioctl_entries[i].target_cmd & (TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) >> TARGET_IOC_SIZESHIFT); + } return -TARGET_ENOSYS; } if (ie->target_cmd == cmd) @@ -5647,6 +5657,11 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg) arg_type++; target_size = thunk_type_size(arg_type, 0); switch(ie->access) { + /* FIXME: actually the direction given in the ioctl should be + * correct so we can assume the communication is uni-directional. + * The alsa developers did not like this concept though and + * declared ioctls IOC_R and IOC_W even though they were IOC_RW.*/ +/* case IOC_R: ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp)); if (!is_error(ret)) { @@ -5665,6 +5680,7 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg) unlock_user(argptr, arg, 0); ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp)); break; +*/ default: case IOC_RW: argptr = lock_user(VERIFY_READ, arg, target_size, 1); @@ -7461,6 +7477,25 @@ static int open_self_stat(void *cpu_env, int fd) return 0; } +static int open_cpuinfo(void *cpu_env, int fd) +{ + dprintf(fd, +"Processor : ARMv7 Processor rev 5 (v7l)\n" +"BogoMIPS : 799.53\n" +"Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3\n" +"CPU implementer : 0x41\n" +"CPU architecture: 7\n" +"CPU variant : 0x2\n" +"CPU part : 0xc08\n" +"CPU revision : 5\n" +"\n" +"Hardware : Genesi Efika MX (Smarttop)\n" +"Revision : 51030\n" +"Serial : 0000000000000000\n"); + + return 0; +} + static int open_self_auxv(void *cpu_env, int fd) { CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); @@ -7575,6 +7610,7 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) { "/proc/net/route", open_net_route, is_proc }, #endif + { "cpuinfo", open_cpuinfo, is_proc_myself }, { NULL, NULL, NULL } }; @@ -7692,10 +7728,10 @@ static TargetFdTrans target_inotify_trans = { /* do_syscall() should always have a single exit point at the end so that actions, such as logging of syscall results, can be performed. All errnos that do_syscall() returns must be -TARGET_. */ -abi_long do_syscall(void *cpu_env, int num, abi_long arg1, - abi_long arg2, abi_long arg3, abi_long arg4, - abi_long arg5, abi_long arg6, abi_long arg7, - abi_long arg8) +abi_long do_syscall(void *cpu_env, int num, abi_ulong arg1, + abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, + abi_ulong arg5, abi_ulong arg6, abi_ulong arg7, + abi_ulong arg8) { CPUState *cpu = ENV_GET_CPU(cpu_env); abi_long ret; @@ -8071,9 +8107,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_oldstat: goto unimplemented; #endif - case TARGET_NR_lseek: - ret = get_errno(lseek(arg1, arg2, arg3)); + case TARGET_NR_lseek: { + off_t off = arg2; + if (arg3 != SEEK_SET) { + off = (abi_long)arg2; + } + ret = get_errno(lseek(arg1, off, arg3)); break; + } #if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA) /* Alpha specific */ case TARGET_NR_getxpid: @@ -8950,6 +8991,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_gettimeofday: { struct timeval tv; + if(copy_from_user_timeval(&tv, arg1)) + goto efault; ret = get_errno(gettimeofday(&tv, NULL)); if (!is_error(ret)) { if (copy_to_user_timeval(arg1, &tv)) @@ -10197,7 +10240,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { struct timespec ts, *pts; - if (arg3 >= 0) { + if ((abi_long)arg3 >= 0) { /* Convert ms to secs, ns */ ts.tv_sec = arg3 / 1000; ts.tv_nsec = (arg3 % 1000) * 1000000LL; diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h index f5b4549ea3..55eaeee4b6 100644 --- a/pc-bios/s390-ccw/cio.h +++ b/pc-bios/s390-ccw/cio.h @@ -133,7 +133,7 @@ struct ccw1 { __u8 flags; __u16 count; __u32 cda; -} __attribute__ ((packed)); +} __attribute__ ((packed, aligned(8))); #define CCW_FLAG_DC 0x80 #define CCW_FLAG_CC 0x40 diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c index 67a0a4a58b..1c73e5aeae 100644 --- a/qapi/string-input-visitor.c +++ b/qapi/string-input-visitor.c @@ -43,7 +43,8 @@ static void free_range(void *range, void *dummy) g_free(range); } -static int parse_str(StringInputVisitor *siv, const char *name, Error **errp) +static int parse_str(StringInputVisitor *siv, const char *name, bool u64, + Error **errp) { char *str = (char *) siv->string; long long start, end; @@ -60,7 +61,11 @@ static int parse_str(StringInputVisitor *siv, const char *name, Error **errp) do { errno = 0; - start = strtoll(str, &endptr, 0); + if (u64) { + start = strtoull(str, &endptr, 0); + } else { + start = strtoll(str, &endptr, 0); + } if (errno == 0 && endptr > str) { if (*endptr == '\0') { cur = g_malloc0(sizeof(*cur)); @@ -71,7 +76,11 @@ static int parse_str(StringInputVisitor *siv, const char *name, Error **errp) } else if (*endptr == '-') { str = endptr + 1; errno = 0; - end = strtoll(str, &endptr, 0); + if (u64) { + end = strtoull(str, &endptr, 0); + } else { + end = strtoll(str, &endptr, 0); + } if (errno == 0 && endptr > str && start <= end && (start > INT64_MAX - 65536 || end < start + 65536)) { @@ -127,7 +136,7 @@ start_list(Visitor *v, const char *name, GenericList **list, size_t size, assert(list); siv->list = list; - if (parse_str(siv, name, errp) < 0) { + if (parse_str(siv, name, false, errp) < 0) { *list = NULL; return; } @@ -215,7 +224,7 @@ static void parse_type_int64(Visitor *v, const char *name, int64_t *obj, { StringInputVisitor *siv = to_siv(v); - if (parse_str(siv, name, errp) < 0) { + if (parse_str(siv, name, false, errp) < 0) { return; } @@ -251,15 +260,43 @@ error: static void parse_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) { - /* FIXME: parse_type_int64 mishandles values over INT64_MAX */ - int64_t i; - Error *err = NULL; - parse_type_int64(v, name, &i, &err); - if (err) { - error_propagate(errp, err); - } else { - *obj = i; + StringInputVisitor *siv = to_siv(v); + + if (!siv->string) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "integer"); + return; } + + parse_str(siv, name, true, errp); + + if (!siv->ranges) { + goto error; + } + + if (!siv->cur_range) { + Range *r; + + siv->cur_range = g_list_first(siv->ranges); + if (!siv->cur_range) { + goto error; + } + + r = siv->cur_range->data; + if (!r) { + goto error; + } + + siv->cur = range_lob(r); + } + + *obj = siv->cur; + siv->cur++; + return; + +error: + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, + "a uint64 value or range"); } static void parse_type_size(Visitor *v, const char *name, uint64_t *obj, diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c index 5396fbfbb6..f3710b80a3 100644 --- a/qemu-bridge-helper.c +++ b/qemu-bridge-helper.c @@ -110,7 +110,12 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) *argend = 0; if (strcmp(cmd, "deny") == 0) { - acl_rule = g_malloc(sizeof(*acl_rule)); + acl_rule = calloc(1, sizeof(*acl_rule)); + if (!acl_rule) { + fclose(f); + errno = ENOMEM; + return -1; + } if (strcmp(arg, "all") == 0) { acl_rule->type = ACL_DENY_ALL; } else { @@ -119,7 +124,12 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) } QSIMPLEQ_INSERT_TAIL(acl_list, acl_rule, entry); } else if (strcmp(cmd, "allow") == 0) { - acl_rule = g_malloc(sizeof(*acl_rule)); + acl_rule = calloc(1, sizeof(*acl_rule)); + if (!acl_rule) { + fclose(f); + errno = ENOMEM; + return -1; + } if (strcmp(arg, "all") == 0) { acl_rule->type = ACL_ALLOW_ALL; } else { @@ -413,6 +423,17 @@ int main(int argc, char **argv) goto cleanup; } +#ifndef CONFIG_LIBCAP + /* avoid sending the fd as root user if running suid to not fool + * peer credentials to daemons that dont expect that + */ + if (setuid(getuid()) < 0) { + fprintf(stderr, "Failed to drop privileges.\n"); + ret = EXIT_FAILURE; + goto cleanup; + } +#endif + /* write fd to the domain socket */ if (send_fd(unixfd, fd) == -1) { fprintf(stderr, "failed to write fd to unix socket: %s\n", @@ -434,7 +455,7 @@ cleanup: } while ((acl_rule = QSIMPLEQ_FIRST(&acl_list)) != NULL) { QSIMPLEQ_REMOVE_HEAD(&acl_list, entry); - g_free(acl_rule); + free(acl_rule); } return ret; diff --git a/roms/Makefile b/roms/Makefile index b5e5a69e91..89d69eb350 100644 --- a/roms/Makefile +++ b/roms/Makefile @@ -52,6 +52,12 @@ SEABIOS_EXTRAVERSION="-prebuilt.qemu-project.org" # EFIROM ?= $(shell which EfiRom 2>/dev/null) +# NB: Certain SUSE qemu subpackages use date information, but we want +# reproducible builds, so we use a pre-determined timestamp, rather +# than the current timestamp to acheive consistent results build to +# build. +PACKAGING_TIMESTAMP = $(shell date -r ../VERSION +%s) + default: @echo "nothing is build by default" @echo "available build targets:" @@ -106,7 +112,7 @@ build-lgplvgabios: .PHONY: sgabios skiboot sgabios: - $(MAKE) -C sgabios + $(MAKE) -C sgabios PACKAGING_TIMESTAMP=$(PACKAGING_TIMESTAMP) cp sgabios/sgabios.bin ../pc-bios @@ -126,18 +132,22 @@ efi-rom-%: build-pxe-roms build-efi-roms build-pxe-roms: $(MAKE) -C ipxe/src CONFIG=qemu \ + PACKAGING_TIMESTAMP=$(PACKAGING_TIMESTAMP) \ CROSS_COMPILE=$(x86_64_cross_prefix) \ $(patsubst %,bin/%.rom,$(pxerom_targets)) build-efi-roms: build-pxe-roms $(MAKE) -C ipxe/src CONFIG=qemu \ + PACKAGING_TIMESTAMP=$(PACKAGING_TIMESTAMP) \ CROSS_COMPILE=$(x86_64_cross_prefix) \ $(patsubst %,bin-i386-efi/%.efidrv,$(pxerom_targets)) \ $(patsubst %,bin-x86_64-efi/%.efidrv,$(pxerom_targets)) slof: - $(MAKE) -C SLOF CROSS=$(powerpc64_cross_prefix) qemu + $(MAKE) -C SLOF CROSS=$(powerpc64_cross_prefix) \ + PACKAGING_TIMESTAMP=$(PACKAGING_TIMESTAMP) \ + qemu cp SLOF/boot_rom.bin ../pc-bios/slof.bin u-boot.e500: diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh index 8afc3eb5bb..bb29213fa5 100755 --- a/scripts/qemu-binfmt-conf.sh +++ b/scripts/qemu-binfmt-conf.sh @@ -206,7 +206,7 @@ qemu_check_systemd() { } qemu_generate_register() { - echo ":qemu-$cpu:M::$magic:$mask:$qemu:$FLAGS" + echo ":qemu-$cpu:M::$magic:$mask:$qemu:P$FLAGS" } qemu_register_interpreter() { @@ -247,9 +247,9 @@ qemu_set_binfmts() { continue fi - qemu="$QEMU_PATH/qemu-$cpu" + qemu="$QEMU_PATH/qemu-$cpu-binfmt" if [ "$cpu" = "i486" ] ; then - qemu="$QEMU_PATH/qemu-i386" + qemu="$QEMU_PATH/qemu-i386-binfmt" fi if [ "$host_family" != "$family" ] ; then @@ -264,7 +264,7 @@ BINFMT_SET=qemu_register_interpreter SYSTEMDDIR="/etc/binfmt.d" DEBIANDIR="/usr/share/binfmts" -QEMU_PATH=/usr/local/bin +QEMU_PATH=/usr/bin FLAGS="" options=$(getopt -o ds:Q:e:hc: -l debian,systemd:,qemu-path:,exportdir:,help,credential: -- "$@") diff --git a/slirp/socket.c b/slirp/socket.c index ecec0295a9..cb7b5b608d 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -59,6 +59,27 @@ socreate(Slirp *slirp) return(so); } +/* + * Remove references to so from the given message queue. + */ +static void +soqfree(struct socket *so, struct quehead *qh) +{ + struct mbuf *ifq; + + for (ifq = (struct mbuf *) qh->qh_link; + (struct quehead *) ifq != qh; + ifq = ifq->ifq_next) { + if (ifq->ifq_so == so) { + struct mbuf *ifm; + ifq->ifq_so = NULL; + for (ifm = ifq->ifs_next; ifm != ifq; ifm = ifm->ifs_next) { + ifm->ifq_so = NULL; + } + } + } +} + /* * remque and free a socket, clobber cache */ @@ -66,23 +87,9 @@ void sofree(struct socket *so) { Slirp *slirp = so->slirp; - struct mbuf *ifm; - for (ifm = (struct mbuf *) slirp->if_fastq.qh_link; - (struct quehead *) ifm != &slirp->if_fastq; - ifm = ifm->ifq_next) { - if (ifm->ifq_so == so) { - ifm->ifq_so = NULL; - } - } - - for (ifm = (struct mbuf *) slirp->if_batchq.qh_link; - (struct quehead *) ifm != &slirp->if_batchq; - ifm = ifm->ifq_next) { - if (ifm->ifq_so == so) { - ifm->ifq_so = NULL; - } - } + soqfree(so, &slirp->if_fastq); + soqfree(so, &slirp->if_batchq); if (so->so_emu==EMU_RSH && so->extra) { sofree(so->extra); diff --git a/target/i386/cpu.c b/target/i386/cpu.c index ddc45abd70..6617e01a72 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1522,6 +1522,50 @@ static X86CPUDefinition builtin_x86_defs[] = { .xlevel = 0x8000001A, .model_id = "AMD Opteron 63xx class CPU", }, + { + .name = "EPYC", + .level = 0xd, + .vendor = CPUID_VENDOR_AMD, + .family = 23, + .model = 1, + .stepping = 2, + .features[FEAT_1_EDX] = + CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | CPUID_CLFLUSH | + CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | CPUID_PGE | + CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | CPUID_MCE | + CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | CPUID_DE | + CPUID_VME | CPUID_FP87, + .features[FEAT_1_ECX] = + CPUID_EXT_RDRAND | CPUID_EXT_F16C | CPUID_EXT_AVX | + CPUID_EXT_XSAVE | CPUID_EXT_AES | CPUID_EXT_POPCNT | + CPUID_EXT_MOVBE | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_FMA | CPUID_EXT_SSSE3 | + CPUID_EXT_MONITOR | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3, + .features[FEAT_8000_0001_EDX] = + CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_PDPE1GB | + CPUID_EXT2_FFXSR | CPUID_EXT2_MMXEXT | CPUID_EXT2_NX | + CPUID_EXT2_SYSCALL, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_OSVW | CPUID_EXT3_3DNOWPREFETCH | + CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | + CPUID_EXT3_CR8LEG | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, + .features[FEAT_7_0_EBX] = + CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 | + CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_RDSEED | + CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT | + CPUID_7_0_EBX_SHA_NI, + /* Missing: XSAVES (not supported by some Linux versions, + * including v4.1 to v4.12). + * KVM doesn't yet expose any XSAVES state save component. + */ + .features[FEAT_XSAVE] = + CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, + .xlevel = 0x8000000A, + .model_id = "AMD EPYC Processor", + }, }; typedef struct PropValue { diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 051867399b..fdbaf372a9 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1500,7 +1500,7 @@ uint64_t cpu_get_tsc(CPUX86State *env); /* XXX: This value should match the one returned by CPUID * and in exec.c */ # if defined(TARGET_X86_64) -# define TCG_PHYS_ADDR_BITS 40 +# define TCG_PHYS_ADDR_BITS 42 # else # define TCG_PHYS_ADDR_BITS 36 # endif diff --git a/tests/Makefile.include b/tests/Makefile.include index 37c1bed683..27d4ce8bc3 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -113,6 +113,8 @@ check-unit-y += tests/check-qom-interface$(EXESUF) gcov-files-check-qom-interface-y = qom/object.c check-unit-y += tests/check-qom-proplist$(EXESUF) gcov-files-check-qom-proplist-y = qom/object.c +check-unit-y += tests/check-qom-props$(EXESUF) +gcov-files-check-qom-props-y = qom/object.c check-unit-y += tests/test-qemu-opts$(EXESUF) gcov-files-test-qemu-opts-y = util/qemu-option.c check-unit-y += tests/test-keyval$(EXESUF) @@ -183,6 +185,8 @@ check-qtest-virtio-y += tests/virtio-rng-test$(EXESUF) gcov-files-virtio-y += hw/virtio/virtio-rng.c check-qtest-virtio-y += tests/virtio-scsi-test$(EXESUF) gcov-files-virtio-y += i386-softmmu/hw/scsi/virtio-scsi.c +check-qtest-virtio-y += tests/scsi-disk-test$(EXESUF) +gcov-files-virtio-y += i386-softmmu/hw/scsi/scsi-disk.c ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy) check-qtest-virtio-y += tests/virtio-9p-test$(EXESUF) gcov-files-virtio-y += hw/9pfs/virtio-9p.c @@ -571,6 +575,7 @@ tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y) tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y) tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y) tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y) +tests/check-qom-props$(EXESUF): tests/check-qom-props.o $(test-qom-obj-y) tests/test-char$(EXESUF): tests/test-char.o $(test-util-obj-y) $(qtest-obj-y) $(test-io-obj-y) $(chardev-obj-y) tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y) @@ -776,6 +781,7 @@ tests/postcopy-test$(EXESUF): tests/postcopy-test.o tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o $(test-util-obj-y) \ $(qtest-obj-y) $(test-io-obj-y) $(libqos-virtio-obj-y) $(libqos-pc-obj-y) \ $(chardev-obj-y) +tests/scsi-disk-test$(EXESUF): tests/scsi-disk-test.o tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y) tests/test-keyval$(EXESUF): tests/test-keyval.o $(test-util-obj-y) $(test-qapi-obj-y) diff --git a/tests/check-qom-props.c b/tests/check-qom-props.c new file mode 100644 index 0000000000..681e121c07 --- /dev/null +++ b/tests/check-qom-props.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * Copyright (c) 2015 SUSE Linux GmbH + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Author: Daniel P. Berrange + * Andreas Färber + */ + +#include "qemu/osdep.h" + +#include + +#include "qapi/visitor.h" +#include "qom/object.h" +#include "qemu/module.h" + + +#define TYPE_DUMMY "qemu-dummy" + +typedef struct DummyObject DummyObject; +typedef struct DummyObjectClass DummyObjectClass; + +#define DUMMY_OBJECT(obj) \ + OBJECT_CHECK(DummyObject, (obj), TYPE_DUMMY) + +struct DummyObject { + Object parent_obj; + + uint64_t u64val; +}; + +struct DummyObjectClass { + ObjectClass parent_class; +}; + +static void dummy_set_uint64(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + uint64_t *ptr = (uint64_t *)opaque; + + visit_type_uint64(v, name, ptr, errp); +} + +static void dummy_get_uint64(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + uint64_t value = *(uint64_t *)opaque; + + visit_type_uint64(v, name, &value, errp); +} + +static void dummy_init(Object *obj) +{ + DummyObject *dobj = DUMMY_OBJECT(obj); + + object_property_add(obj, "u64val", "uint64", + dummy_get_uint64, + dummy_set_uint64, + NULL, &dobj->u64val, NULL); +} + + +static const TypeInfo dummy_info = { + .name = TYPE_DUMMY, + .parent = TYPE_OBJECT, + .instance_size = sizeof(DummyObject), + .instance_init = dummy_init, + .class_size = sizeof(DummyObjectClass), +}; + +static void test_dummy_uint64(void) +{ + Error *err = NULL; + char *str; + DummyObject *dobj = DUMMY_OBJECT(object_new(TYPE_DUMMY)); + + g_assert(dobj->u64val == 0); + + str = g_strdup_printf("%" PRIu64, UINT64_MAX); + object_property_parse(OBJECT(dobj), str, "u64val", &err); + g_free(str); + g_assert(!err); + g_assert_cmpint(dobj->u64val, ==, UINT64_MAX); + + dobj->u64val = 0; + str = g_strdup_printf("0x%" PRIx64, UINT64_MAX); + object_property_parse(OBJECT(dobj), str, "u64val", &err); + g_free(str); + g_assert(!err); + g_assert_cmpint(dobj->u64val, ==, UINT64_MAX); + + object_unref(OBJECT(dobj)); +} + + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + module_call_init(MODULE_INIT_QOM); + type_register_static(&dummy_info); + + g_test_add_func("/qom/props/uint64", test_dummy_uint64); + + return g_test_run(); +} diff --git a/tests/scsi-disk-test.c b/tests/scsi-disk-test.c new file mode 100644 index 0000000000..5dc7e71417 --- /dev/null +++ b/tests/scsi-disk-test.c @@ -0,0 +1,82 @@ +/* + * QTest testcase for SCSI disks + * See virtio-scsi-test for more integrated tests. + * + * Copyright (c) 2015 SUSE Linux GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include +#include "libqtest.h" +#include "qapi/qmp/qnum.h" + +static void test_scsi_disk_common(const char *type, const char *id) +{ + char *cmdline, *path; + QDict *response; + QNum *value; + + cmdline = g_strdup_printf( + "-drive id=drv0,if=none,file=/dev/null,format=raw " + "-device virtio-scsi-pci,id=scsi0 " + "-device %s,id=%s,bus=scsi0.0,drive=drv0" + ",wwn=0x%" PRIx64 ",port_wwn=0x%" PRIx64, + type, id, UINT64_MAX, UINT64_C(1) << 63); + qtest_start(cmdline); + g_free(cmdline); + + path = g_strdup_printf("/machine/peripheral/%s", id); + + response = qmp("{ 'execute': 'qom-get'," + " 'arguments': { 'path': %s," + " 'property': 'wwn' } }", + path); + g_assert(response); + g_assert(qdict_haskey(response, "return")); + value = qobject_to_qnum(qdict_get(response, "return")); + g_assert_cmpint(qnum_get_uint(value), ==, UINT64_MAX); + + response = qmp("{ 'execute': 'qom-get'," + " 'arguments': { 'path': %s," + " 'property': 'port_wwn' } }", + path); + g_assert(response); + g_assert(qdict_haskey(response, "return")); + value = qobject_to_qnum(qdict_get(response, "return")); + g_assert_cmpint(qnum_get_uint(value), ==, UINT64_C(1) << 63); + + g_free(path); + qtest_end(); +} + +static void test_scsi_disk(void) +{ + test_scsi_disk_common("scsi-disk", "disk0"); +} + +static void test_scsi_hd(void) +{ + test_scsi_disk_common("scsi-hd", "hd0"); +} + +static void test_scsi_cd(void) +{ + test_scsi_disk_common("scsi-cd", "cd0"); +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + qtest_add_func("/scsi-disk/props", test_scsi_disk); + qtest_add_func("/scsi-hd/props", test_scsi_hd); + qtest_add_func("/scsi-cd/props", test_scsi_cd); + + ret = g_test_run(); + + return ret; +} diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c index 79313a7f7a..558782796a 100644 --- a/tests/test-string-input-visitor.c +++ b/tests/test-string-input-visitor.c @@ -55,6 +55,14 @@ static void test_visitor_in_int(TestInputVisitorData *data, v = visitor_input_test_init(data, "-42"); + visit_type_int(v, NULL, &res, &err); + g_assert(!err); + g_assert_cmpint(res, ==, value); + visitor_input_teardown(data, unused); + + value = INT64_MAX; + v = visitor_input_test_init(data, g_strdup_printf("%" PRId64, value)); + visit_type_int(v, NULL, &res, &err); g_assert(!err); g_assert_cmpint(res, ==, value); @@ -70,6 +78,27 @@ static void test_visitor_in_int(TestInputVisitorData *data, error_free_or_abort(&err); } +static void test_visitor_in_uint64(TestInputVisitorData *data, + const void *unused) +{ + uint64_t res = 0, value = UINT64_MAX; + Error *err = NULL; + Visitor *v; + + v = visitor_input_test_init(data, g_strdup_printf("%" PRIu64, value)); + + visit_type_uint64(v, NULL, &res, &err); + g_assert(!err); + g_assert_cmpint(res, ==, value); + visitor_input_teardown(data, unused); + + v = visitor_input_test_init(data, g_strdup_printf("0x%" PRIx64, value)); + + visit_type_uint64(v, NULL, &res, &err); + g_assert(!err); + g_assert_cmpint(res, ==, value); +} + static void check_ilist(Visitor *v, int64_t *expected, size_t n) { int64List *res = NULL; @@ -356,6 +385,8 @@ int main(int argc, char **argv) input_visitor_test_add("/string-visitor/input/int", &in_visitor_data, test_visitor_in_int); + input_visitor_test_add("/string-visitor/input/uint64", + &in_visitor_data, test_visitor_in_uint64); input_visitor_test_add("/string-visitor/input/intList", &in_visitor_data, test_visitor_in_intList); input_visitor_test_add("/string-visitor/input/bool", diff --git a/ui/console.c b/ui/console.c index d2d3534c49..c28e19c375 100644 --- a/ui/console.c +++ b/ui/console.c @@ -880,7 +880,7 @@ static void console_putchar(QemuConsole *s, int ch) } else { if (s->nb_esc_params < MAX_ESC_PARAMS) s->nb_esc_params++; - if (ch == ';') + if (ch == ';' || ch == '?') break; trace_console_putchar_csi(s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params); diff --git a/ui/vnc.c b/ui/vnc.c index 651cbb8606..eb3d7d0e54 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1657,6 +1657,25 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym) if (down) vs->modifiers_state[keycode] ^= 1; break; + default: + if (qemu_console_is_graphic(NULL)) { + /* record key 'down' info. Some client like tigervnc + * will send key down repeatedly if user pressing a + * a key for long time. In this case, we should add + * additional key up event before repeated key down, + * so that it can display the key multiple times. + */ + if (down) { + if (vs->modifiers_state[keycode]) { + /* add a key up event */ + do_key_event(vs, 0, keycode, sym); + } + vs->modifiers_state[keycode] = 1; + } else { + vs->modifiers_state[keycode] = 0; + } + } + break; } /* Turn off the lock state sync logic if the client support the led diff --git a/user-exec.c b/user-exec.c index 2a975eaf69..6225c4e1a8 100644 --- a/user-exec.c +++ b/user-exec.c @@ -78,6 +78,10 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set); #endif + + /* Maybe we're still holding the TB fiddling lock? */ + tb_lock_reset(); + /* XXX: locking issue */ if (is_write && h2g_valid(address)) { switch (page_unprotect(h2g(address), pc)) { diff --git a/util/thread-pool.c b/util/thread-pool.c index 610646d131..2e34e9846d 100644 --- a/util/thread-pool.c +++ b/util/thread-pool.c @@ -308,7 +308,12 @@ static void thread_pool_init_one(ThreadPool *pool, AioContext *ctx) qemu_mutex_init(&pool->lock); qemu_cond_init(&pool->worker_stopped); qemu_sem_init(&pool->sem, 0); - pool->max_threads = 64; + if (sizeof(pool) == 4) { + /* 32bit systems run out of virtual memory quickly */ + pool->max_threads = 4; + } else { + pool->max_threads = 64; + } pool->new_thread_bh = aio_bh_new(ctx, spawn_thread_bh_fn, pool); QLIST_INIT(&pool->head); diff --git a/vl.c b/vl.c index 8e247cc2a2..9bfbc25c6b 100644 --- a/vl.c +++ b/vl.c @@ -26,6 +26,7 @@ #include "qemu/cutils.h" #include "qemu/help_option.h" #include "qemu/uuid.h" +#include #ifdef CONFIG_SECCOMP #include "sysemu/seccomp.h" @@ -3035,6 +3036,7 @@ int main(int argc, char **argv, char **envp) } BlockdevOptions_queue; QSIMPLEQ_HEAD(, BlockdevOptions_queue) bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); + struct rlimit rlimit_as; module_call_init(MODULE_INIT_TRACE); @@ -3042,6 +3044,16 @@ int main(int argc, char **argv, char **envp) qemu_init_cpu_loop(); qemu_mutex_lock_iothread(); + /* + * Try to raise the soft address space limit. + * Default on SLES 11 SP2 is 80% of physical+swap memory. + */ + getrlimit(RLIMIT_AS, &rlimit_as); + if (rlimit_as.rlim_cur < rlimit_as.rlim_max) { + rlimit_as.rlim_cur = rlimit_as.rlim_max; + setrlimit(RLIMIT_AS, &rlimit_as); + } + atexit(qemu_run_exit_notifiers); error_set_progname(argv[0]); qemu_init_exec_dir(argv[0]);