From e76d442043ff50716457d5558c237b6e60345f53 Mon Sep 17 00:00:00 2001 From: Gal Hammer Date: Wed, 7 Jan 2015 10:38:35 +0200 Subject: [PATCH 01/15] char: restore stdio echo on resume from suspend. The monitor's auto-completion feature stopped working when stdio is used as an input and qemu was resumed after it was suspended (using ctrl-z). Signed-off-by: Gal Hammer Signed-off-by: Paolo Bonzini --- qemu-char.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/qemu-char.c b/qemu-char.c index ef84b53681..5430b87048 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -1112,6 +1112,9 @@ static struct termios oldtty; static int old_fd0_flags; static bool stdio_in_use; static bool stdio_allow_signal; +static bool stdio_echo_state; + +static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo); static void term_exit(void) { @@ -1119,10 +1122,17 @@ static void term_exit(void) fcntl(0, F_SETFL, old_fd0_flags); } +static void term_stdio_handler(int sig) +{ + /* restore echo after resume from suspend. */ + qemu_chr_set_echo_stdio(NULL, stdio_echo_state); +} + static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo) { struct termios tty; + stdio_echo_state = echo; tty = oldtty; if (!echo) { tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP @@ -1149,6 +1159,7 @@ static void qemu_chr_close_stdio(struct CharDriverState *chr) static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts) { CharDriverState *chr; + struct sigaction act; if (is_daemonized()) { error_report("cannot use stdio with -daemonize"); @@ -1166,6 +1177,10 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts) qemu_set_nonblock(0); atexit(term_exit); + memset(&act, 0, sizeof(act)); + act.sa_handler = term_stdio_handler; + sigaction(SIGCONT, &act, NULL); + chr = qemu_chr_open_fd(0, 1); chr->chr_close = qemu_chr_close_stdio; chr->chr_set_echo = qemu_chr_set_echo_stdio; From 364c3e6b8dd7912e01d19122d791b8c8f6df4f6c Mon Sep 17 00:00:00 2001 From: Marcel Apfelbaum Date: Wed, 7 Jan 2015 14:11:38 +0200 Subject: [PATCH 02/15] vl.c: fix regression when reading machine type from config file After 'Machine as QOM' series the machine type input triggers the creation of the machine class. If the machine type is set in the configuration file, the machine class is not updated accordingly and remains the default. Fixed that by querying the machine options after the configuration file is loaded. Cc: qemu-stable@nongnu.org Reported-by: William Dauchy Signed-off-by: Marcel Apfelbaum Signed-off-by: Paolo Bonzini --- vl.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/vl.c b/vl.c index 7786b2f921..1a2da2b36a 100644 --- a/vl.c +++ b/vl.c @@ -2796,9 +2796,6 @@ int main(int argc, char **argv, char **envp) exit(1); } switch(popt->index) { - case QEMU_OPTION_M: - machine_class = machine_parse(optarg); - break; case QEMU_OPTION_no_kvm_irqchip: { olist = qemu_find_opts("machine"); qemu_opts_parse(olist, "kernel_irqchip=off", 0); @@ -3420,16 +3417,13 @@ int main(int argc, char **argv, char **envp) olist = qemu_find_opts("machine"); qemu_opts_parse(olist, "accel=kvm", 0); break; + case QEMU_OPTION_M: case QEMU_OPTION_machine: olist = qemu_find_opts("machine"); opts = qemu_opts_parse(olist, optarg, 1); if (!opts) { exit(1); } - optarg = qemu_opt_get(opts, "type"); - if (optarg) { - machine_class = machine_parse(optarg); - } break; case QEMU_OPTION_no_kvm: olist = qemu_find_opts("machine"); @@ -3752,6 +3746,13 @@ int main(int argc, char **argv, char **envp) } } } + + opts = qemu_get_machine_opts(); + optarg = qemu_opt_get(opts, "type"); + if (optarg) { + machine_class = machine_parse(optarg); + } + loc_set_none(); os_daemonize(); From 4d91558d60c229f34819329728cf46ff71e13935 Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Fri, 31 Oct 2014 17:03:53 +0900 Subject: [PATCH 03/15] 9pfs: changed to use event_notifier instead of qemu_pipe Changed to use event_notifier instead of qemu_pipe. It is necessary for porting 9pfs to Windows and MacOS. Signed-off-by: SeokYeon Hwang Signed-off-by: Paolo Bonzini --- hw/9pfs/virtio-9p-coth.c | 29 +++++++---------------------- hw/9pfs/virtio-9p-coth.h | 4 ++-- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/hw/9pfs/virtio-9p-coth.c b/hw/9pfs/virtio-9p-coth.c index ae6cde8005..8185c533c0 100644 --- a/hw/9pfs/virtio-9p-coth.c +++ b/hw/9pfs/virtio-9p-coth.c @@ -14,6 +14,7 @@ #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" +#include "qemu/event_notifier.h" #include "block/coroutine.h" #include "virtio-9p-coth.h" @@ -26,15 +27,11 @@ void co_run_in_worker_bh(void *opaque) g_thread_pool_push(v9fs_pool.pool, co, NULL); } -static void v9fs_qemu_process_req_done(void *arg) +static void v9fs_qemu_process_req_done(EventNotifier *e) { - char byte; - ssize_t len; Coroutine *co; - do { - len = read(v9fs_pool.rfd, &byte, sizeof(byte)); - } while (len == -1 && errno == EINTR); + event_notifier_test_and_clear(e); while ((co = g_async_queue_try_pop(v9fs_pool.completed)) != NULL) { qemu_coroutine_enter(co, NULL); @@ -43,22 +40,18 @@ static void v9fs_qemu_process_req_done(void *arg) static void v9fs_thread_routine(gpointer data, gpointer user_data) { - ssize_t len; - char byte = 0; Coroutine *co = data; qemu_coroutine_enter(co, NULL); g_async_queue_push(v9fs_pool.completed, co); - do { - len = write(v9fs_pool.wfd, &byte, sizeof(byte)); - } while (len == -1 && errno == EINTR); + + event_notifier_set(&v9fs_pool.e); } int v9fs_init_worker_threads(void) { int ret = 0; - int notifier_fds[2]; V9fsThPool *p = &v9fs_pool; sigset_t set, oldset; @@ -66,10 +59,6 @@ int v9fs_init_worker_threads(void) /* Leave signal handling to the iothread. */ pthread_sigmask(SIG_SETMASK, &set, &oldset); - if (qemu_pipe(notifier_fds) == -1) { - ret = -1; - goto err_out; - } p->pool = g_thread_pool_new(v9fs_thread_routine, p, -1, FALSE, NULL); if (!p->pool) { ret = -1; @@ -84,13 +73,9 @@ int v9fs_init_worker_threads(void) ret = -1; goto err_out; } - p->rfd = notifier_fds[0]; - p->wfd = notifier_fds[1]; + event_notifier_init(&p->e, 0); - fcntl(p->rfd, F_SETFL, O_NONBLOCK); - fcntl(p->wfd, F_SETFL, O_NONBLOCK); - - qemu_set_fd_handler(p->rfd, v9fs_qemu_process_req_done, NULL, NULL); + event_notifier_set_handler(&p->e, v9fs_qemu_process_req_done); err_out: pthread_sigmask(SIG_SETMASK, &oldset, NULL); return ret; diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 86d5ed4169..4f51b250d1 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -21,8 +21,8 @@ #include typedef struct V9fsThPool { - int rfd; - int wfd; + EventNotifier e; + GThreadPool *pool; GAsyncQueue *completed; } V9fsThPool; From 719cac1ce20c8806303793b2501aedb9edf1bca3 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 19 Dec 2014 00:59:45 -0200 Subject: [PATCH 04/15] vl: Avoid unnecessary 'if' nesting Just a coding style change, to make other changes easier to review. Signed-off-by: Eduardo Habkost Reviewed-by: Andrew Jones Signed-off-by: Paolo Bonzini --- vl.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/vl.c b/vl.c index 1a2da2b36a..56a17ddc6b 100644 --- a/vl.c +++ b/vl.c @@ -1170,13 +1170,11 @@ static void smp_parse(QemuOpts *opts) if (cpus == 0) { cpus = cores * threads * sockets; } + } else if (cores == 0) { + threads = threads > 0 ? threads : 1; + cores = cpus / (sockets * threads); } else { - if (cores == 0) { - threads = threads > 0 ? threads : 1; - cores = cpus / (sockets * threads); - } else { - threads = cpus / (cores * sockets); - } + threads = cpus / (cores * sockets); } max_cpus = qemu_opt_get_number(opts, "maxcpus", 0); From c00cd99527d0d1b47a387239a7e3a8cf8ff82764 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 19 Dec 2014 00:59:46 -0200 Subject: [PATCH 05/15] vl: fix max_cpus check We should confirm max_cpus, which is >= smp_cpus, is <= the machine's true max_cpus, not just smp_cpus. Signed-off-by: Andrew Jones Reviewed-by: Eduardo Habkost Signed-off-by: Eduardo Habkost Signed-off-by: Paolo Bonzini --- vl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vl.c b/vl.c index 56a17ddc6b..95451b6af8 100644 --- a/vl.c +++ b/vl.c @@ -3850,9 +3850,9 @@ int main(int argc, char **argv, char **envp) smp_parse(qemu_opts_find(qemu_find_opts("smp-opts"), NULL)); machine_class->max_cpus = machine_class->max_cpus ?: 1; /* Default to UP */ - if (smp_cpus > machine_class->max_cpus) { + if (max_cpus > machine_class->max_cpus) { fprintf(stderr, "Number of SMP cpus requested (%d), exceeds max cpus " - "supported by machine `%s' (%d)\n", smp_cpus, + "supported by machine `%s' (%d)\n", max_cpus, machine_class->name, machine_class->max_cpus); exit(1); } From ec2cbbdd80463efd4bc81a9d1362a2acb3097a21 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 19 Dec 2014 00:59:47 -0200 Subject: [PATCH 06/15] vl: Don't silently change topology when all -smp options were set QEMU tries to change the "threads" option even if it was explicitly set in the command-line, and it shouldn't do that. The right thing to do when all options (cpus, sockets, cores, threds) are explicitly set is to sanity check them and abort in case they don't make sense (i.e. when sockets*cores*threads < cpus). Signed-off-by: Eduardo Habkost Reviewed-by: Andrew Jones Signed-off-by: Paolo Bonzini --- vl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/vl.c b/vl.c index 95451b6af8..f6b24c4070 100644 --- a/vl.c +++ b/vl.c @@ -1173,8 +1173,14 @@ static void smp_parse(QemuOpts *opts) } else if (cores == 0) { threads = threads > 0 ? threads : 1; cores = cpus / (sockets * threads); - } else { + } else if (threads == 0) { threads = cpus / (cores * sockets); + } else if (sockets * cores * threads < cpus) { + fprintf(stderr, "cpu topology: error: " + "sockets (%u) * cores (%u) * threads (%u) < " + "smp_cpus (%u)\n", + sockets, cores, threads, cpus); + exit(1); } max_cpus = qemu_opt_get_number(opts, "maxcpus", 0); From 3b9985e9a104dd90427570dd4e06e4d1f152c48b Mon Sep 17 00:00:00 2001 From: Marcel Apfelbaum Date: Sun, 11 Jan 2015 12:38:43 +0200 Subject: [PATCH 07/15] vl.c: fix regression when reading memory size from config file This is happening because an actual logic is performed on the memory arguments inside the main's switch, disregarding the config file content. Solved by extracting the logic on a separate function and calling it after the switch. Signed-off-by: Marcel Apfelbaum Signed-off-by: Paolo Bonzini --- vl.c | 177 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 90 insertions(+), 87 deletions(-) diff --git a/vl.c b/vl.c index f6b24c4070..6adb36ecd4 100644 --- a/vl.c +++ b/vl.c @@ -2648,6 +2648,92 @@ out: return 0; } +static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size) +{ + uint64_t sz; + const char *mem_str; + const char *maxmem_str, *slots_str; + const ram_addr_t default_ram_size = (ram_addr_t)DEFAULT_RAM_SIZE * + 1024 * 1024; + QemuOpts *opts = qemu_find_opts_singleton("memory"); + + sz = 0; + mem_str = qemu_opt_get(opts, "size"); + if (mem_str) { + if (!*mem_str) { + error_report("missing 'size' option value"); + exit(EXIT_FAILURE); + } + + sz = qemu_opt_get_size(opts, "size", ram_size); + + /* Fix up legacy suffix-less format */ + if (g_ascii_isdigit(mem_str[strlen(mem_str) - 1])) { + uint64_t overflow_check = sz; + + sz <<= 20; + if ((sz >> 20) != overflow_check) { + error_report("too large 'size' option value"); + exit(EXIT_FAILURE); + } + } + } + + /* backward compatibility behaviour for case "-m 0" */ + if (sz == 0) { + sz = default_ram_size; + } + + sz = QEMU_ALIGN_UP(sz, 8192); + ram_size = sz; + if (ram_size != sz) { + error_report("ram size too large"); + exit(EXIT_FAILURE); + } + + /* store value for the future use */ + qemu_opt_set_number(opts, "size", ram_size); + *maxram_size = ram_size; + + maxmem_str = qemu_opt_get(opts, "maxmem"); + slots_str = qemu_opt_get(opts, "slots"); + if (maxmem_str && slots_str) { + uint64_t slots; + + sz = qemu_opt_get_size(opts, "maxmem", 0); + if (sz < ram_size) { + error_report("invalid -m option value: maxmem " + "(0x%" PRIx64 ") <= initial memory (0x" + RAM_ADDR_FMT ")", sz, ram_size); + exit(EXIT_FAILURE); + } + + slots = qemu_opt_get_number(opts, "slots", 0); + if ((sz > ram_size) && !slots) { + error_report("invalid -m option value: maxmem " + "(0x%" PRIx64 ") more than initial memory (0x" + RAM_ADDR_FMT ") but no hotplug slots where " + "specified", sz, ram_size); + exit(EXIT_FAILURE); + } + + if ((sz <= ram_size) && slots) { + error_report("invalid -m option value: %" + PRIu64 " hotplug slots where specified but " + "maxmem (0x%" PRIx64 ") <= initial memory (0x" + RAM_ADDR_FMT ")", slots, sz, ram_size); + exit(EXIT_FAILURE); + } + *maxram_size = sz; + *ram_slots = slots; + } else if ((!maxmem_str && slots_str) || + (maxmem_str && !slots_str)) { + error_report("invalid -m option value: missing " + "'%s' option", slots_str ? "maxmem" : "slots"); + exit(EXIT_FAILURE); + } +} + int main(int argc, char **argv, char **envp) { int i; @@ -2683,9 +2769,7 @@ int main(int argc, char **argv, char **envp) }; const char *trace_events = NULL; const char *trace_file = NULL; - const ram_addr_t default_ram_size = (ram_addr_t)DEFAULT_RAM_SIZE * - 1024 * 1024; - ram_addr_t maxram_size = default_ram_size; + ram_addr_t maxram_size; uint64_t ram_slots = 0; FILE *vmstate_dump_file = NULL; Error *main_loop_err = NULL; @@ -2736,7 +2820,6 @@ int main(int argc, char **argv, char **envp) module_call_init(MODULE_INIT_MACHINE); machine_class = find_default_machine(); cpu_model = NULL; - ram_size = default_ram_size; snapshot = 0; cyls = heads = secs = 0; translation = BIOS_ATA_TRANSLATION_AUTO; @@ -3023,92 +3106,13 @@ int main(int argc, char **argv, char **envp) version(); exit(0); break; - case QEMU_OPTION_m: { - uint64_t sz; - const char *mem_str; - const char *maxmem_str, *slots_str; - + case QEMU_OPTION_m: opts = qemu_opts_parse(qemu_find_opts("memory"), optarg, 1); if (!opts) { exit(EXIT_FAILURE); } - - mem_str = qemu_opt_get(opts, "size"); - if (!mem_str) { - error_report("invalid -m option, missing 'size' option"); - exit(EXIT_FAILURE); - } - if (!*mem_str) { - error_report("missing 'size' option value"); - exit(EXIT_FAILURE); - } - - sz = qemu_opt_get_size(opts, "size", ram_size); - - /* Fix up legacy suffix-less format */ - if (g_ascii_isdigit(mem_str[strlen(mem_str) - 1])) { - uint64_t overflow_check = sz; - - sz <<= 20; - if ((sz >> 20) != overflow_check) { - error_report("too large 'size' option value"); - exit(EXIT_FAILURE); - } - } - - /* backward compatibility behaviour for case "-m 0" */ - if (sz == 0) { - sz = default_ram_size; - } - - sz = QEMU_ALIGN_UP(sz, 8192); - ram_size = sz; - if (ram_size != sz) { - error_report("ram size too large"); - exit(EXIT_FAILURE); - } - maxram_size = ram_size; - - maxmem_str = qemu_opt_get(opts, "maxmem"); - slots_str = qemu_opt_get(opts, "slots"); - if (maxmem_str && slots_str) { - uint64_t slots; - - sz = qemu_opt_get_size(opts, "maxmem", 0); - if (sz < ram_size) { - error_report("invalid -m option value: maxmem " - "(0x%" PRIx64 ") <= initial memory (0x" - RAM_ADDR_FMT ")", sz, ram_size); - exit(EXIT_FAILURE); - } - - slots = qemu_opt_get_number(opts, "slots", 0); - if ((sz > ram_size) && !slots) { - error_report("invalid -m option value: maxmem " - "(0x%" PRIx64 ") more than initial memory (0x" - RAM_ADDR_FMT ") but no hotplug slots where " - "specified", sz, ram_size); - exit(EXIT_FAILURE); - } - - if ((sz <= ram_size) && slots) { - error_report("invalid -m option value: %" - PRIu64 " hotplug slots where specified but " - "maxmem (0x%" PRIx64 ") <= initial memory (0x" - RAM_ADDR_FMT ")", slots, sz, ram_size); - exit(EXIT_FAILURE); - } - maxram_size = sz; - ram_slots = slots; - } else if ((!maxmem_str && slots_str) || - (maxmem_str && !slots_str)) { - error_report("invalid -m option value: missing " - "'%s' option", slots_str ? "maxmem" : "slots"); - exit(EXIT_FAILURE); - } break; - } #ifdef CONFIG_TPM case QEMU_OPTION_tpmdev: if (tpm_config_parse(qemu_find_opts("tpmdev"), optarg) < 0) { @@ -3757,6 +3761,8 @@ int main(int argc, char **argv, char **envp) machine_class = machine_parse(optarg); } + set_memory_options(&ram_slots, &maxram_size); + loc_set_none(); os_daemonize(); @@ -4006,9 +4012,6 @@ int main(int argc, char **argv, char **envp) exit(1); } - /* store value for the future use */ - qemu_opt_set_number(qemu_find_opts_singleton("memory"), "size", ram_size); - if (qemu_opts_foreach(qemu_find_opts("device"), device_help_func, NULL, 0) != 0) { exit(0); From 07958082fdf39284935d38a5b8aec1fe7d020637 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 7 Jan 2015 17:36:27 +0100 Subject: [PATCH 08/15] target-i386: fix movntsd on big-endian hosts This was accessing an XMM register's low half without going through XMM_Q. Cc: qemu-stable@nongnu.org Reviewed-by: Eduardo Habkost Signed-off-by: Paolo Bonzini --- target-i386/translate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target-i386/translate.c b/target-i386/translate.c index ebdc3500e5..5af43003b0 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -3074,7 +3074,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, goto illegal_op; gen_lea_modrm(env, s, modrm); if (b1 & 1) { - gen_stq_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); + gen_stq_env_A0(s, offsetof(CPUX86State, + xmm_regs[reg].XMM_Q(0))); } else { tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, xmm_regs[reg].XMM_L(0))); From bee818872cd9e8c07be529f75da3e48a68bf7a93 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 24 Oct 2014 09:44:38 +0200 Subject: [PATCH 09/15] target-i386: do not memcpy in and out of xmm_regs After the next patch, we will move the high parts of AVX and AVX512 registers in the same array as the SSE registers. This will make it impossible to memcpy an array of 128-bit values in and out of xmm_regs in one swoop. Use a for loop instead. Similarly, always use XMM_Q in translate.c. This avoids introducing bugs such as the one fixed in the previous patch. Reviewed-by: Eduardo Habkost Signed-off-by: Paolo Bonzini --- target-i386/kvm.c | 30 ++++++++++++++++++++++++------ target-i386/translate.c | 8 ++++---- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index f92edfe14a..cf9f3319c2 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1019,7 +1019,10 @@ static int kvm_put_fpu(X86CPU *cpu) fpu.ftwx |= (!env->fptags[i]) << i; } memcpy(fpu.fpr, env->fpregs, sizeof env->fpregs); - memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs); + for (i = 0; i < CPU_NB_REGS; i++) { + stq_p(&fpu.xmm[i][0], env->xmm_regs[i].XMM_Q(0)); + stq_p(&fpu.xmm[i][8], env->xmm_regs[i].XMM_Q(1)); + } fpu.mxcsr = env->mxcsr; return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_FPU, &fpu); @@ -1045,6 +1048,7 @@ static int kvm_put_xsave(X86CPU *cpu) CPUX86State *env = &cpu->env; struct kvm_xsave* xsave = env->kvm_xsave_buf; uint16_t cwd, swd, twd; + uint8_t *xmm; int i, r; if (!kvm_has_xsave()) { @@ -1065,8 +1069,6 @@ static int kvm_put_xsave(X86CPU *cpu) memcpy(&xsave->region[XSAVE_CWD_RDP], &env->fpdp, sizeof(env->fpdp)); memcpy(&xsave->region[XSAVE_ST_SPACE], env->fpregs, sizeof env->fpregs); - memcpy(&xsave->region[XSAVE_XMM_SPACE], env->xmm_regs, - sizeof env->xmm_regs); xsave->region[XSAVE_MXCSR] = env->mxcsr; *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] = env->xstate_bv; memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs, @@ -1079,6 +1081,13 @@ static int kvm_put_xsave(X86CPU *cpu) sizeof env->opmask_regs); memcpy(&xsave->region[XSAVE_ZMM_Hi256], env->zmmh_regs, sizeof env->zmmh_regs); + + xmm = (uint8_t *)&xsave->region[XSAVE_XMM_SPACE]; + for (i = 0; i < CPU_NB_REGS; i++, xmm += 16) { + stq_p(xmm, env->xmm_regs[i].XMM_Q(0)); + stq_p(xmm+8, env->xmm_regs[i].XMM_Q(1)); + } + #ifdef TARGET_X86_64 memcpy(&xsave->region[XSAVE_Hi16_ZMM], env->hi16_zmm_regs, sizeof env->hi16_zmm_regs); @@ -1384,7 +1393,10 @@ static int kvm_get_fpu(X86CPU *cpu) env->fptags[i] = !((fpu.ftwx >> i) & 1); } memcpy(env->fpregs, fpu.fpr, sizeof env->fpregs); - memcpy(env->xmm_regs, fpu.xmm, sizeof env->xmm_regs); + for (i = 0; i < CPU_NB_REGS; i++) { + env->xmm_regs[i].XMM_Q(0) = ldq_p(&fpu.xmm[i][0]); + env->xmm_regs[i].XMM_Q(1) = ldq_p(&fpu.xmm[i][8]); + } env->mxcsr = fpu.mxcsr; return 0; @@ -1395,6 +1407,7 @@ static int kvm_get_xsave(X86CPU *cpu) CPUX86State *env = &cpu->env; struct kvm_xsave* xsave = env->kvm_xsave_buf; int ret, i; + const uint8_t *xmm; uint16_t cwd, swd, twd; if (!kvm_has_xsave()) { @@ -1421,8 +1434,6 @@ static int kvm_get_xsave(X86CPU *cpu) env->mxcsr = xsave->region[XSAVE_MXCSR]; memcpy(env->fpregs, &xsave->region[XSAVE_ST_SPACE], sizeof env->fpregs); - memcpy(env->xmm_regs, &xsave->region[XSAVE_XMM_SPACE], - sizeof env->xmm_regs); env->xstate_bv = *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV]; memcpy(env->ymmh_regs, &xsave->region[XSAVE_YMMH_SPACE], sizeof env->ymmh_regs); @@ -1434,6 +1445,13 @@ static int kvm_get_xsave(X86CPU *cpu) sizeof env->opmask_regs); memcpy(env->zmmh_regs, &xsave->region[XSAVE_ZMM_Hi256], sizeof env->zmmh_regs); + + xmm = (const uint8_t *)&xsave->region[XSAVE_XMM_SPACE]; + for (i = 0; i < CPU_NB_REGS; i++, xmm += 16) { + env->xmm_regs[i].XMM_Q(0) = ldq_p(xmm); + env->xmm_regs[i].XMM_Q(1) = ldq_p(xmm+8); + } + #ifdef TARGET_X86_64 memcpy(env->hi16_zmm_regs, &xsave->region[XSAVE_Hi16_ZMM], sizeof env->hi16_zmm_regs); diff --git a/target-i386/translate.c b/target-i386/translate.c index 5af43003b0..9ebdf4b384 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -2621,10 +2621,10 @@ static inline void gen_sto_env_A0(DisasContext *s, int offset) static inline void gen_op_movo(int d_offset, int s_offset) { - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8); + tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(0))); + tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(0))); + tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(1))); + tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(1))); } static inline void gen_op_movq(int d_offset, int s_offset) From e1660dc57c1bacb78cbe39001e58a577c927dacb Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Fri, 9 Jan 2015 11:25:20 +0000 Subject: [PATCH 10/15] qemu-common.h: optimise muldiv64 if int128 is available Let compiler do the job to optimise the function. Signed-off-by: Frediano Ziglio Signed-off-by: Paolo Bonzini Signed-off-by: Frediano Ziglio --- include/qemu-common.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/qemu-common.h b/include/qemu-common.h index f8622141a8..644b46dcdd 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -370,6 +370,12 @@ static inline uint8_t from_bcd(uint8_t val) } /* compute with 96 bit intermediate result: (a*b)/c */ +#ifdef CONFIG_INT128 +static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) +{ + return (__int128_t)a * b / c; +} +#else static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) { union { @@ -392,6 +398,7 @@ static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; return res.ll; } +#endif /* Round number down to multiple */ #define QEMU_ALIGN_DOWN(n, m) ((n) / (m) * (m)) From 6f84da3a07668ce881a0c853390eb05313d61157 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Mon, 12 Jan 2015 10:45:17 +0100 Subject: [PATCH 11/15] hw/scsi/lsi53c895a: add support for additional diag / debug registers Some ancient Linux kernels read from registers 0x09 and 0x3c-3f during boot. According to the spec these registers are for diag and debug purposes only. If they are absend qemu aborts on read. Signed-off-by: Peter Lieven Signed-off-by: Paolo Bonzini --- hw/scsi/lsi53c895a.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index ec920488d6..db7d4b8c9c 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -277,6 +277,7 @@ typedef struct { uint32_t csbc; uint32_t scratch[18]; /* SCRATCHA-SCRATCHR */ uint8_t sbr; + uint32_t adder; /* Script ram is stored as 32-bit words in host byteorder. */ uint32_t script_ram[2048]; @@ -1389,6 +1390,7 @@ again: switch ((insn >> 27) & 7) { case 0: /* Jump */ DPRINTF("Jump to 0x%08x\n", addr); + s->adder = addr; s->dsp = addr; break; case 1: /* Call */ @@ -1513,6 +1515,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) return 0x7f; case 0x08: /* Revision ID */ return 0x00; + case 0x09: /* SOCL */ + return s->socl; case 0xa: /* SSID */ return s->ssid; case 0xb: /* SBCL */ @@ -1577,6 +1581,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) return s->sbr; case 0x3b: /* DCNTL */ return s->dcntl; + /* ADDER Output (Debug of relative jump address) */ + CASE_GET_REG32(adder, 0x3c) case 0x40: /* SIEN0 */ return s->sien0; case 0x41: /* SIEN1 */ From c88f68ec3ce54ebc5da13d07d6512689c4e9be30 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 12 Jan 2015 12:43:09 +0800 Subject: [PATCH 12/15] rules.mak: Fix module build Module build is broken since commit c261d774fb ( rules.mak: Fix DSO build by pulling in archive symbols). That commit added .mo placeholders of DSO to -y variables, in order to pull stub symbols to executable. But the placeholders are unintentionally expanded in -y, rather than filtered out while linking. Fix it by moving the -objs expanding to before inserting .mo placeholders. Note that passing -cflags and -libs to member objects are also moved to keep it happening before object expanding. Reported-by: Bharata B Rao Tested-by: Bharata B Rao Signed-off-by: Fam Zheng Signed-off-by: Paolo Bonzini --- rules.mak | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/rules.mak b/rules.mak index f500fefdd1..3a056272e2 100644 --- a/rules.mak +++ b/rules.mak @@ -326,7 +326,17 @@ define unnest-vars $(if $1,$(call fix-paths,$1/,,$2)) # Descend and include every subdir Makefile.objs - $(foreach v, $2, $(call unnest-var-recursive,$1,$2,$v)) + $(foreach v, $2, + $(call unnest-var-recursive,$1,$2,$v) + # Pass the .mo-cflags and .mo-libs along to its member objects + $(foreach o, $(filter %.mo,$($v)), + $(foreach p,$($o-objs), + $(if $($o-cflags), $(eval $p-cflags += $($o-cflags))) + $(if $($o-libs), $(eval $p-libs += $($o-libs)))))) + + # For all %.mo objects that are directly added into -y, just expand them + $(foreach v,$(filter %-y,$2), + $(eval $v := $(foreach o,$($v),$(if $($o-objs),$($o-objs),$o)))) $(foreach v,$(filter %-m,$2), # All .o found in *-m variables are single object modules, create .mo @@ -353,18 +363,9 @@ define unnest-vars # according to .mo-objs. Report error if not set $(if $($o-objs), $(eval $(o:%.mo=%$(DSOSUF)): module-common.o $($o-objs)), - $(error $o added in $v but $o-objs is not set)) - # Pass the .mo-cflags and .mo-libs along to member objects - $(foreach p,$($o-objs), - $(if $($o-cflags), $(eval $p-cflags += $($o-cflags))) - $(if $($o-libs), $(eval $p-libs += $($o-libs))))) + $(error $o added in $v but $o-objs is not set))) $(shell mkdir -p ./ $(sort $(dir $($v)))) # Include all the .d files $(eval -include $(addsuffix *.d, $(sort $(dir $($v))))) $(eval $v := $(filter-out %/,$($v)))) - - # For all %.mo objects that are directly added into -y, expand them to %.mo-objs - $(foreach v,$2, - $(eval $v := $(foreach o,$($v),$(if $($o-objs),$($o-objs),$o)))) - endef From 488eef2f1d16c97cf7f9ebf644ecafa1ea1e9acc Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 12 Jan 2015 11:47:30 +0100 Subject: [PATCH 13/15] scsi: fix cancellation when I/O was completed but DMA was not. Commit d577646 (scsi: Introduce scsi_req_cancel_complete, 2014-09-25) was supposed to have no semantic change, but it missed a case. When r->aiocb has already been NULLed, but DMA was not complete and the SCSI layer was waiting for scsi_req_continue, after the patch the SCSI layer will not call the .cancel callback of SCSIBusInfo. Fixes: d5776465ee9a55815792efa34d79de240f4ffd99 Cc: qemu-stable@nongnu.org Reported-by: Dr. David Alan Gilbert Tested-by: Dr. David Alan Gilbert Reviewed-by: Fam Zheng Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-bus.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 24f7b74ae8..9b740a3cfa 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -1770,6 +1770,8 @@ void scsi_req_cancel(SCSIRequest *req) req->io_canceled = true; if (req->aiocb) { blk_aio_cancel(req->aiocb); + } else { + scsi_req_cancel_complete(req); } } From f186aa976bab11130af7299b07f7fafd258a63f1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 23 Dec 2014 21:54:14 +0100 Subject: [PATCH 14/15] qemu-timer: rename timer_init to timer_init_tl timer_init is not called that often. Free the name for an equivalent of timer_new. Signed-off-by: Paolo Bonzini --- include/block/aio.h | 2 +- include/qemu/timer.h | 10 +++++----- qemu-timer.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/block/aio.h b/include/block/aio.h index 6bf0e0456a..7d1e26b33b 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -314,7 +314,7 @@ static inline void aio_timer_init(AioContext *ctx, int scale, QEMUTimerCB *cb, void *opaque) { - timer_init(ts, ctx->tlg.tl[type], scale, cb, opaque); + timer_init_tl(ts, ctx->tlg.tl[type], scale, cb, opaque); } /** diff --git a/include/qemu/timer.h b/include/qemu/timer.h index d9df0940d9..0666920652 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -410,7 +410,7 @@ int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg); */ /** - * timer_init: + * timer_init_tl: * @ts: the timer to be initialised * @timer_list: the timer list to attach the timer to * @scale: the scale value for the timer @@ -423,9 +423,9 @@ int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg); * You need not call an explicit deinit call. Simply make * sure it is not on a list with timer_del. */ -void timer_init(QEMUTimer *ts, - QEMUTimerList *timer_list, int scale, - QEMUTimerCB *cb, void *opaque); +void timer_init_tl(QEMUTimer *ts, + QEMUTimerList *timer_list, int scale, + QEMUTimerCB *cb, void *opaque); /** * timer_new_tl: @@ -448,7 +448,7 @@ static inline QEMUTimer *timer_new_tl(QEMUTimerList *timer_list, void *opaque) { QEMUTimer *ts = g_malloc0(sizeof(QEMUTimer)); - timer_init(ts, timer_list, scale, cb, opaque); + timer_init_tl(ts, timer_list, scale, cb, opaque); return ts; } diff --git a/qemu-timer.c b/qemu-timer.c index cb7d988b56..98d9d1bc0b 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -331,9 +331,9 @@ int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout) } -void timer_init(QEMUTimer *ts, - QEMUTimerList *timer_list, int scale, - QEMUTimerCB *cb, void *opaque) +void timer_init_tl(QEMUTimer *ts, + QEMUTimerList *timer_list, int scale, + QEMUTimerCB *cb, void *opaque) { ts->timer_list = timer_list; ts->cb = cb; From 1979b908b6e99cc24c1c0746060422f8778aa9d9 Mon Sep 17 00:00:00 2001 From: Pavel Dovgalyuk Date: Mon, 12 Jan 2015 15:00:43 +0300 Subject: [PATCH 15/15] cpus: consistently use QEMU_CLOCK_VIRTUAL_RT for icount_warp_rt timer Fix mismatch between timer_new_ms and timer_mod. Signed-off-by: Pavel Dovgalyuk Signed-off-by: Paolo Bonzini --- cpus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpus.c b/cpus.c index 2edb5cd807..3a5323b1fc 100644 --- a/cpus.c +++ b/cpus.c @@ -324,7 +324,7 @@ static void icount_adjust(void) static void icount_adjust_rt(void *opaque) { timer_mod(icount_rt_timer, - qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000); icount_adjust(); }