aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.objs2
-rw-r--r--Makefile.target6
-rw-r--r--accel/Makefile.objs2
-rw-r--r--accel/kvm/kvm-all.c29
-rw-r--r--accel/stubs/Makefile.objs1
-rw-r--r--accel/stubs/tcg-stub.c22
-rw-r--r--accel/tcg/Makefile.objs2
-rw-r--r--accel/tcg/cpu-exec-common.c2
-rw-r--r--accel/tcg/tcg-all.c35
-rw-r--r--accel/tcg/translate-all.c37
-rw-r--r--accel/tcg/translate-common.c56
-rw-r--r--block/nbd-client.c4
-rw-r--r--bootdevice.c2
-rw-r--r--bsd-user/main.c1
-rwxr-xr-xconfigure184
-rw-r--r--exec.c23
-rw-r--r--hmp-commands-info.hx4
-rw-r--r--hw/acpi/ich9.c1
-rw-r--r--hw/i386/kvmvapic.c5
-rw-r--r--hw/i386/pc_q35.c1
-rw-r--r--hw/misc/Makefile.objs2
-rw-r--r--hw/scsi/virtio-scsi.c3
-rw-r--r--include/exec/cpu-common.h2
-rw-r--r--include/exec/cpu-defs.h4
-rw-r--r--include/exec/exec-all.h7
-rw-r--r--include/exec/poison.h8
-rw-r--r--include/hw/i386/pc.h13
-rw-r--r--include/qemu-common.h7
-rw-r--r--include/qemu/main-loop.h2
-rw-r--r--include/qemu/thread-posix.h4
-rw-r--r--include/qemu/thread-win32.h5
-rw-r--r--include/qom/cpu.h13
-rw-r--r--include/sysemu/accel.h2
-rw-r--r--include/sysemu/kvm.h31
-rw-r--r--monitor.c2
-rw-r--r--qemu-doc.texi14
-rw-r--r--qom/cpu.c18
-rwxr-xr-xscripts/checkpatch.pl4
-rw-r--r--target/i386/Makefile.objs9
-rw-r--r--target/i386/cpu.c4
-rw-r--r--target/i386/cpu.h33
-rw-r--r--target/i386/excp_helper.c343
-rw-r--r--target/i386/fpu_helper.c29
-rw-r--r--target/i386/hax-all.c12
-rw-r--r--target/i386/helper.c376
-rw-r--r--target/i386/kvm.c91
-rw-r--r--target/i386/kvm_i386.h23
-rw-r--r--target/i386/machine.c31
-rw-r--r--target/i386/mpx_helper.c30
-rw-r--r--target/i386/seg_helper.c28
-rw-r--r--target/i386/xsave_helper.c114
-rw-r--r--target/mips/kvm.c4
-rw-r--r--tcg/tcg.h4
-rw-r--r--tests/test-char.c6
-rw-r--r--util/main-loop.c8
-rw-r--r--util/oslib-win32.c6
-rw-r--r--util/qemu-sockets.c2
-rw-r--r--util/qemu-thread-posix.c27
-rw-r--r--util/qemu-thread-win32.c34
-rw-r--r--vl.c14
60 files changed, 1009 insertions, 779 deletions
diff --git a/Makefile.objs b/Makefile.objs
index b2e6322..756644c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -40,7 +40,7 @@ io-obj-y = io/
ifeq ($(CONFIG_SOFTMMU),y)
common-obj-y = blockdev.o blockdev-nbd.o block/
-common-obj-y += iothread.o
+common-obj-y += bootdevice.o iothread.o
common-obj-y += net/
common-obj-y += qdev-monitor.o device-hotplug.o
common-obj-$(CONFIG_WIN32) += os-win32.o
diff --git a/Makefile.target b/Makefile.target
index 0066579..2baec92 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -90,8 +90,8 @@ all: $(PROGS) stap
# cpu emulator library
obj-y += exec.o
obj-y += accel/
-obj-y += tcg/tcg.o tcg/tcg-op.o tcg/optimize.o
-obj-y += tcg/tcg-common.o tcg/tcg-runtime.o
+obj-$(CONFIG_TCG) += tcg/tcg.o tcg/tcg-op.o tcg/optimize.o
+obj-$(CONFIG_TCG) += tcg/tcg-common.o tcg/tcg-runtime.o
obj-$(CONFIG_TCG_INTERPRETER) += tcg/tci.o
obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o
obj-y += fpu/softfloat.o
@@ -137,7 +137,7 @@ endif #CONFIG_BSD_USER
# System emulator target
ifdef CONFIG_SOFTMMU
obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
-obj-y += qtest.o bootdevice.o
+obj-y += qtest.o
obj-y += hw/
obj-y += memory.o
obj-y += memory_mapping.o
diff --git a/accel/Makefile.objs b/accel/Makefile.objs
index cd5702f..10666ed 100644
--- a/accel/Makefile.objs
+++ b/accel/Makefile.objs
@@ -1,4 +1,4 @@
obj-$(CONFIG_SOFTMMU) += accel.o
obj-y += kvm/
-obj-y += tcg/
+obj-$(CONFIG_TCG) += tcg/
obj-y += stubs/
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 75feffa..2eef7da 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -318,7 +318,7 @@ int kvm_init_vcpu(CPUState *cpu)
cpu->kvm_fd = ret;
cpu->kvm_state = s;
- cpu->kvm_vcpu_dirty = true;
+ cpu->vcpu_dirty = true;
mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
if (mmap_size < 0) {
@@ -981,15 +981,6 @@ static MemoryListener kvm_io_listener = {
.priority = 10,
};
-static void kvm_handle_interrupt(CPUState *cpu, int mask)
-{
- cpu->interrupt_request |= mask;
-
- if (!qemu_cpu_is_self(cpu)) {
- qemu_cpu_kick(cpu);
- }
-}
-
int kvm_set_irq(KVMState *s, int irq, int level)
{
struct kvm_irq_level event;
@@ -1774,8 +1765,6 @@ static int kvm_init(MachineState *ms)
s->many_ioeventfds = kvm_check_many_ioeventfds();
- cpu_interrupt_handler = kvm_handle_interrupt;
-
return 0;
err:
@@ -1864,15 +1853,15 @@ void kvm_flush_coalesced_mmio_buffer(void)
static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
{
- if (!cpu->kvm_vcpu_dirty) {
+ if (!cpu->vcpu_dirty) {
kvm_arch_get_registers(cpu);
- cpu->kvm_vcpu_dirty = true;
+ cpu->vcpu_dirty = true;
}
}
void kvm_cpu_synchronize_state(CPUState *cpu)
{
- if (!cpu->kvm_vcpu_dirty) {
+ if (!cpu->vcpu_dirty) {
run_on_cpu(cpu, do_kvm_cpu_synchronize_state, RUN_ON_CPU_NULL);
}
}
@@ -1880,7 +1869,7 @@ void kvm_cpu_synchronize_state(CPUState *cpu)
static void do_kvm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg)
{
kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE);
- cpu->kvm_vcpu_dirty = false;
+ cpu->vcpu_dirty = false;
}
void kvm_cpu_synchronize_post_reset(CPUState *cpu)
@@ -1891,7 +1880,7 @@ void kvm_cpu_synchronize_post_reset(CPUState *cpu)
static void do_kvm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg)
{
kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
- cpu->kvm_vcpu_dirty = false;
+ cpu->vcpu_dirty = false;
}
void kvm_cpu_synchronize_post_init(CPUState *cpu)
@@ -1901,7 +1890,7 @@ void kvm_cpu_synchronize_post_init(CPUState *cpu)
static void do_kvm_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg)
{
- cpu->kvm_vcpu_dirty = true;
+ cpu->vcpu_dirty = true;
}
void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu)
@@ -1982,9 +1971,9 @@ int kvm_cpu_exec(CPUState *cpu)
do {
MemTxAttrs attrs;
- if (cpu->kvm_vcpu_dirty) {
+ if (cpu->vcpu_dirty) {
kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE);
- cpu->kvm_vcpu_dirty = false;
+ cpu->vcpu_dirty = false;
}
kvm_arch_pre_run(cpu, run);
diff --git a/accel/stubs/Makefile.objs b/accel/stubs/Makefile.objs
index bd5794f..fdfbf73 100644
--- a/accel/stubs/Makefile.objs
+++ b/accel/stubs/Makefile.objs
@@ -1 +1,2 @@
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
+obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o
diff --git a/accel/stubs/tcg-stub.c b/accel/stubs/tcg-stub.c
new file mode 100644
index 0000000..5dd480b
--- /dev/null
+++ b/accel/stubs/tcg-stub.c
@@ -0,0 +1,22 @@
+/*
+ * QEMU TCG accelerator stub
+ *
+ * Copyright Red Hat, Inc. 2013
+ *
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * 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 "qemu-common.h"
+#include "cpu.h"
+#include "tcg/tcg.h"
+#include "exec/cpu-common.h"
+#include "exec/exec-all.h"
+
+void tb_flush(CPUState *cpu)
+{
+}
diff --git a/accel/tcg/Makefile.objs b/accel/tcg/Makefile.objs
index f173cd5..70cd474 100644
--- a/accel/tcg/Makefile.objs
+++ b/accel/tcg/Makefile.objs
@@ -1,3 +1,3 @@
obj-$(CONFIG_SOFTMMU) += tcg-all.o
obj-$(CONFIG_SOFTMMU) += cputlb.o
-obj-y += cpu-exec.o cpu-exec-common.o translate-all.o translate-common.o
+obj-y += cpu-exec.o cpu-exec-common.o translate-all.o
diff --git a/accel/tcg/cpu-exec-common.c b/accel/tcg/cpu-exec-common.c
index e81da27..5b4ae54 100644
--- a/accel/tcg/cpu-exec-common.c
+++ b/accel/tcg/cpu-exec-common.c
@@ -23,6 +23,8 @@
#include "exec/exec-all.h"
#include "exec/memory-internal.h"
+bool tcg_allowed;
+
/* exit the current TB, but without causing any exception to be raised */
void cpu_loop_exit_noexc(CPUState *cpu)
{
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
index dba9931..56dbb56 100644
--- a/accel/tcg/tcg-all.c
+++ b/accel/tcg/tcg-all.c
@@ -27,13 +27,44 @@
#include "sysemu/accel.h"
#include "sysemu/sysemu.h"
#include "qom/object.h"
+#include "qemu-common.h"
+#include "qom/cpu.h"
+#include "sysemu/cpus.h"
+#include "qemu/main-loop.h"
-int tcg_tb_size;
-static bool tcg_allowed = true;
+unsigned long tcg_tb_size;
+
+#ifndef CONFIG_USER_ONLY
+/* mask must never be zero, except for A20 change call */
+static void tcg_handle_interrupt(CPUState *cpu, int mask)
+{
+ int old_mask;
+ g_assert(qemu_mutex_iothread_locked());
+
+ old_mask = cpu->interrupt_request;
+ cpu->interrupt_request |= mask;
+
+ /*
+ * If called from iothread context, wake the target cpu in
+ * case its halted.
+ */
+ if (!qemu_cpu_is_self(cpu)) {
+ qemu_cpu_kick(cpu);
+ } else {
+ cpu->icount_decr.u16.high = -1;
+ if (use_icount &&
+ !cpu->can_do_io
+ && (mask & ~old_mask) != 0) {
+ cpu_abort(cpu, "Raised interrupt while not in I/O function");
+ }
+ }
+}
+#endif
static int tcg_init(MachineState *ms)
{
tcg_exec_init(tcg_tb_size * 1024 * 1024);
+ cpu_interrupt_handler = tcg_handle_interrupt;
return 0;
}
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 93fb923..dfb9f0d 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -112,9 +112,6 @@ typedef struct PageDesc {
#define V_L2_BITS 10
#define V_L2_SIZE (1 << V_L2_BITS)
-uintptr_t qemu_host_page_size;
-intptr_t qemu_host_page_mask;
-
/*
* L1 Mapping properties
*/
@@ -363,21 +360,6 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t retaddr)
return r;
}
-void page_size_init(void)
-{
- /* NOTE: we can always suppose that qemu_host_page_size >=
- TARGET_PAGE_SIZE */
- qemu_real_host_page_size = getpagesize();
- qemu_real_host_page_mask = -(intptr_t)qemu_real_host_page_size;
- if (qemu_host_page_size == 0) {
- qemu_host_page_size = qemu_real_host_page_size;
- }
- if (qemu_host_page_size < TARGET_PAGE_SIZE) {
- qemu_host_page_size = TARGET_PAGE_SIZE;
- }
- qemu_host_page_mask = -(intptr_t)qemu_host_page_size;
-}
-
static void page_init(void)
{
page_size_init();
@@ -802,6 +784,7 @@ static void tb_htable_init(void)
size. */
void tcg_exec_init(unsigned long tb_size)
{
+ tcg_allowed = true;
cpu_gen_init();
page_init();
tb_htable_init();
@@ -813,11 +796,6 @@ void tcg_exec_init(unsigned long tb_size)
#endif
}
-bool tcg_enabled(void)
-{
- return tcg_ctx.code_gen_buffer != NULL;
-}
-
/*
* Allocate a new translation block. Flush the translation buffer if
* too many translation blocks or too much generated code.
@@ -1873,6 +1851,11 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
tb_lock();
+ if (!tcg_enabled()) {
+ cpu_fprintf(f, "TCG not enabled\n");
+ return;
+ }
+
target_code_size = 0;
max_target_code_size = 0;
cross_page = 0;
@@ -2223,3 +2206,11 @@ int page_unprotect(target_ulong address, uintptr_t pc)
return 0;
}
#endif /* CONFIG_USER_ONLY */
+
+/* This is a wrapper for common code that can not use CONFIG_SOFTMMU */
+void tcg_flush_softmmu_tlb(CPUState *cs)
+{
+#ifdef CONFIG_SOFTMMU
+ tlb_flush(cs);
+#endif
+}
diff --git a/accel/tcg/translate-common.c b/accel/tcg/translate-common.c
deleted file mode 100644
index 40fe5a1..0000000
--- a/accel/tcg/translate-common.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Host code generation common components
- *
- * Copyright (c) 2015 Peter Crosthwaite <crosthwaite.peter@gmail.com>
- *
- * 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 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 <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qom/cpu.h"
-#include "sysemu/cpus.h"
-#include "qemu/main-loop.h"
-
-uintptr_t qemu_real_host_page_size;
-intptr_t qemu_real_host_page_mask;
-
-#ifndef CONFIG_USER_ONLY
-/* mask must never be zero, except for A20 change call */
-static void tcg_handle_interrupt(CPUState *cpu, int mask)
-{
- int old_mask;
- g_assert(qemu_mutex_iothread_locked());
-
- old_mask = cpu->interrupt_request;
- cpu->interrupt_request |= mask;
-
- /*
- * If called from iothread context, wake the target cpu in
- * case its halted.
- */
- if (!qemu_cpu_is_self(cpu)) {
- qemu_cpu_kick(cpu);
- } else {
- cpu->icount_decr.u16.high = -1;
- if (use_icount &&
- !cpu->can_do_io
- && (mask & ~old_mask) != 0) {
- cpu_abort(cpu, "Raised interrupt while not in I/O function");
- }
- }
-}
-
-CPUInterruptHandler cpu_interrupt_handler = tcg_handle_interrupt;
-#endif
diff --git a/block/nbd-client.c b/block/nbd-client.c
index 02e9281..208f907 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -345,14 +345,14 @@ int nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
void nbd_client_detach_aio_context(BlockDriverState *bs)
{
NBDClientSession *client = nbd_get_client_session(bs);
- qio_channel_detach_aio_context(QIO_CHANNEL(client->sioc));
+ qio_channel_detach_aio_context(QIO_CHANNEL(client->ioc));
}
void nbd_client_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
NBDClientSession *client = nbd_get_client_session(bs);
- qio_channel_attach_aio_context(QIO_CHANNEL(client->sioc), new_context);
+ qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), new_context);
aio_co_schedule(new_context, client->read_reply_co);
}
diff --git a/bootdevice.c b/bootdevice.c
index 33e3029..1141009 100644
--- a/bootdevice.c
+++ b/bootdevice.c
@@ -27,7 +27,7 @@
#include "sysemu/sysemu.h"
#include "qapi/visitor.h"
#include "qemu/error-report.h"
-#include "hw/hw.h"
+#include "sysemu/reset.h"
#include "hw/qdev-core.h"
typedef struct FWBootEntry FWBootEntry;
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 04f95dd..fa9c012 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -25,7 +25,6 @@
#include "qemu/config-file.h"
#include "qemu/path.h"
#include "qemu/help_option.h"
-/* For tb_lock */
#include "cpu.h"
#include "exec/exec-all.h"
#include "tcg.h"
diff --git a/configure b/configure
index c571ad1..806658c 100755
--- a/configure
+++ b/configure
@@ -40,14 +40,18 @@ printf " '%s'" "$0" "$@" >> config.log
echo >> config.log
echo "#" >> config.log
-error_exit() {
- echo
+print_error() {
+ (echo
echo "ERROR: $1"
while test -n "$2"; do
echo " $2"
shift
done
- echo
+ echo) >&2
+}
+
+error_exit() {
+ print_error "$@"
exit 1
}
@@ -163,6 +167,79 @@ have_backend () {
echo "$trace_backends" | grep "$1" >/dev/null
}
+glob() {
+ eval test -z '"${1#'"$2"'}"'
+}
+
+supported_hax_target() {
+ test "$hax" = "yes" || return 1
+ glob "$1" "*-softmmu" || return 1
+ case "${1%-softmmu}" in
+ i386|x86_64)
+ return 0
+ ;;
+ esac
+ return 1
+}
+
+supported_kvm_target() {
+ test "$kvm" = "yes" || return 1
+ glob "$1" "*-softmmu" || return 1
+ case "${1%-softmmu}:$cpu" in
+ arm:arm | aarch64:aarch64 | \
+ i386:i386 | i386:x86_64 | i386:x32 | \
+ x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \
+ mips:mips | mipsel:mips | \
+ ppc:ppc | ppcemb:ppc | ppc64:ppc | \
+ ppc:ppc64 | ppcemb:ppc64 | ppc64:ppc64 | \
+ s390x:s390x)
+ return 0
+ ;;
+ esac
+ return 1
+}
+
+supported_xen_target() {
+ test "$xen" = "yes" || return 1
+ glob "$1" "*-softmmu" || return 1
+ case "${1%-softmmu}:$cpu" in
+ arm:arm | aarch64:aarch64 | \
+ i386:i386 | i386:x86_64 | x86_64:i386 | x86_64:x86_64)
+ return 0
+ ;;
+ esac
+ return 1
+}
+
+supported_target() {
+ case "$1" in
+ *-softmmu)
+ ;;
+ *-linux-user)
+ if test "$linux" != "yes"; then
+ print_error "Target '$target' is only available on a Linux host"
+ return 1
+ fi
+ ;;
+ *-bsd-user)
+ if test "$bsd" != "yes"; then
+ print_error "Target '$target' is only available on a BSD host"
+ return 1
+ fi
+ ;;
+ *)
+ print_error "Invalid target name '$target'"
+ return 1
+ ;;
+ esac
+ test "$tcg" = "yes" && return 0
+ supported_kvm_target "$1" && return 0
+ supported_xen_target "$1" && return 0
+ supported_hax_target "$1" && return 0
+ print_error "TCG disabled, but hardware accelerator not available for '$target'"
+ return 1
+}
+
# default parameters
source_path=$(dirname "$0")
cpu=""
@@ -224,6 +301,7 @@ cap_ng=""
attr=""
libattr=""
xfs=""
+tcg="yes"
vhost_net="no"
vhost_scsi="no"
@@ -961,6 +1039,10 @@ for opt do
;;
--enable-cap-ng) cap_ng="yes"
;;
+ --disable-tcg) tcg="no"
+ ;;
+ --enable-tcg) tcg="yes"
+ ;;
--disable-spice) spice="no"
;;
--enable-spice) spice="yes"
@@ -1690,23 +1772,27 @@ if test "$solaris" = "yes" ; then
fi
if test -z "${target_list+xxx}" ; then
- target_list="$default_target_list"
+ for target in $default_target_list; do
+ supported_target $target 2>/dev/null && \
+ target_list="$target_list $target"
+ done
+ target_list="${target_list# }"
else
target_list=$(echo "$target_list" | sed -e 's/,/ /g')
+ for target in $target_list; do
+ # Check that we recognised the target name; this allows a more
+ # friendly error message than if we let it fall through.
+ case " $default_target_list " in
+ *" $target "*)
+ ;;
+ *)
+ error_exit "Unknown target name '$target'"
+ ;;
+ esac
+ supported_target $target || exit 1
+ done
fi
-# Check that we recognised the target name; this allows a more
-# friendly error message than if we let it fall through.
-for target in $target_list; do
- case " $default_target_list " in
- *" $target "*)
- ;;
- *)
- error_exit "Unknown target name '$target'"
- ;;
- esac
-done
-
# see if system emulation was really requested
case " $target_list " in
*"-softmmu "*) softmmu=yes
@@ -5119,7 +5205,6 @@ echo "module support $modules"
echo "host CPU $cpu"
echo "host big endian $bigendian"
echo "target list $target_list"
-echo "tcg debug enabled $debug_tcg"
echo "gprof enabled $gprof"
echo "sparse enabled $sparse"
echo "strip binaries $strip_opt"
@@ -5174,8 +5259,12 @@ echo "ATTR/XATTR support $attr"
echo "Install blobs $blobs"
echo "KVM support $kvm"
echo "HAX support $hax"
+echo "TCG support $tcg"
+if test "$tcg" = "yes" ; then
+ echo "TCG debug enabled $debug_tcg"
+ echo "TCG interpreter $tcg_interpreter"
+fi
echo "RDMA support $rdma"
-echo "TCG interpreter $tcg_interpreter"
echo "fdt support $fdt"
echo "preadv support $preadv"
echo "fdatasync $fdatasync"
@@ -5618,8 +5707,11 @@ fi
if test "$signalfd" = "yes" ; then
echo "CONFIG_SIGNALFD=y" >> $config_host_mak
fi
-if test "$tcg_interpreter" = "yes" ; then
- echo "CONFIG_TCG_INTERPRETER=y" >> $config_host_mak
+if test "$tcg" = "yes"; then
+ echo "CONFIG_TCG=y" >> $config_host_mak
+ if test "$tcg_interpreter" = "yes" ; then
+ echo "CONFIG_TCG_INTERPRETER=y" >> $config_host_mak
+ fi
fi
if test "$fdatasync" = "yes" ; then
echo "CONFIG_FDATASYNC=y" >> $config_host_mak
@@ -6006,16 +6098,10 @@ case "$target" in
target_softmmu="yes"
;;
${target_name}-linux-user)
- if test "$linux" != "yes" ; then
- error_exit "Target '$target' is only available on a Linux host"
- fi
target_user_only="yes"
target_linux_user="yes"
;;
${target_name}-bsd-user)
- if test "$bsd" != "yes" ; then
- error_exit "Target '$target' is only available on a BSD host"
- fi
target_user_only="yes"
target_bsd_user="yes"
;;
@@ -6178,46 +6264,22 @@ echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >> $config_target_mak
if [ "$HOST_VARIANT_DIR" != "" ]; then
echo "HOST_VARIANT_DIR=$HOST_VARIANT_DIR" >> $config_target_mak
fi
-case "$target_name" in
- i386|x86_64)
- if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
- echo "CONFIG_XEN=y" >> $config_target_mak
- if test "$xen_pci_passthrough" = yes; then
+
+if supported_xen_target $target; then
+ echo "CONFIG_XEN=y" >> $config_target_mak
+ if test "$xen_pci_passthrough" = yes; then
echo "CONFIG_XEN_PCI_PASSTHROUGH=y" >> "$config_target_mak"
- fi
fi
- ;;
- *)
-esac
-case "$target_name" in
- aarch64|arm|i386|x86_64|ppcemb|ppc|ppc64|s390x|mipsel|mips)
- # Make sure the target and host cpus are compatible
- if test "$kvm" = "yes" -a "$target_softmmu" = "yes" -a \
- \( "$target_name" = "$cpu" -o \
- \( "$target_name" = "ppcemb" -a "$cpu" = "ppc" \) -o \
- \( "$target_name" = "ppc64" -a "$cpu" = "ppc" \) -o \
- \( "$target_name" = "ppc" -a "$cpu" = "ppc64" \) -o \
- \( "$target_name" = "ppcemb" -a "$cpu" = "ppc64" \) -o \
- \( "$target_name" = "mipsel" -a "$cpu" = "mips" \) -o \
- \( "$target_name" = "x86_64" -a "$cpu" = "i386" \) -o \
- \( "$target_name" = "i386" -a "$cpu" = "x86_64" \) -o \
- \( "$target_name" = "x86_64" -a "$cpu" = "x32" \) -o \
- \( "$target_name" = "i386" -a "$cpu" = "x32" \) \) ; then
- echo "CONFIG_KVM=y" >> $config_target_mak
- if test "$vhost_net" = "yes" ; then
+fi
+if supported_kvm_target $target; then
+ echo "CONFIG_KVM=y" >> $config_target_mak
+ if test "$vhost_net" = "yes" ; then
echo "CONFIG_VHOST_NET=y" >> $config_target_mak
echo "CONFIG_VHOST_NET_TEST_$target_name=y" >> $config_host_mak
- fi
fi
-esac
-if test "$hax" = "yes" ; then
- if test "$target_softmmu" = "yes" ; then
- case "$target_name" in
- i386|x86_64)
- echo "CONFIG_HAX=y" >> $config_target_mak
- ;;
- esac
- fi
+fi
+if supported_hax_target $target; then
+ echo "CONFIG_HAX=y" >> $config_target_mak
fi
if test "$target_bigendian" = "yes" ; then
echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
diff --git a/exec.c b/exec.c
index 42ad1ea..a083ff8 100644
--- a/exec.c
+++ b/exec.c
@@ -118,6 +118,11 @@ __thread CPUState *current_cpu;
2 = Adaptive rate instruction counting. */
int use_icount;
+uintptr_t qemu_host_page_size;
+intptr_t qemu_host_page_mask;
+uintptr_t qemu_real_host_page_size;
+intptr_t qemu_real_host_page_mask;
+
bool set_preferred_target_page_bits(int bits)
{
/* The target page size is the lowest common denominator for all
@@ -2312,6 +2317,7 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
{
bool locked = false;
+ assert(tcg_enabled());
if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
locked = true;
tb_lock();
@@ -2370,6 +2376,7 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
CPUWatchpoint *wp;
uint32_t cpu_flags;
+ assert(tcg_enabled());
if (cpu->watchpoint_hit) {
/* We re-entered the check after replacing the TB. Now raise
* the debug interrupt so that is will trigger after the
@@ -2815,6 +2822,7 @@ static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr,
cpu_physical_memory_range_includes_clean(addr, length, dirty_log_mask);
}
if (dirty_log_mask & (1 << DIRTY_MEMORY_CODE)) {
+ assert(tcg_enabled());
tb_lock();
tb_invalidate_phys_range(addr, addr + length);
tb_unlock();
@@ -3590,3 +3598,18 @@ err:
}
#endif
+
+void page_size_init(void)
+{
+ /* NOTE: we can always suppose that qemu_host_page_size >=
+ TARGET_PAGE_SIZE */
+ qemu_real_host_page_size = getpagesize();
+ qemu_real_host_page_mask = -(intptr_t)qemu_real_host_page_size;
+ if (qemu_host_page_size == 0) {
+ qemu_host_page_size = qemu_real_host_page_size;
+ }
+ if (qemu_host_page_size < TARGET_PAGE_SIZE) {
+ qemu_host_page_size = TARGET_PAGE_SIZE;
+ }
+ qemu_host_page_mask = -(intptr_t)qemu_host_page_size;
+}
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index ba98e58..07500ef 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -261,6 +261,7 @@ STEXI
Show memory tree.
ETEXI
+#if defined(CONFIG_TCG)
{
.name = "jit",
.args_type = "",
@@ -268,6 +269,7 @@ ETEXI
.help = "show dynamic compiler info",
.cmd = hmp_info_jit,
},
+#endif
STEXI
@item info jit
@@ -275,6 +277,7 @@ STEXI
Show dynamic compiler info.
ETEXI
+#if defined(CONFIG_TCG)
{
.name = "opcount",
.args_type = "",
@@ -282,6 +285,7 @@ ETEXI
.help = "show dynamic compiler opcode counters",
.cmd = hmp_info_opcount,
},
+#endif
STEXI
@item info opcount
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 5c279bb..c5d8646 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -33,7 +33,6 @@
#include "sysemu/sysemu.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/tco.h"
-#include "sysemu/kvm.h"
#include "exec/address-spaces.h"
#include "hw/i386/ich9.h"
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index 82a4955..0d9ef77 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -410,7 +410,8 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
handlers = &s->rom_state.mp;
}
- if (!kvm_enabled()) {
+ if (tcg_enabled()) {
+ cpu_restore_state(cs, cs->mem_io_pc);
cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
&current_flags);
/* Account this instruction, because we will exit the tb.
@@ -456,7 +457,7 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
resume_all_vcpus();
- if (!kvm_enabled()) {
+ if (tcg_enabled()) {
/* Both tb_lock and iothread_mutex will be reset when
* longjmps back into the cpu_exec loop. */
tb_lock();
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 1523ef3..8f696b7 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -36,6 +36,7 @@
#include "hw/timer/mc146818rtc.h"
#include "hw/xen/xen.h"
#include "sysemu/kvm.h"
+#include "kvm_i386.h"
#include "hw/kvm/clock.h"
#include "hw/pci-host/q35.h"
#include "exec/address-spaces.h"
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 08a79c3..44e0e79 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -6,6 +6,7 @@ common-obj-$(CONFIG_ISA_DEBUG) += debugexit.o
common-obj-$(CONFIG_SGA) += sga.o
common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o
+common-obj-$(CONFIG_EDU) += edu.o
common-obj-y += unimp.o
@@ -53,7 +54,6 @@ obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
obj-$(CONFIG_MIPS_ITU) += mips_itu.o
obj-$(CONFIG_PVPANIC) += pvpanic.o
-obj-$(CONFIG_EDU) += edu.o
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
obj-$(CONFIG_AUX) += auxbus.o
obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index f46f06d..d076fe7 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -43,12 +43,13 @@ static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
void virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq, VirtIOSCSIReq *req)
{
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
const size_t zero_skip =
offsetof(VirtIOSCSIReq, resp_iov) + sizeof(req->resp_iov);
req->vq = vq;
req->dev = s;
- qemu_sglist_init(&req->qsgl, DEVICE(s), 8, &address_space_memory);
+ qemu_sglist_init(&req->qsgl, DEVICE(s), 8, vdev->dma_as);
qemu_iovec_init(&req->resp_iov, 1);
memset((uint8_t *)req + zero_skip, 0, sizeof(*req) - zero_skip);
}
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 4d45a72..74341b1 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -28,6 +28,8 @@ void qemu_init_cpu_list(void);
void cpu_list_lock(void);
void cpu_list_unlock(void);
+void tcg_flush_softmmu_tlb(CPUState *cs);
+
#if !defined(CONFIG_USER_ONLY)
enum device_endian {
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index 5f4e303..bc8e7f8 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -25,7 +25,9 @@
#include "qemu/host-utils.h"
#include "qemu/queue.h"
+#ifdef CONFIG_TCG
#include "tcg-target.h"
+#endif
#ifndef CONFIG_USER_ONLY
#include "exec/hwaddr.h"
#endif
@@ -54,7 +56,7 @@ typedef uint64_t target_ulong;
#error TARGET_LONG_SIZE undefined
#endif
-#if !defined(CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
/* use a fully associative victim tlb of 8 entries */
#define CPU_VTLB_SIZE 8
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 724ec73..8096d64 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -82,6 +82,9 @@ void cpu_reloading_memory_map(void);
* Note that with KVM only one address space is supported.
*/
void cpu_address_space_init(CPUState *cpu, AddressSpace *as, int asidx);
+#endif
+
+#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
/* cputlb.c */
/**
* tlb_flush_page:
@@ -467,6 +470,10 @@ extern uintptr_t tci_tb_ptr;
smaller than 4 bytes, so we don't worry about special-casing this. */
#define GETPC_ADJ 2
+void tb_lock(void);
+void tb_unlock(void);
+void tb_lock_reset(void);
+
#if !defined(CONFIG_USER_ONLY)
struct MemoryRegion *iotlb_to_region(CPUState *cpu,
diff --git a/include/exec/poison.h b/include/exec/poison.h
index 5ffed4d..41cd2eb 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -7,13 +7,16 @@
#pragma GCC poison TARGET_I386
#pragma GCC poison TARGET_X86_64
+#pragma GCC poison TARGET_AARCH64
#pragma GCC poison TARGET_ALPHA
#pragma GCC poison TARGET_ARM
#pragma GCC poison TARGET_CRIS
+#pragma GCC poison TARGET_HPPA
#pragma GCC poison TARGET_LM32
#pragma GCC poison TARGET_M68K
#pragma GCC poison TARGET_MICROBLAZE
#pragma GCC poison TARGET_MIPS
+#pragma GCC poison TARGET_ABI_MIPSN32
#pragma GCC poison TARGET_ABI_MIPSO32
#pragma GCC poison TARGET_MIPS64
#pragma GCC poison TARGET_ABI_MIPSN64
@@ -28,10 +31,12 @@
#pragma GCC poison TARGET_SH4
#pragma GCC poison TARGET_SPARC
#pragma GCC poison TARGET_SPARC64
+#pragma GCC poison TARGET_TILEGX
#pragma GCC poison TARGET_TRICORE
#pragma GCC poison TARGET_UNICORE32
#pragma GCC poison TARGET_XTENSA
+#pragma GCC poison TARGET_HAS_BFLT
#pragma GCC poison TARGET_NAME
#pragma GCC poison TARGET_SUPPORTS_MTTCG
#pragma GCC poison TARGET_WORDS_BIGENDIAN
@@ -65,6 +70,7 @@
#pragma GCC poison CONFIG_ARM_A64_DIS
#pragma GCC poison CONFIG_ARM_DIS
#pragma GCC poison CONFIG_CRIS_DIS
+#pragma GCC poison CONFIG_HPPA_DIS
#pragma GCC poison CONFIG_I386_DIS
#pragma GCC poison CONFIG_LM32_DIS
#pragma GCC poison CONFIG_M68K_DIS
@@ -80,6 +86,8 @@
#pragma GCC poison CONFIG_LINUX_USER
#pragma GCC poison CONFIG_VHOST_NET
+#pragma GCC poison CONFIG_KVM
+#pragma GCC poison CONFIG_SOFTMMU
#endif
#endif
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 233216a..f48d167 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -20,19 +20,6 @@
#define HPET_INTCAP "hpet-intcap"
-#ifdef CONFIG_KVM
-#define kvm_pit_in_kernel() \
- (kvm_irqchip_in_kernel() && !kvm_irqchip_is_split())
-#define kvm_pic_in_kernel() \
- (kvm_irqchip_in_kernel() && !kvm_irqchip_is_split())
-#define kvm_ioapic_in_kernel() \
- (kvm_irqchip_in_kernel() && !kvm_irqchip_is_split())
-#else
-#define kvm_pit_in_kernel() 0
-#define kvm_pic_in_kernel() 0
-#define kvm_ioapic_in_kernel() 0
-#endif
-
/**
* PCMachineState:
* @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 387ef52..b5adbfa 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -76,8 +76,13 @@ int qemu_openpty_raw(int *aslave, char *pty_name);
sendto(sockfd, buf, len, flags, destaddr, addrlen)
#endif
+extern bool tcg_allowed;
void tcg_exec_init(unsigned long tb_size);
-bool tcg_enabled(void);
+#ifdef CONFIG_TCG
+#define tcg_enabled() (tcg_allowed)
+#else
+#define tcg_enabled() 0
+#endif
void cpu_exec_init_all(void);
void cpu_exec_step_atomic(CPUState *cpu);
diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
index d7e24af..6b4b60b 100644
--- a/include/qemu/main-loop.h
+++ b/include/qemu/main-loop.h
@@ -79,7 +79,7 @@ int qemu_init_main_loop(Error **errp);
*
* @nonblocking: Whether the caller should block until an event occurs.
*/
-int main_loop_wait(int nonblocking);
+void main_loop_wait(int nonblocking);
/**
* qemu_get_aio_context: Return the main loop's AioContext
diff --git a/include/qemu/thread-posix.h b/include/qemu/thread-posix.h
index 09d1e15..e5e3a0f 100644
--- a/include/qemu/thread-posix.h
+++ b/include/qemu/thread-posix.h
@@ -12,10 +12,12 @@ typedef QemuMutex QemuRecMutex;
struct QemuMutex {
pthread_mutex_t lock;
+ bool initialized;
};
struct QemuCond {
pthread_cond_t cond;
+ bool initialized;
};
struct QemuSemaphore {
@@ -26,6 +28,7 @@ struct QemuSemaphore {
#else
sem_t sem;
#endif
+ bool initialized;
};
struct QemuEvent {
@@ -34,6 +37,7 @@ struct QemuEvent {
pthread_cond_t cond;
#endif
unsigned value;
+ bool initialized;
};
struct QemuThread {
diff --git a/include/qemu/thread-win32.h b/include/qemu/thread-win32.h
index 4c4a261..3a05e3b 100644
--- a/include/qemu/thread-win32.h
+++ b/include/qemu/thread-win32.h
@@ -5,11 +5,13 @@
struct QemuMutex {
SRWLOCK lock;
+ bool initialized;
};
typedef struct QemuRecMutex QemuRecMutex;
struct QemuRecMutex {
CRITICAL_SECTION lock;
+ bool initialized;
};
void qemu_rec_mutex_destroy(QemuRecMutex *mutex);
@@ -19,15 +21,18 @@ void qemu_rec_mutex_unlock(QemuRecMutex *mutex);
struct QemuCond {
CONDITION_VARIABLE var;
+ bool initialized;
};
struct QemuSemaphore {
HANDLE sema;
+ bool initialized;
};
struct QemuEvent {
int value;
HANDLE event;
+ bool initialized;
};
typedef struct QemuThreadData QemuThreadData;
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 2fe7cff..7bfd50c 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -369,7 +369,6 @@ struct CPUState {
vaddr mem_io_vaddr;
int kvm_fd;
- bool kvm_vcpu_dirty;
struct KVMState *kvm_state;
struct kvm_run *kvm_run;
@@ -386,6 +385,9 @@ struct CPUState {
uint32_t can_do_io;
int32_t exception_index; /* used by m68k TCG */
+ /* shared by kvm, hax and hvf */
+ bool vcpu_dirty;
+
/* Used to keep track of an outstanding cpu throttle thread for migration
* autoconverge
*/
@@ -400,7 +402,6 @@ struct CPUState {
icount_decr_u16 u16;
} icount_decr;
- bool hax_vcpu_dirty;
struct hax_vcpu_state *hax_vcpu;
/* The pending_tlb_flush flag is set and cleared atomically to
@@ -816,6 +817,8 @@ void cpu_interrupt(CPUState *cpu, int mask);
#endif /* USER_ONLY */
+#ifdef NEED_CPU_H
+
#ifdef CONFIG_SOFTMMU
static inline void cpu_unassigned_access(CPUState *cpu, hwaddr addr,
bool is_write, bool is_exec,
@@ -838,6 +841,8 @@ static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
}
#endif
+#endif /* NEED_CPU_H */
+
/**
* cpu_set_pc:
* @cpu: The CPU to set the program counter for.
@@ -1014,6 +1019,8 @@ void cpu_exec_initfn(CPUState *cpu);
void cpu_exec_realizefn(CPUState *cpu, Error **errp);
void cpu_exec_unrealizefn(CPUState *cpu);
+#ifdef NEED_CPU_H
+
#ifdef CONFIG_SOFTMMU
extern const struct VMStateDescription vmstate_cpu_common;
#else
@@ -1028,6 +1035,8 @@ extern const struct VMStateDescription vmstate_cpu_common;
.offset = 0, \
}
+#endif /* NEED_CPU_H */
+
#define UNASSIGNED_CPU_INDEX -1
#endif
diff --git a/include/sysemu/accel.h b/include/sysemu/accel.h
index ecc5c84..5a632ce 100644
--- a/include/sysemu/accel.h
+++ b/include/sysemu/accel.h
@@ -63,7 +63,7 @@ typedef struct AccelClass {
#define ACCEL_GET_CLASS(obj) \
OBJECT_GET_CLASS(AccelClass, (obj), TYPE_ACCEL)
-extern int tcg_tb_size;
+extern unsigned long tcg_tb_size;
void configure_accelerator(MachineState *ms);
/* Register accelerator specific global properties */
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 1e91613..052e11f 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -19,26 +19,18 @@
#include "exec/memattrs.h"
#include "hw/irq.h"
-#ifdef CONFIG_KVM
-#include <linux/kvm.h>
-#include <linux/kvm_para.h>
+#ifdef NEED_CPU_H
+# ifdef CONFIG_KVM
+# include <linux/kvm.h>
+# include <linux/kvm_para.h>
+# define CONFIG_KVM_IS_POSSIBLE
+# endif
#else
-/* These constants must never be used at runtime if kvm_enabled() is false.
- * They exist so we don't need #ifdefs around KVM-specific code that already
- * checks kvm_enabled() properly.
- */
-#define KVM_CPUID_SIGNATURE 0
-#define KVM_CPUID_FEATURES 0
-#define KVM_FEATURE_CLOCKSOURCE 0
-#define KVM_FEATURE_NOP_IO_DELAY 0
-#define KVM_FEATURE_MMU_OP 0
-#define KVM_FEATURE_CLOCKSOURCE2 0
-#define KVM_FEATURE_ASYNC_PF 0
-#define KVM_FEATURE_STEAL_TIME 0
-#define KVM_FEATURE_PV_EOI 0
-#define KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 0
+# define CONFIG_KVM_IS_POSSIBLE
#endif
+#ifdef CONFIG_KVM_IS_POSSIBLE
+
extern bool kvm_allowed;
extern bool kvm_kernel_irqchip;
extern bool kvm_split_irqchip;
@@ -55,7 +47,6 @@ extern bool kvm_direct_msi_allowed;
extern bool kvm_ioeventfd_any_length_allowed;
extern bool kvm_msi_use_devid;
-#if defined CONFIG_KVM || !defined NEED_CPU_H
#define kvm_enabled() (kvm_allowed)
/**
* kvm_irqchip_in_kernel:
@@ -178,6 +169,7 @@ extern bool kvm_msi_use_devid;
#define kvm_msi_devid_required() (kvm_msi_use_devid)
#else
+
#define kvm_enabled() (0)
#define kvm_irqchip_in_kernel() (false)
#define kvm_irqchip_is_split() (false)
@@ -193,7 +185,8 @@ extern bool kvm_msi_use_devid;
#define kvm_direct_msi_enabled() (false)
#define kvm_ioeventfd_any_length_enabled() (false)
#define kvm_msi_devid_required() (false)
-#endif
+
+#endif /* CONFIG_KVM_IS_POSSIBLE */
struct kvm_run;
struct kvm_lapic_state;
diff --git a/monitor.c b/monitor.c
index 40318764..d8ac20f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1098,6 +1098,7 @@ static void hmp_info_registers(Monitor *mon, const QDict *qdict)
}
}
+#ifdef CONFIG_TCG
static void hmp_info_jit(Monitor *mon, const QDict *qdict)
{
if (!tcg_enabled()) {
@@ -1113,6 +1114,7 @@ static void hmp_info_opcount(Monitor *mon, const QDict *qdict)
{
dump_opcount_info((FILE *)mon, monitor_fprintf);
}
+#endif
static void hmp_info_history(Monitor *mon, const QDict *qdict)
{
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 21079fd..d2986cb 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -386,11 +386,9 @@ CPU registers by prefixing them with @emph{$}.
@node disk_images
@section Disk Images
-Since version 0.6.1, QEMU supports many disk image formats, including
-growable disk images (their size increase as non empty sectors are
-written), compressed and encrypted disk images. Version 0.8.3 added
-the new qcow2 disk image format which is essential to support VM
-snapshots.
+QEMU supports many disk image formats, including growable disk images
+(their size increase as non empty sectors are written), compressed and
+encrypted disk images.
@menu
* disk_images_quickstart:: Quick start for disk image creation
@@ -2566,6 +2564,8 @@ so should only be used with trusted guest OS.
@end table
+@c man end
+
@node ColdFire System emulator
@section ColdFire System emulator
@cindex system emulation (ColdFire)
@@ -2610,6 +2610,8 @@ so should only be used with trusted guest OS.
@end table
+@c man end
+
@node Cris System emulator
@section Cris System emulator
@cindex system emulation (Cris)
@@ -2682,6 +2684,8 @@ so should only be used with trusted guest OS.
@end table
+@c man end
+
@node QEMU Guest Agent
@chapter QEMU Guest Agent invocation
diff --git a/qom/cpu.c b/qom/cpu.c
index 585419b..8757f03 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -26,11 +26,14 @@
#include "qemu/notify.h"
#include "qemu/log.h"
#include "exec/log.h"
+#include "exec/cpu-common.h"
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
#include "hw/qdev-properties.h"
#include "trace-root.h"
+CPUInterruptHandler cpu_interrupt_handler;
+
bool cpu_exists(int64_t id)
{
CPUState *cpu;
@@ -293,9 +296,7 @@ static void cpu_common_reset(CPUState *cpu)
if (tcg_enabled()) {
cpu_tb_jmp_cache_clear(cpu);
-#ifdef CONFIG_SOFTMMU
- tlb_flush(cpu, 0);
-#endif
+ tcg_flush_softmmu_tlb(cpu);
}
}
@@ -418,6 +419,17 @@ static vaddr cpu_adjust_watchpoint_address(CPUState *cpu, vaddr addr, int len)
return addr;
}
+static void generic_handle_interrupt(CPUState *cpu, int mask)
+{
+ cpu->interrupt_request |= mask;
+
+ if (!qemu_cpu_is_self(cpu)) {
+ qemu_cpu_kick(cpu);
+ }
+}
+
+CPUInterruptHandler cpu_interrupt_handler = generic_handle_interrupt;
+
static void cpu_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 45027b9..73efc92 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2473,6 +2473,10 @@ sub process {
if ($line =~ /\b(strto[^kd].*?)\s*\(/) {
ERROR("consider using qemu_$1 in preference to $1\n" . $herecurr);
}
+# recommend sigaction over signal for portability, when establishing a handler
+ if ($line =~ /\bsignal\s*\(/ && !($line =~ /SIG_(?:IGN|DFL)/)) {
+ ERROR("use sigaction to establish signal handlers; signal is not portable\n" . $herecurr);
+ }
# check for module_init(), use category-specific init macros explicitly please
if ($line =~ /^module_init\s*\(/) {
ERROR("please use block_init(), type_init() etc. instead of module_init()\n" . $herecurr);
diff --git a/target/i386/Makefile.objs b/target/i386/Makefile.objs
index 4fcb7f3..6a26e9d 100644
--- a/target/i386/Makefile.objs
+++ b/target/i386/Makefile.objs
@@ -1,7 +1,8 @@
-obj-y += translate.o helper.o cpu.o bpt_helper.o
-obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o
-obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o mpx_helper.o
-obj-y += gdbstub.o
+obj-y += helper.o cpu.o gdbstub.o xsave_helper.o
+obj-$(CONFIG_TCG) += translate.o
+obj-$(CONFIG_TCG) += bpt_helper.o cc_helper.o excp_helper.o fpu_helper.o
+obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o mpx_helper.o
+obj-$(CONFIG_TCG) += seg_helper.o smm_helper.o svm_helper.o
obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o monitor.o
obj-$(CONFIG_KVM) += kvm.o hyperv.o
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 642519a..c571772 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -4040,8 +4040,10 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->class_by_name = x86_cpu_class_by_name;
cc->parse_features = x86_cpu_parse_featurestr;
cc->has_work = x86_cpu_has_work;
+#ifdef CONFIG_TCG
cc->do_interrupt = x86_cpu_do_interrupt;
cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
+#endif
cc->dump_state = x86_cpu_dump_state;
cc->get_crash_info = x86_cpu_get_crash_info;
cc->set_pc = x86_cpu_set_pc;
@@ -4070,7 +4072,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->gdb_core_xml_file = "i386-32bit.xml";
cc->gdb_num_core_regs = 41;
#endif
-#ifndef CONFIG_USER_ONLY
+#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
cc->debug_excp_handler = breakpoint_handler;
#endif
cc->cpu_exec_enter = x86_cpu_exec_enter;
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index de0551f..7a228af 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -52,7 +52,9 @@
#include "exec/cpu-defs.h"
+#ifdef CONFIG_TCG
#include "fpu/softfloat.h"
+#endif
#define R_EAX 0
#define R_ECX 1
@@ -1418,8 +1420,6 @@ int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
/* op_helper.c */
/* used for debug or cpu save/restore */
-void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f);
-floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper);
/* cpu-exec.c */
/* the following helpers are only usable in user mode simulation as
@@ -1596,11 +1596,14 @@ void QEMU_NORETURN raise_interrupt(CPUX86State *nenv, int intno, int is_int,
/* cc_helper.c */
extern const uint8_t parity_table[256];
uint32_t cpu_cc_compute_all(CPUX86State *env1, int op);
-void update_fp_status(CPUX86State *env);
static inline uint32_t cpu_compute_eflags(CPUX86State *env)
{
- return env->eflags | cpu_cc_compute_all(env, CC_OP) | (env->df & DF_MASK);
+ uint32_t eflags = env->eflags;
+ if (tcg_enabled()) {
+ eflags |= cpu_cc_compute_all(env, CC_OP) | (env->df & DF_MASK);
+ }
+ return eflags;
}
/* NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS
@@ -1645,8 +1648,24 @@ static inline int32_t x86_get_a20_mask(CPUX86State *env)
}
/* fpu_helper.c */
-void cpu_set_mxcsr(CPUX86State *env, uint32_t val);
-void cpu_set_fpuc(CPUX86State *env, uint16_t val);
+void update_fp_status(CPUX86State *env);
+void update_mxcsr_status(CPUX86State *env);
+
+static inline void cpu_set_mxcsr(CPUX86State *env, uint32_t mxcsr)
+{
+ env->mxcsr = mxcsr;
+ if (tcg_enabled()) {
+ update_mxcsr_status(env);
+ }
+}
+
+static inline void cpu_set_fpuc(CPUX86State *env, uint16_t fpuc)
+{
+ env->fpuc = fpuc;
+ if (tcg_enabled()) {
+ update_fp_status(env);
+ }
+}
/* mem_helper.c */
void helper_lock_init(void);
@@ -1697,4 +1716,6 @@ void x86_cpu_dump_local_apic_state(CPUState *cs, FILE *f,
/* cpu.c */
bool cpu_is_bsp(X86CPU *cpu);
+void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf);
+void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf);
#endif /* I386_CPU_H */
diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c
index b769772..cef4449 100644
--- a/target/i386/excp_helper.c
+++ b/target/i386/excp_helper.c
@@ -136,3 +136,346 @@ void raise_exception_ra(CPUX86State *env, int exception_index, uintptr_t retaddr
{
raise_interrupt2(env, exception_index, 0, 0, 0, retaddr);
}
+
+#if defined(CONFIG_USER_ONLY)
+int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
+ int is_write, int mmu_idx)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
+ /* user mode only emulation */
+ is_write &= 1;
+ env->cr[2] = addr;
+ env->error_code = (is_write << PG_ERROR_W_BIT);
+ env->error_code |= PG_ERROR_U_MASK;
+ cs->exception_index = EXCP0E_PAGE;
+ env->exception_is_int = 0;
+ env->exception_next_eip = -1;
+ return 1;
+}
+
+#else
+
+/* return value:
+ * -1 = cannot handle fault
+ * 0 = nothing more to do
+ * 1 = generate PF fault
+ */
+int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
+ int is_write1, int mmu_idx)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+ uint64_t ptep, pte;
+ int32_t a20_mask;
+ target_ulong pde_addr, pte_addr;
+ int error_code = 0;
+ int is_dirty, prot, page_size, is_write, is_user;
+ hwaddr paddr;
+ uint64_t rsvd_mask = PG_HI_RSVD_MASK;
+ uint32_t page_offset;
+ target_ulong vaddr;
+
+ is_user = mmu_idx == MMU_USER_IDX;
+#if defined(DEBUG_MMU)
+ printf("MMU fault: addr=%" VADDR_PRIx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
+ addr, is_write1, is_user, env->eip);
+#endif
+ is_write = is_write1 & 1;
+
+ a20_mask = x86_get_a20_mask(env);
+ if (!(env->cr[0] & CR0_PG_MASK)) {
+ pte = addr;
+#ifdef TARGET_X86_64
+ if (!(env->hflags & HF_LMA_MASK)) {
+ /* Without long mode we can only address 32bits in real mode */
+ pte = (uint32_t)pte;
+ }
+#endif
+ prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ page_size = 4096;
+ goto do_mapping;
+ }
+
+ if (!(env->efer & MSR_EFER_NXE)) {
+ rsvd_mask |= PG_NX_MASK;
+ }
+
+ if (env->cr[4] & CR4_PAE_MASK) {
+ uint64_t pde, pdpe;
+ target_ulong pdpe_addr;
+
+#ifdef TARGET_X86_64
+ if (env->hflags & HF_LMA_MASK) {
+ bool la57 = env->cr[4] & CR4_LA57_MASK;
+ uint64_t pml5e_addr, pml5e;
+ uint64_t pml4e_addr, pml4e;
+ int32_t sext;
+
+ /* test virtual address sign extension */
+ sext = la57 ? (int64_t)addr >> 56 : (int64_t)addr >> 47;
+ if (sext != 0 && sext != -1) {
+ env->error_code = 0;
+ cs->exception_index = EXCP0D_GPF;
+ return 1;
+ }
+
+ if (la57) {
+ pml5e_addr = ((env->cr[3] & ~0xfff) +
+ (((addr >> 48) & 0x1ff) << 3)) & a20_mask;
+ pml5e = x86_ldq_phys(cs, pml5e_addr);
+ if (!(pml5e & PG_PRESENT_MASK)) {
+ goto do_fault;
+ }
+ if (pml5e & (rsvd_mask | PG_PSE_MASK)) {
+ goto do_fault_rsvd;
+ }
+ if (!(pml5e & PG_ACCESSED_MASK)) {
+ pml5e |= PG_ACCESSED_MASK;
+ x86_stl_phys_notdirty(cs, pml5e_addr, pml5e);
+ }
+ ptep = pml5e ^ PG_NX_MASK;
+ } else {
+ pml5e = env->cr[3];
+ ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
+ }
+
+ pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
+ (((addr >> 39) & 0x1ff) << 3)) & a20_mask;
+ pml4e = x86_ldq_phys(cs, pml4e_addr);
+ if (!(pml4e & PG_PRESENT_MASK)) {
+ goto do_fault;
+ }
+ if (pml4e & (rsvd_mask | PG_PSE_MASK)) {
+ goto do_fault_rsvd;
+ }
+ if (!(pml4e & PG_ACCESSED_MASK)) {
+ pml4e |= PG_ACCESSED_MASK;
+ x86_stl_phys_notdirty(cs, pml4e_addr, pml4e);
+ }
+ ptep &= pml4e ^ PG_NX_MASK;
+ pdpe_addr = ((pml4e & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
+ a20_mask;
+ pdpe = x86_ldq_phys(cs, pdpe_addr);
+ if (!(pdpe & PG_PRESENT_MASK)) {
+ goto do_fault;
+ }
+ if (pdpe & rsvd_mask) {
+ goto do_fault_rsvd;
+ }
+ ptep &= pdpe ^ PG_NX_MASK;
+ if (!(pdpe & PG_ACCESSED_MASK)) {
+ pdpe |= PG_ACCESSED_MASK;
+ x86_stl_phys_notdirty(cs, pdpe_addr, pdpe);
+ }
+ if (pdpe & PG_PSE_MASK) {
+ /* 1 GB page */
+ page_size = 1024 * 1024 * 1024;
+ pte_addr = pdpe_addr;
+ pte = pdpe;
+ goto do_check_protect;
+ }
+ } else
+#endif
+ {
+ /* XXX: load them when cr3 is loaded ? */
+ pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
+ a20_mask;
+ pdpe = x86_ldq_phys(cs, pdpe_addr);
+ if (!(pdpe & PG_PRESENT_MASK)) {
+ goto do_fault;
+ }
+ rsvd_mask |= PG_HI_USER_MASK;
+ if (pdpe & (rsvd_mask | PG_NX_MASK)) {
+ goto do_fault_rsvd;
+ }
+ ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
+ }
+
+ pde_addr = ((pdpe & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
+ a20_mask;
+ pde = x86_ldq_phys(cs, pde_addr);
+ if (!(pde & PG_PRESENT_MASK)) {
+ goto do_fault;
+ }
+ if (pde & rsvd_mask) {
+ goto do_fault_rsvd;
+ }
+ ptep &= pde ^ PG_NX_MASK;
+ if (pde & PG_PSE_MASK) {
+ /* 2 MB page */
+ page_size = 2048 * 1024;
+ pte_addr = pde_addr;
+ pte = pde;
+ goto do_check_protect;
+ }
+ /* 4 KB page */
+ if (!(pde & PG_ACCESSED_MASK)) {
+ pde |= PG_ACCESSED_MASK;
+ x86_stl_phys_notdirty(cs, pde_addr, pde);
+ }
+ pte_addr = ((pde & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
+ a20_mask;
+ pte = x86_ldq_phys(cs, pte_addr);
+ if (!(pte & PG_PRESENT_MASK)) {
+ goto do_fault;
+ }
+ if (pte & rsvd_mask) {
+ goto do_fault_rsvd;
+ }
+ /* combine pde and pte nx, user and rw protections */
+ ptep &= pte ^ PG_NX_MASK;
+ page_size = 4096;
+ } else {
+ uint32_t pde;
+
+ /* page directory entry */
+ pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
+ a20_mask;
+ pde = x86_ldl_phys(cs, pde_addr);
+ if (!(pde & PG_PRESENT_MASK)) {
+ goto do_fault;
+ }
+ ptep = pde | PG_NX_MASK;
+
+ /* if PSE bit is set, then we use a 4MB page */
+ if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
+ page_size = 4096 * 1024;
+ pte_addr = pde_addr;
+
+ /* Bits 20-13 provide bits 39-32 of the address, bit 21 is reserved.
+ * Leave bits 20-13 in place for setting accessed/dirty bits below.
+ */
+ pte = pde | ((pde & 0x1fe000LL) << (32 - 13));
+ rsvd_mask = 0x200000;
+ goto do_check_protect_pse36;
+ }
+
+ if (!(pde & PG_ACCESSED_MASK)) {
+ pde |= PG_ACCESSED_MASK;
+ x86_stl_phys_notdirty(cs, pde_addr, pde);
+ }
+
+ /* page directory entry */
+ pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
+ a20_mask;
+ pte = x86_ldl_phys(cs, pte_addr);
+ if (!(pte & PG_PRESENT_MASK)) {
+ goto do_fault;
+ }
+ /* combine pde and pte user and rw protections */
+ ptep &= pte | PG_NX_MASK;
+ page_size = 4096;
+ rsvd_mask = 0;
+ }
+
+do_check_protect:
+ rsvd_mask |= (page_size - 1) & PG_ADDRESS_MASK & ~PG_PSE_PAT_MASK;
+do_check_protect_pse36:
+ if (pte & rsvd_mask) {
+ goto do_fault_rsvd;
+ }
+ ptep ^= PG_NX_MASK;
+
+ /* can the page can be put in the TLB? prot will tell us */
+ if (is_user && !(ptep & PG_USER_MASK)) {
+ goto do_fault_protect;
+ }
+
+ prot = 0;
+ if (mmu_idx != MMU_KSMAP_IDX || !(ptep & PG_USER_MASK)) {
+ prot |= PAGE_READ;
+ if ((ptep & PG_RW_MASK) || (!is_user && !(env->cr[0] & CR0_WP_MASK))) {
+ prot |= PAGE_WRITE;
+ }
+ }
+ if (!(ptep & PG_NX_MASK) &&
+ (mmu_idx == MMU_USER_IDX ||
+ !((env->cr[4] & CR4_SMEP_MASK) && (ptep & PG_USER_MASK)))) {
+ prot |= PAGE_EXEC;
+ }
+ if ((env->cr[4] & CR4_PKE_MASK) && (env->hflags & HF_LMA_MASK) &&
+ (ptep & PG_USER_MASK) && env->pkru) {
+ uint32_t pk = (pte & PG_PKRU_MASK) >> PG_PKRU_BIT;
+ uint32_t pkru_ad = (env->pkru >> pk * 2) & 1;
+ uint32_t pkru_wd = (env->pkru >> pk * 2) & 2;
+ uint32_t pkru_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+
+ if (pkru_ad) {
+ pkru_prot &= ~(PAGE_READ | PAGE_WRITE);
+ } else if (pkru_wd && (is_user || env->cr[0] & CR0_WP_MASK)) {
+ pkru_prot &= ~PAGE_WRITE;
+ }
+
+ prot &= pkru_prot;
+ if ((pkru_prot & (1 << is_write1)) == 0) {
+ assert(is_write1 != 2);
+ error_code |= PG_ERROR_PK_MASK;
+ goto do_fault_protect;
+ }
+ }
+
+ if ((prot & (1 << is_write1)) == 0) {
+ goto do_fault_protect;
+ }
+
+ /* yes, it can! */
+ is_dirty = is_write && !(pte & PG_DIRTY_MASK);
+ if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
+ pte |= PG_ACCESSED_MASK;
+ if (is_dirty) {
+ pte |= PG_DIRTY_MASK;
+ }
+ x86_stl_phys_notdirty(cs, pte_addr, pte);
+ }
+
+ if (!(pte & PG_DIRTY_MASK)) {
+ /* only set write access if already dirty... otherwise wait
+ for dirty access */
+ assert(!is_write);
+ prot &= ~PAGE_WRITE;
+ }
+
+ do_mapping:
+ pte = pte & a20_mask;
+
+ /* align to page_size */
+ pte &= PG_ADDRESS_MASK & ~(page_size - 1);
+
+ /* Even if 4MB pages, we map only one 4KB page in the cache to
+ avoid filling it too fast */
+ vaddr = addr & TARGET_PAGE_MASK;
+ page_offset = vaddr & (page_size - 1);
+ paddr = pte + page_offset;
+
+ assert(prot & (1 << is_write1));
+ tlb_set_page_with_attrs(cs, vaddr, paddr, cpu_get_mem_attrs(env),
+ prot, mmu_idx, page_size);
+ return 0;
+ do_fault_rsvd:
+ error_code |= PG_ERROR_RSVD_MASK;
+ do_fault_protect:
+ error_code |= PG_ERROR_P_MASK;
+ do_fault:
+ error_code |= (is_write << PG_ERROR_W_BIT);
+ if (is_user)
+ error_code |= PG_ERROR_U_MASK;
+ if (is_write1 == 2 &&
+ (((env->efer & MSR_EFER_NXE) &&
+ (env->cr[4] & CR4_PAE_MASK)) ||
+ (env->cr[4] & CR4_SMEP_MASK)))
+ error_code |= PG_ERROR_I_D_MASK;
+ if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {
+ /* cr2 is not modified in case of exceptions */
+ x86_stq_phys(cs,
+ env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
+ addr);
+ } else {
+ env->cr[2] = addr;
+ }
+ env->error_code = error_code;
+ cs->exception_index = EXCP0E_PAGE;
+ return 1;
+}
+#endif
diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c
index 69ea33a..9014b6f 100644
--- a/target/i386/fpu_helper.c
+++ b/target/i386/fpu_helper.c
@@ -1539,24 +1539,6 @@ void helper_xsetbv(CPUX86State *env, uint32_t ecx, uint64_t mask)
raise_exception_ra(env, EXCP0D_GPF, GETPC());
}
-void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f)
-{
- CPU_LDoubleU temp;
-
- temp.d = f;
- *pmant = temp.l.lower;
- *pexp = temp.l.upper;
-}
-
-floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper)
-{
- CPU_LDoubleU temp;
-
- temp.l.upper = upper;
- temp.l.lower = mant;
- return temp.d;
-}
-
/* MMX/SSE */
/* XXX: optimize by storing fptt and fptags in the static cpu state */
@@ -1568,12 +1550,11 @@ floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper)
#define SSE_RC_CHOP 0x6000
#define SSE_FZ 0x8000
-void cpu_set_mxcsr(CPUX86State *env, uint32_t mxcsr)
+void update_mxcsr_status(CPUX86State *env)
{
+ uint32_t mxcsr = env->mxcsr;
int rnd_type;
- env->mxcsr = mxcsr;
-
/* set rounding mode */
switch (mxcsr & SSE_RC_MASK) {
default:
@@ -1599,12 +1580,6 @@ void cpu_set_mxcsr(CPUX86State *env, uint32_t mxcsr)
set_flush_to_zero((mxcsr & SSE_FZ) ? 1 : 0, &env->fp_status);
}
-void cpu_set_fpuc(CPUX86State *env, uint16_t val)
-{
- env->fpuc = val;
- update_fp_status(env);
-}
-
void helper_ldmxcsr(CPUX86State *env, uint32_t val)
{
cpu_set_mxcsr(env, val);
diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c
index ba6117d..3ce6950 100644
--- a/target/i386/hax-all.c
+++ b/target/i386/hax-all.c
@@ -232,7 +232,7 @@ int hax_init_vcpu(CPUState *cpu)
}
cpu->hax_vcpu = hax_global.vm->vcpus[cpu->cpu_index];
- cpu->hax_vcpu_dirty = true;
+ cpu->vcpu_dirty = true;
qemu_register_reset(hax_reset_vcpu_state, (CPUArchState *) (cpu->env_ptr));
return ret;
@@ -599,12 +599,12 @@ static void do_hax_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
CPUArchState *env = cpu->env_ptr;
hax_arch_get_registers(env);
- cpu->hax_vcpu_dirty = true;
+ cpu->vcpu_dirty = true;
}
void hax_cpu_synchronize_state(CPUState *cpu)
{
- if (!cpu->hax_vcpu_dirty) {
+ if (!cpu->vcpu_dirty) {
run_on_cpu(cpu, do_hax_cpu_synchronize_state, RUN_ON_CPU_NULL);
}
}
@@ -615,7 +615,7 @@ static void do_hax_cpu_synchronize_post_reset(CPUState *cpu,
CPUArchState *env = cpu->env_ptr;
hax_vcpu_sync_state(env, 1);
- cpu->hax_vcpu_dirty = false;
+ cpu->vcpu_dirty = false;
}
void hax_cpu_synchronize_post_reset(CPUState *cpu)
@@ -628,7 +628,7 @@ static void do_hax_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg)
CPUArchState *env = cpu->env_ptr;
hax_vcpu_sync_state(env, 1);
- cpu->hax_vcpu_dirty = false;
+ cpu->vcpu_dirty = false;
}
void hax_cpu_synchronize_post_init(CPUState *cpu)
@@ -638,7 +638,7 @@ void hax_cpu_synchronize_post_init(CPUState *cpu)
static void do_hax_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg)
{
- cpu->hax_vcpu_dirty = true;
+ cpu->vcpu_dirty = true;
}
void hax_cpu_synchronize_pre_loadvm(CPUState *cpu)
diff --git a/target/i386/helper.c b/target/i386/helper.c
index ef05059..f63eb3d 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -29,6 +29,36 @@
#include "hw/i386/apic_internal.h"
#endif
+void cpu_sync_bndcs_hflags(CPUX86State *env)
+{
+ uint32_t hflags = env->hflags;
+ uint32_t hflags2 = env->hflags2;
+ uint32_t bndcsr;
+
+ if ((hflags & HF_CPL_MASK) == 3) {
+ bndcsr = env->bndcs_regs.cfgu;
+ } else {
+ bndcsr = env->msr_bndcfgs;
+ }
+
+ if ((env->cr[4] & CR4_OSXSAVE_MASK)
+ && (env->xcr0 & XSTATE_BNDCSR_MASK)
+ && (bndcsr & BNDCFG_ENABLE)) {
+ hflags |= HF_MPX_EN_MASK;
+ } else {
+ hflags &= ~HF_MPX_EN_MASK;
+ }
+
+ if (bndcsr & BNDCFG_BNDPRESERVE) {
+ hflags2 |= HF2_MPX_PR_MASK;
+ } else {
+ hflags2 &= ~HF2_MPX_PR_MASK;
+ }
+
+ env->hflags = hflags;
+ env->hflags2 = hflags2;
+}
+
static void cpu_x86_version(CPUX86State *env, int *family, int *model)
{
int cpuver = env->cpuid_version;
@@ -692,349 +722,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
cpu_sync_bndcs_hflags(env);
}
-#if defined(CONFIG_USER_ONLY)
-
-int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
- int is_write, int mmu_idx)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- /* user mode only emulation */
- is_write &= 1;
- env->cr[2] = addr;
- env->error_code = (is_write << PG_ERROR_W_BIT);
- env->error_code |= PG_ERROR_U_MASK;
- cs->exception_index = EXCP0E_PAGE;
- env->exception_is_int = 0;
- env->exception_next_eip = -1;
- return 1;
-}
-
-#else
-
-/* return value:
- * -1 = cannot handle fault
- * 0 = nothing more to do
- * 1 = generate PF fault
- */
-int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
- int is_write1, int mmu_idx)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- uint64_t ptep, pte;
- int32_t a20_mask;
- target_ulong pde_addr, pte_addr;
- int error_code = 0;
- int is_dirty, prot, page_size, is_write, is_user;
- hwaddr paddr;
- uint64_t rsvd_mask = PG_HI_RSVD_MASK;
- uint32_t page_offset;
- target_ulong vaddr;
-
- is_user = mmu_idx == MMU_USER_IDX;
-#if defined(DEBUG_MMU)
- printf("MMU fault: addr=%" VADDR_PRIx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
- addr, is_write1, is_user, env->eip);
-#endif
- is_write = is_write1 & 1;
-
- a20_mask = x86_get_a20_mask(env);
- if (!(env->cr[0] & CR0_PG_MASK)) {
- pte = addr;
-#ifdef TARGET_X86_64
- if (!(env->hflags & HF_LMA_MASK)) {
- /* Without long mode we can only address 32bits in real mode */
- pte = (uint32_t)pte;
- }
-#endif
- prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- page_size = 4096;
- goto do_mapping;
- }
-
- if (!(env->efer & MSR_EFER_NXE)) {
- rsvd_mask |= PG_NX_MASK;
- }
-
- if (env->cr[4] & CR4_PAE_MASK) {
- uint64_t pde, pdpe;
- target_ulong pdpe_addr;
-
-#ifdef TARGET_X86_64
- if (env->hflags & HF_LMA_MASK) {
- bool la57 = env->cr[4] & CR4_LA57_MASK;
- uint64_t pml5e_addr, pml5e;
- uint64_t pml4e_addr, pml4e;
- int32_t sext;
-
- /* test virtual address sign extension */
- sext = la57 ? (int64_t)addr >> 56 : (int64_t)addr >> 47;
- if (sext != 0 && sext != -1) {
- env->error_code = 0;
- cs->exception_index = EXCP0D_GPF;
- return 1;
- }
-
- if (la57) {
- pml5e_addr = ((env->cr[3] & ~0xfff) +
- (((addr >> 48) & 0x1ff) << 3)) & a20_mask;
- pml5e = x86_ldq_phys(cs, pml5e_addr);
- if (!(pml5e & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- if (pml5e & (rsvd_mask | PG_PSE_MASK)) {
- goto do_fault_rsvd;
- }
- if (!(pml5e & PG_ACCESSED_MASK)) {
- pml5e |= PG_ACCESSED_MASK;
- x86_stl_phys_notdirty(cs, pml5e_addr, pml5e);
- }
- ptep = pml5e ^ PG_NX_MASK;
- } else {
- pml5e = env->cr[3];
- ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
- }
-
- pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
- (((addr >> 39) & 0x1ff) << 3)) & a20_mask;
- pml4e = x86_ldq_phys(cs, pml4e_addr);
- if (!(pml4e & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- if (pml4e & (rsvd_mask | PG_PSE_MASK)) {
- goto do_fault_rsvd;
- }
- if (!(pml4e & PG_ACCESSED_MASK)) {
- pml4e |= PG_ACCESSED_MASK;
- x86_stl_phys_notdirty(cs, pml4e_addr, pml4e);
- }
- ptep &= pml4e ^ PG_NX_MASK;
- pdpe_addr = ((pml4e & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
- a20_mask;
- pdpe = x86_ldq_phys(cs, pdpe_addr);
- if (!(pdpe & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- if (pdpe & rsvd_mask) {
- goto do_fault_rsvd;
- }
- ptep &= pdpe ^ PG_NX_MASK;
- if (!(pdpe & PG_ACCESSED_MASK)) {
- pdpe |= PG_ACCESSED_MASK;
- x86_stl_phys_notdirty(cs, pdpe_addr, pdpe);
- }
- if (pdpe & PG_PSE_MASK) {
- /* 1 GB page */
- page_size = 1024 * 1024 * 1024;
- pte_addr = pdpe_addr;
- pte = pdpe;
- goto do_check_protect;
- }
- } else
-#endif
- {
- /* XXX: load them when cr3 is loaded ? */
- pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
- a20_mask;
- pdpe = x86_ldq_phys(cs, pdpe_addr);
- if (!(pdpe & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- rsvd_mask |= PG_HI_USER_MASK;
- if (pdpe & (rsvd_mask | PG_NX_MASK)) {
- goto do_fault_rsvd;
- }
- ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
- }
-
- pde_addr = ((pdpe & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
- a20_mask;
- pde = x86_ldq_phys(cs, pde_addr);
- if (!(pde & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- if (pde & rsvd_mask) {
- goto do_fault_rsvd;
- }
- ptep &= pde ^ PG_NX_MASK;
- if (pde & PG_PSE_MASK) {
- /* 2 MB page */
- page_size = 2048 * 1024;
- pte_addr = pde_addr;
- pte = pde;
- goto do_check_protect;
- }
- /* 4 KB page */
- if (!(pde & PG_ACCESSED_MASK)) {
- pde |= PG_ACCESSED_MASK;
- x86_stl_phys_notdirty(cs, pde_addr, pde);
- }
- pte_addr = ((pde & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
- a20_mask;
- pte = x86_ldq_phys(cs, pte_addr);
- if (!(pte & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- if (pte & rsvd_mask) {
- goto do_fault_rsvd;
- }
- /* combine pde and pte nx, user and rw protections */
- ptep &= pte ^ PG_NX_MASK;
- page_size = 4096;
- } else {
- uint32_t pde;
-
- /* page directory entry */
- pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
- a20_mask;
- pde = x86_ldl_phys(cs, pde_addr);
- if (!(pde & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- ptep = pde | PG_NX_MASK;
-
- /* if PSE bit is set, then we use a 4MB page */
- if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
- page_size = 4096 * 1024;
- pte_addr = pde_addr;
-
- /* Bits 20-13 provide bits 39-32 of the address, bit 21 is reserved.
- * Leave bits 20-13 in place for setting accessed/dirty bits below.
- */
- pte = pde | ((pde & 0x1fe000LL) << (32 - 13));
- rsvd_mask = 0x200000;
- goto do_check_protect_pse36;
- }
-
- if (!(pde & PG_ACCESSED_MASK)) {
- pde |= PG_ACCESSED_MASK;
- x86_stl_phys_notdirty(cs, pde_addr, pde);
- }
-
- /* page directory entry */
- pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
- a20_mask;
- pte = x86_ldl_phys(cs, pte_addr);
- if (!(pte & PG_PRESENT_MASK)) {
- goto do_fault;
- }
- /* combine pde and pte user and rw protections */
- ptep &= pte | PG_NX_MASK;
- page_size = 4096;
- rsvd_mask = 0;
- }
-
-do_check_protect:
- rsvd_mask |= (page_size - 1) & PG_ADDRESS_MASK & ~PG_PSE_PAT_MASK;
-do_check_protect_pse36:
- if (pte & rsvd_mask) {
- goto do_fault_rsvd;
- }
- ptep ^= PG_NX_MASK;
-
- /* can the page can be put in the TLB? prot will tell us */
- if (is_user && !(ptep & PG_USER_MASK)) {
- goto do_fault_protect;
- }
-
- prot = 0;
- if (mmu_idx != MMU_KSMAP_IDX || !(ptep & PG_USER_MASK)) {
- prot |= PAGE_READ;
- if ((ptep & PG_RW_MASK) || (!is_user && !(env->cr[0] & CR0_WP_MASK))) {
- prot |= PAGE_WRITE;
- }
- }
- if (!(ptep & PG_NX_MASK) &&
- (mmu_idx == MMU_USER_IDX ||
- !((env->cr[4] & CR4_SMEP_MASK) && (ptep & PG_USER_MASK)))) {
- prot |= PAGE_EXEC;
- }
- if ((env->cr[4] & CR4_PKE_MASK) && (env->hflags & HF_LMA_MASK) &&
- (ptep & PG_USER_MASK) && env->pkru) {
- uint32_t pk = (pte & PG_PKRU_MASK) >> PG_PKRU_BIT;
- uint32_t pkru_ad = (env->pkru >> pk * 2) & 1;
- uint32_t pkru_wd = (env->pkru >> pk * 2) & 2;
- uint32_t pkru_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-
- if (pkru_ad) {
- pkru_prot &= ~(PAGE_READ | PAGE_WRITE);
- } else if (pkru_wd && (is_user || env->cr[0] & CR0_WP_MASK)) {
- pkru_prot &= ~PAGE_WRITE;
- }
-
- prot &= pkru_prot;
- if ((pkru_prot & (1 << is_write1)) == 0) {
- assert(is_write1 != 2);
- error_code |= PG_ERROR_PK_MASK;
- goto do_fault_protect;
- }
- }
-
- if ((prot & (1 << is_write1)) == 0) {
- goto do_fault_protect;
- }
-
- /* yes, it can! */
- is_dirty = is_write && !(pte & PG_DIRTY_MASK);
- if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
- pte |= PG_ACCESSED_MASK;
- if (is_dirty) {
- pte |= PG_DIRTY_MASK;
- }
- x86_stl_phys_notdirty(cs, pte_addr, pte);
- }
-
- if (!(pte & PG_DIRTY_MASK)) {
- /* only set write access if already dirty... otherwise wait
- for dirty access */
- assert(!is_write);
- prot &= ~PAGE_WRITE;
- }
-
- do_mapping:
- pte = pte & a20_mask;
-
- /* align to page_size */
- pte &= PG_ADDRESS_MASK & ~(page_size - 1);
-
- /* Even if 4MB pages, we map only one 4KB page in the cache to
- avoid filling it too fast */
- vaddr = addr & TARGET_PAGE_MASK;
- page_offset = vaddr & (page_size - 1);
- paddr = pte + page_offset;
-
- assert(prot & (1 << is_write1));
- tlb_set_page_with_attrs(cs, vaddr, paddr, cpu_get_mem_attrs(env),
- prot, mmu_idx, page_size);
- return 0;
- do_fault_rsvd:
- error_code |= PG_ERROR_RSVD_MASK;
- do_fault_protect:
- error_code |= PG_ERROR_P_MASK;
- do_fault:
- error_code |= (is_write << PG_ERROR_W_BIT);
- if (is_user)
- error_code |= PG_ERROR_U_MASK;
- if (is_write1 == 2 &&
- (((env->efer & MSR_EFER_NXE) &&
- (env->cr[4] & CR4_PAE_MASK)) ||
- (env->cr[4] & CR4_SMEP_MASK)))
- error_code |= PG_ERROR_I_D_MASK;
- if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {
- /* cr2 is not modified in case of exceptions */
- x86_stq_phys(cs,
- env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
- addr);
- } else {
- env->cr[2] = addr;
- }
- env->error_code = error_code;
- cs->exception_index = EXCP0E_PAGE;
- return 1;
-}
-
+#if !defined(CONFIG_USER_ONLY)
hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
X86CPU *cpu = X86_CPU(cs);
@@ -1302,7 +990,7 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
env->tpr_access_type = access;
cpu_interrupt(cs, CPU_INTERRUPT_TPR);
- } else {
+ } else if (tcg_enabled()) {
cpu_restore_state(cs, cs->mem_io_pc);
apic_handle_tpr_access_report(cpu->apic_state, env->eip, access);
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index ee36502..f84a49d 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -1433,56 +1433,12 @@ static int kvm_put_xsave(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;
X86XSaveArea *xsave = env->kvm_xsave_buf;
- uint16_t cwd, swd, twd;
- int i;
if (!has_xsave) {
return kvm_put_fpu(cpu);
}
+ x86_cpu_xsave_all_areas(cpu, xsave);
- memset(xsave, 0, sizeof(struct kvm_xsave));
- twd = 0;
- swd = env->fpus & ~(7 << 11);
- swd |= (env->fpstt & 7) << 11;
- cwd = env->fpuc;
- for (i = 0; i < 8; ++i) {
- twd |= (!env->fptags[i]) << i;
- }
- xsave->legacy.fcw = cwd;
- xsave->legacy.fsw = swd;
- xsave->legacy.ftw = twd;
- xsave->legacy.fpop = env->fpop;
- xsave->legacy.fpip = env->fpip;
- xsave->legacy.fpdp = env->fpdp;
- memcpy(&xsave->legacy.fpregs, env->fpregs,
- sizeof env->fpregs);
- xsave->legacy.mxcsr = env->mxcsr;
- xsave->header.xstate_bv = env->xstate_bv;
- memcpy(&xsave->bndreg_state.bnd_regs, env->bnd_regs,
- sizeof env->bnd_regs);
- xsave->bndcsr_state.bndcsr = env->bndcs_regs;
- memcpy(&xsave->opmask_state.opmask_regs, env->opmask_regs,
- sizeof env->opmask_regs);
-
- for (i = 0; i < CPU_NB_REGS; i++) {
- uint8_t *xmm = xsave->legacy.xmm_regs[i];
- uint8_t *ymmh = xsave->avx_state.ymmh[i];
- uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i];
- stq_p(xmm, env->xmm_regs[i].ZMM_Q(0));
- stq_p(xmm+8, env->xmm_regs[i].ZMM_Q(1));
- stq_p(ymmh, env->xmm_regs[i].ZMM_Q(2));
- stq_p(ymmh+8, env->xmm_regs[i].ZMM_Q(3));
- stq_p(zmmh, env->xmm_regs[i].ZMM_Q(4));
- stq_p(zmmh+8, env->xmm_regs[i].ZMM_Q(5));
- stq_p(zmmh+16, env->xmm_regs[i].ZMM_Q(6));
- stq_p(zmmh+24, env->xmm_regs[i].ZMM_Q(7));
- }
-
-#ifdef TARGET_X86_64
- memcpy(&xsave->hi16_zmm_state.hi16_zmm, &env->xmm_regs[16],
- 16 * sizeof env->xmm_regs[16]);
- memcpy(&xsave->pkru_state, &env->pkru, sizeof env->pkru);
-#endif
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave);
}
@@ -1868,8 +1824,7 @@ static int kvm_get_xsave(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;
X86XSaveArea *xsave = env->kvm_xsave_buf;
- int ret, i;
- uint16_t cwd, swd, twd;
+ int ret;
if (!has_xsave) {
return kvm_get_fpu(cpu);
@@ -1879,48 +1834,8 @@ static int kvm_get_xsave(X86CPU *cpu)
if (ret < 0) {
return ret;
}
+ x86_cpu_xrstor_all_areas(cpu, xsave);
- cwd = xsave->legacy.fcw;
- swd = xsave->legacy.fsw;
- twd = xsave->legacy.ftw;
- env->fpop = xsave->legacy.fpop;
- env->fpstt = (swd >> 11) & 7;
- env->fpus = swd;
- env->fpuc = cwd;
- for (i = 0; i < 8; ++i) {
- env->fptags[i] = !((twd >> i) & 1);
- }
- env->fpip = xsave->legacy.fpip;
- env->fpdp = xsave->legacy.fpdp;
- env->mxcsr = xsave->legacy.mxcsr;
- memcpy(env->fpregs, &xsave->legacy.fpregs,
- sizeof env->fpregs);
- env->xstate_bv = xsave->header.xstate_bv;
- memcpy(env->bnd_regs, &xsave->bndreg_state.bnd_regs,
- sizeof env->bnd_regs);
- env->bndcs_regs = xsave->bndcsr_state.bndcsr;
- memcpy(env->opmask_regs, &xsave->opmask_state.opmask_regs,
- sizeof env->opmask_regs);
-
- for (i = 0; i < CPU_NB_REGS; i++) {
- uint8_t *xmm = xsave->legacy.xmm_regs[i];
- uint8_t *ymmh = xsave->avx_state.ymmh[i];
- uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i];
- env->xmm_regs[i].ZMM_Q(0) = ldq_p(xmm);
- env->xmm_regs[i].ZMM_Q(1) = ldq_p(xmm+8);
- env->xmm_regs[i].ZMM_Q(2) = ldq_p(ymmh);
- env->xmm_regs[i].ZMM_Q(3) = ldq_p(ymmh+8);
- env->xmm_regs[i].ZMM_Q(4) = ldq_p(zmmh);
- env->xmm_regs[i].ZMM_Q(5) = ldq_p(zmmh+8);
- env->xmm_regs[i].ZMM_Q(6) = ldq_p(zmmh+16);
- env->xmm_regs[i].ZMM_Q(7) = ldq_p(zmmh+24);
- }
-
-#ifdef TARGET_X86_64
- memcpy(&env->xmm_regs[16], &xsave->hi16_zmm_state.hi16_zmm,
- 16 * sizeof env->xmm_regs[16]);
- memcpy(&env->pkru, &xsave->pkru_state, sizeof env->pkru);
-#endif
return 0;
}
diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h
index bfce427..1de9876 100644
--- a/target/i386/kvm_i386.h
+++ b/target/i386/kvm_i386.h
@@ -15,6 +15,29 @@
#define kvm_apic_in_kernel() (kvm_irqchip_in_kernel())
+#ifdef CONFIG_KVM
+
+#define kvm_pit_in_kernel() \
+ (kvm_irqchip_in_kernel() && !kvm_irqchip_is_split())
+#define kvm_pic_in_kernel() \
+ (kvm_irqchip_in_kernel() && !kvm_irqchip_is_split())
+#define kvm_ioapic_in_kernel() \
+ (kvm_irqchip_in_kernel() && !kvm_irqchip_is_split())
+
+#else
+
+#define kvm_pit_in_kernel() 0
+#define kvm_pic_in_kernel() 0
+#define kvm_ioapic_in_kernel() 0
+
+/* These constants must never be used at runtime if kvm_enabled() is false.
+ * They exist so we don't need #ifdefs around KVM-specific code that already
+ * checks kvm_enabled() properly.
+ */
+#define KVM_CPUID_FEATURES 0
+
+#endif /* CONFIG_KVM */
+
bool kvm_allows_irq0_override(void);
bool kvm_has_smm(void);
bool kvm_has_adjust_clock_stable(void);
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 8c7a822..eab3372 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -142,6 +142,24 @@ typedef struct x86_FPReg_tmp {
uint16_t tmp_exp;
} x86_FPReg_tmp;
+static void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f)
+{
+ CPU_LDoubleU temp;
+
+ temp.d = f;
+ *pmant = temp.l.lower;
+ *pexp = temp.l.upper;
+}
+
+static floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper)
+{
+ CPU_LDoubleU temp;
+
+ temp.l.upper = upper;
+ temp.l.lower = mant;
+ return temp.d;
+}
+
static void fpreg_pre_save(void *opaque)
{
x86_FPReg_tmp *tmp = opaque;
@@ -262,14 +280,17 @@ static int cpu_post_load(void *opaque, int version_id)
for(i = 0; i < 8; i++) {
env->fptags[i] = (env->fptag_vmstate >> i) & 1;
}
- update_fp_status(env);
+ if (tcg_enabled()) {
+ target_ulong dr7;
+ update_fp_status(env);
+ update_mxcsr_status(env);
+
+ cpu_breakpoint_remove_all(cs, BP_CPU);
+ cpu_watchpoint_remove_all(cs, BP_CPU);
- cpu_breakpoint_remove_all(cs, BP_CPU);
- cpu_watchpoint_remove_all(cs, BP_CPU);
- {
/* Indicate all breakpoints disabled, as they are, then
let the helper re-enable them. */
- target_ulong dr7 = env->dr[7];
+ dr7 = env->dr[7];
env->dr[7] = dr7 & ~(DR7_GLOBAL_BP_MASK | DR7_LOCAL_BP_MASK);
cpu_x86_update_dr7(env, dr7);
}
diff --git a/target/i386/mpx_helper.c b/target/i386/mpx_helper.c
index 7e44820..ade5d24 100644
--- a/target/i386/mpx_helper.c
+++ b/target/i386/mpx_helper.c
@@ -24,36 +24,6 @@
#include "exec/exec-all.h"
-void cpu_sync_bndcs_hflags(CPUX86State *env)
-{
- uint32_t hflags = env->hflags;
- uint32_t hflags2 = env->hflags2;
- uint32_t bndcsr;
-
- if ((hflags & HF_CPL_MASK) == 3) {
- bndcsr = env->bndcs_regs.cfgu;
- } else {
- bndcsr = env->msr_bndcfgs;
- }
-
- if ((env->cr[4] & CR4_OSXSAVE_MASK)
- && (env->xcr0 & XSTATE_BNDCSR_MASK)
- && (bndcsr & BNDCFG_ENABLE)) {
- hflags |= HF_MPX_EN_MASK;
- } else {
- hflags &= ~HF_MPX_EN_MASK;
- }
-
- if (bndcsr & BNDCFG_BNDPRESERVE) {
- hflags2 |= HF2_MPX_PR_MASK;
- } else {
- hflags2 &= ~HF2_MPX_PR_MASK;
- }
-
- env->hflags = hflags;
- env->hflags2 = hflags2;
-}
-
void helper_bndck(CPUX86State *env, uint32_t fail)
{
if (unlikely(fail)) {
diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c
index 0374031..600a4d7 100644
--- a/target/i386/seg_helper.c
+++ b/target/i386/seg_helper.c
@@ -692,7 +692,10 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
if (!(e2 & DESC_P_MASK)) {
raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc);
}
- if (!(e2 & DESC_C_MASK) && dpl < cpl) {
+ if (e2 & DESC_C_MASK) {
+ dpl = cpl;
+ }
+ if (dpl < cpl) {
/* to inner privilege */
get_ss_esp_from_tss(env, &ss, &esp, dpl, 0);
if ((ss & 0xfffc) == 0) {
@@ -719,7 +722,7 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
new_stack = 1;
sp_mask = get_sp_mask(ss_e2);
ssp = get_seg_base(ss_e1, ss_e2);
- } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
+ } else {
/* to same privilege */
if (vm86) {
raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
@@ -728,13 +731,6 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
sp_mask = get_sp_mask(env->segs[R_SS].flags);
ssp = env->segs[R_SS].base;
esp = env->regs[R_ESP];
- dpl = cpl;
- } else {
- raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
- new_stack = 0; /* avoid warning */
- sp_mask = 0; /* avoid warning */
- ssp = 0; /* avoid warning */
- esp = 0; /* avoid warning */
}
shift = type >> 3;
@@ -919,23 +915,21 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK)) {
raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
}
- if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
+ if (e2 & DESC_C_MASK) {
+ dpl = cpl;
+ }
+ if (dpl < cpl || ist != 0) {
/* to inner privilege */
new_stack = 1;
esp = get_rsp_from_tss(env, ist != 0 ? ist + 3 : dpl);
ss = 0;
- } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
+ } else {
/* to same privilege */
if (env->eflags & VM_MASK) {
raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
}
new_stack = 0;
esp = env->regs[R_ESP];
- dpl = cpl;
- } else {
- raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
- new_stack = 0; /* avoid warning */
- esp = 0; /* avoid warning */
}
esp &= ~0xfLL; /* align stack */
@@ -956,7 +950,7 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
if (new_stack) {
ss = 0 | dpl;
- cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
+ cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, dpl << DESC_DPL_SHIFT);
}
env->regs[R_ESP] = esp;
diff --git a/target/i386/xsave_helper.c b/target/i386/xsave_helper.c
new file mode 100644
index 0000000..ca735ee
--- /dev/null
+++ b/target/i386/xsave_helper.c
@@ -0,0 +1,114 @@
+/*
+ * 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 "qapi/error.h"
+
+#include "qemu-common.h"
+#include "cpu.h"
+
+void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf)
+{
+ CPUX86State *env = &cpu->env;
+ X86XSaveArea *xsave = buf;
+
+ uint16_t cwd, swd, twd;
+ int i;
+ memset(xsave, 0, sizeof(X86XSaveArea));
+ twd = 0;
+ swd = env->fpus & ~(7 << 11);
+ swd |= (env->fpstt & 7) << 11;
+ cwd = env->fpuc;
+ for (i = 0; i < 8; ++i) {
+ twd |= (!env->fptags[i]) << i;
+ }
+ xsave->legacy.fcw = cwd;
+ xsave->legacy.fsw = swd;
+ xsave->legacy.ftw = twd;
+ xsave->legacy.fpop = env->fpop;
+ xsave->legacy.fpip = env->fpip;
+ xsave->legacy.fpdp = env->fpdp;
+ memcpy(&xsave->legacy.fpregs, env->fpregs,
+ sizeof env->fpregs);
+ xsave->legacy.mxcsr = env->mxcsr;
+ xsave->header.xstate_bv = env->xstate_bv;
+ memcpy(&xsave->bndreg_state.bnd_regs, env->bnd_regs,
+ sizeof env->bnd_regs);
+ xsave->bndcsr_state.bndcsr = env->bndcs_regs;
+ memcpy(&xsave->opmask_state.opmask_regs, env->opmask_regs,
+ sizeof env->opmask_regs);
+
+ for (i = 0; i < CPU_NB_REGS; i++) {
+ uint8_t *xmm = xsave->legacy.xmm_regs[i];
+ uint8_t *ymmh = xsave->avx_state.ymmh[i];
+ uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i];
+ stq_p(xmm, env->xmm_regs[i].ZMM_Q(0));
+ stq_p(xmm+8, env->xmm_regs[i].ZMM_Q(1));
+ stq_p(ymmh, env->xmm_regs[i].ZMM_Q(2));
+ stq_p(ymmh+8, env->xmm_regs[i].ZMM_Q(3));
+ stq_p(zmmh, env->xmm_regs[i].ZMM_Q(4));
+ stq_p(zmmh+8, env->xmm_regs[i].ZMM_Q(5));
+ stq_p(zmmh+16, env->xmm_regs[i].ZMM_Q(6));
+ stq_p(zmmh+24, env->xmm_regs[i].ZMM_Q(7));
+ }
+
+#ifdef TARGET_X86_64
+ memcpy(&xsave->hi16_zmm_state.hi16_zmm, &env->xmm_regs[16],
+ 16 * sizeof env->xmm_regs[16]);
+ memcpy(&xsave->pkru_state, &env->pkru, sizeof env->pkru);
+#endif
+
+}
+
+void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf)
+{
+
+ CPUX86State *env = &cpu->env;
+ const X86XSaveArea *xsave = buf;
+
+ int i;
+ uint16_t cwd, swd, twd;
+ cwd = xsave->legacy.fcw;
+ swd = xsave->legacy.fsw;
+ twd = xsave->legacy.ftw;
+ env->fpop = xsave->legacy.fpop;
+ env->fpstt = (swd >> 11) & 7;
+ env->fpus = swd;
+ env->fpuc = cwd;
+ for (i = 0; i < 8; ++i) {
+ env->fptags[i] = !((twd >> i) & 1);
+ }
+ env->fpip = xsave->legacy.fpip;
+ env->fpdp = xsave->legacy.fpdp;
+ env->mxcsr = xsave->legacy.mxcsr;
+ memcpy(env->fpregs, &xsave->legacy.fpregs,
+ sizeof env->fpregs);
+ env->xstate_bv = xsave->header.xstate_bv;
+ memcpy(env->bnd_regs, &xsave->bndreg_state.bnd_regs,
+ sizeof env->bnd_regs);
+ env->bndcs_regs = xsave->bndcsr_state.bndcsr;
+ memcpy(env->opmask_regs, &xsave->opmask_state.opmask_regs,
+ sizeof env->opmask_regs);
+
+ for (i = 0; i < CPU_NB_REGS; i++) {
+ const uint8_t *xmm = xsave->legacy.xmm_regs[i];
+ const uint8_t *ymmh = xsave->avx_state.ymmh[i];
+ const uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i];
+ env->xmm_regs[i].ZMM_Q(0) = ldq_p(xmm);
+ env->xmm_regs[i].ZMM_Q(1) = ldq_p(xmm+8);
+ env->xmm_regs[i].ZMM_Q(2) = ldq_p(ymmh);
+ env->xmm_regs[i].ZMM_Q(3) = ldq_p(ymmh+8);
+ env->xmm_regs[i].ZMM_Q(4) = ldq_p(zmmh);
+ env->xmm_regs[i].ZMM_Q(5) = ldq_p(zmmh+8);
+ env->xmm_regs[i].ZMM_Q(6) = ldq_p(zmmh+16);
+ env->xmm_regs[i].ZMM_Q(7) = ldq_p(zmmh+24);
+ }
+
+#ifdef TARGET_X86_64
+ memcpy(&env->xmm_regs[16], &xsave->hi16_zmm_state.hi16_zmm,
+ 16 * sizeof env->xmm_regs[16]);
+ memcpy(&env->pkru, &xsave->pkru_state, sizeof env->pkru);
+#endif
+
+}
diff --git a/target/mips/kvm.c b/target/mips/kvm.c
index 0982e87..3317905 100644
--- a/target/mips/kvm.c
+++ b/target/mips/kvm.c
@@ -523,7 +523,7 @@ static void kvm_mips_update_state(void *opaque, int running, RunState state)
* already saved and can be restored when it is synced back to KVM.
*/
if (!running) {
- if (!cs->kvm_vcpu_dirty) {
+ if (!cs->vcpu_dirty) {
ret = kvm_mips_save_count(cs);
if (ret < 0) {
fprintf(stderr, "Failed saving count\n");
@@ -539,7 +539,7 @@ static void kvm_mips_update_state(void *opaque, int running, RunState state)
return;
}
- if (!cs->kvm_vcpu_dirty) {
+ if (!cs->vcpu_dirty) {
ret = kvm_mips_restore_count(cs);
if (ret < 0) {
fprintf(stderr, "Failed restoring count\n");
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 9e37722..da78721 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -757,10 +757,6 @@ void *tcg_malloc_internal(TCGContext *s, int size);
void tcg_pool_reset(TCGContext *s);
TranslationBlock *tcg_tb_alloc(TCGContext *s);
-void tb_lock(void);
-void tb_unlock(void);
-void tb_lock_reset(void);
-
/* Called with tb_lock held. */
static inline void *tcg_malloc(int size)
{
diff --git a/tests/test-char.c b/tests/test-char.c
index 87c724c..b962063 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -20,13 +20,9 @@ typedef struct FeHandler {
static void main_loop(void)
{
- bool nonblocking;
- int last_io = 0;
-
quit = false;
do {
- nonblocking = last_io > 0;
- last_io = main_loop_wait(nonblocking);
+ main_loop_wait(false);
} while (!quit);
}
diff --git a/util/main-loop.c b/util/main-loop.c
index 19cad6b..2f48f41 100644
--- a/util/main-loop.c
+++ b/util/main-loop.c
@@ -487,7 +487,7 @@ static int os_host_main_loop_wait(int64_t timeout)
}
#endif
-int main_loop_wait(int nonblocking)
+void main_loop_wait(int nonblocking)
{
int ret;
uint32_t timeout = UINT32_MAX;
@@ -500,9 +500,7 @@ int main_loop_wait(int nonblocking)
/* poll any events */
g_array_set_size(gpollfds, 0); /* reset for new iteration */
/* XXX: separate device handlers from system ones */
-#ifdef CONFIG_SLIRP
slirp_pollfds_fill(gpollfds, &timeout);
-#endif
if (timeout == UINT32_MAX) {
timeout_ns = -1;
@@ -515,16 +513,12 @@ int main_loop_wait(int nonblocking)
&main_loop_tlg));
ret = os_host_main_loop_wait(timeout_ns);
-#ifdef CONFIG_SLIRP
slirp_pollfds_poll(gpollfds, (ret < 0));
-#endif
/* CPU thread can infinitely wait for event after
missing the warp */
qemu_start_warp_timer();
qemu_clock_run_all_timers();
-
- return ret;
}
/* Functions to operate on the main QEMU AioContext. */
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 80e4668..3de9e77 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -438,10 +438,8 @@ static int poll_rest(gboolean poll_msgs, HANDLE *handles, gint nhandles,
if (timeout == 0 && nhandles > 1) {
/* Remove the handle that fired */
int i;
- if (ready < nhandles - 1) {
- for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) {
- handles[i-1] = handles[i];
- }
+ for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) {
+ handles[i-1] = handles[i];
}
nhandles--;
recursed_result = poll_rest(FALSE, handles, nhandles, fds, nfds, 0);
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 82290cb..d3e5108 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -897,7 +897,7 @@ static int unix_listen_saddr(UnixSocketAddress *saddr,
strncpy(un.sun_path, path, sizeof(un.sun_path));
if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
- error_setg_errno(errp, errno, "Failed to bind socket to %s", un.sun_path);
+ error_setg_errno(errp, errno, "Failed to bind socket to %s", path);
goto err;
}
if (listen(sock, 1) < 0) {
diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index eacd99e..4e95d27 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -43,12 +43,15 @@ void qemu_mutex_init(QemuMutex *mutex)
err = pthread_mutex_init(&mutex->lock, NULL);
if (err)
error_exit(err, __func__);
+ mutex->initialized = true;
}
void qemu_mutex_destroy(QemuMutex *mutex)
{
int err;
+ assert(mutex->initialized);
+ mutex->initialized = false;
err = pthread_mutex_destroy(&mutex->lock);
if (err)
error_exit(err, __func__);
@@ -58,6 +61,7 @@ void qemu_mutex_lock(QemuMutex *mutex)
{
int err;
+ assert(mutex->initialized);
err = pthread_mutex_lock(&mutex->lock);
if (err)
error_exit(err, __func__);
@@ -69,6 +73,7 @@ int qemu_mutex_trylock(QemuMutex *mutex)
{
int err;
+ assert(mutex->initialized);
err = pthread_mutex_trylock(&mutex->lock);
if (err == 0) {
trace_qemu_mutex_locked(mutex);
@@ -84,6 +89,7 @@ void qemu_mutex_unlock(QemuMutex *mutex)
{
int err;
+ assert(mutex->initialized);
trace_qemu_mutex_unlocked(mutex);
err = pthread_mutex_unlock(&mutex->lock);
if (err)
@@ -102,6 +108,7 @@ void qemu_rec_mutex_init(QemuRecMutex *mutex)
if (err) {
error_exit(err, __func__);
}
+ mutex->initialized = true;
}
void qemu_cond_init(QemuCond *cond)
@@ -111,12 +118,15 @@ void qemu_cond_init(QemuCond *cond)
err = pthread_cond_init(&cond->cond, NULL);
if (err)
error_exit(err, __func__);
+ cond->initialized = true;
}
void qemu_cond_destroy(QemuCond *cond)
{
int err;
+ assert(cond->initialized);
+ cond->initialized = false;
err = pthread_cond_destroy(&cond->cond);
if (err)
error_exit(err, __func__);
@@ -126,6 +136,7 @@ void qemu_cond_signal(QemuCond *cond)
{
int err;
+ assert(cond->initialized);
err = pthread_cond_signal(&cond->cond);
if (err)
error_exit(err, __func__);
@@ -135,6 +146,7 @@ void qemu_cond_broadcast(QemuCond *cond)
{
int err;
+ assert(cond->initialized);
err = pthread_cond_broadcast(&cond->cond);
if (err)
error_exit(err, __func__);
@@ -144,6 +156,7 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
{
int err;
+ assert(cond->initialized);
trace_qemu_mutex_unlocked(mutex);
err = pthread_cond_wait(&cond->cond, &mutex->lock);
trace_qemu_mutex_locked(mutex);
@@ -174,12 +187,15 @@ void qemu_sem_init(QemuSemaphore *sem, int init)
error_exit(errno, __func__);
}
#endif
+ sem->initialized = true;
}
void qemu_sem_destroy(QemuSemaphore *sem)
{
int rc;
+ assert(sem->initialized);
+ sem->initialized = false;
#if defined(__APPLE__) || defined(__NetBSD__)
rc = pthread_cond_destroy(&sem->cond);
if (rc < 0) {
@@ -201,6 +217,7 @@ void qemu_sem_post(QemuSemaphore *sem)
{
int rc;
+ assert(sem->initialized);
#if defined(__APPLE__) || defined(__NetBSD__)
pthread_mutex_lock(&sem->lock);
if (sem->count == UINT_MAX) {
@@ -238,6 +255,7 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
int rc;
struct timespec ts;
+ assert(sem->initialized);
#if defined(__APPLE__) || defined(__NetBSD__)
rc = 0;
compute_abs_deadline(&ts, ms);
@@ -285,6 +303,7 @@ void qemu_sem_wait(QemuSemaphore *sem)
{
int rc;
+ assert(sem->initialized);
#if defined(__APPLE__) || defined(__NetBSD__)
pthread_mutex_lock(&sem->lock);
while (sem->count == 0) {
@@ -310,6 +329,7 @@ void qemu_sem_wait(QemuSemaphore *sem)
#else
static inline void qemu_futex_wake(QemuEvent *ev, int n)
{
+ assert(ev->initialized);
pthread_mutex_lock(&ev->lock);
if (n == 1) {
pthread_cond_signal(&ev->cond);
@@ -321,6 +341,7 @@ static inline void qemu_futex_wake(QemuEvent *ev, int n)
static inline void qemu_futex_wait(QemuEvent *ev, unsigned val)
{
+ assert(ev->initialized);
pthread_mutex_lock(&ev->lock);
if (ev->value == val) {
pthread_cond_wait(&ev->cond, &ev->lock);
@@ -355,10 +376,13 @@ void qemu_event_init(QemuEvent *ev, bool init)
#endif
ev->value = (init ? EV_SET : EV_FREE);
+ ev->initialized = true;
}
void qemu_event_destroy(QemuEvent *ev)
{
+ assert(ev->initialized);
+ ev->initialized = false;
#ifndef __linux__
pthread_mutex_destroy(&ev->lock);
pthread_cond_destroy(&ev->cond);
@@ -370,6 +394,7 @@ void qemu_event_set(QemuEvent *ev)
/* qemu_event_set has release semantics, but because it *loads*
* ev->value we need a full memory barrier here.
*/
+ assert(ev->initialized);
smp_mb();
if (atomic_read(&ev->value) != EV_SET) {
if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
@@ -383,6 +408,7 @@ void qemu_event_reset(QemuEvent *ev)
{
unsigned value;
+ assert(ev->initialized);
value = atomic_read(&ev->value);
smp_mb_acquire();
if (value == EV_SET) {
@@ -398,6 +424,7 @@ void qemu_event_wait(QemuEvent *ev)
{
unsigned value;
+ assert(ev->initialized);
value = atomic_read(&ev->value);
smp_mb_acquire();
if (value != EV_SET) {
diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
index 653f29f..94f3491 100644
--- a/util/qemu-thread-win32.c
+++ b/util/qemu-thread-win32.c
@@ -46,15 +46,19 @@ static void error_exit(int err, const char *msg)
void qemu_mutex_init(QemuMutex *mutex)
{
InitializeSRWLock(&mutex->lock);
+ mutex->initialized = true;
}
void qemu_mutex_destroy(QemuMutex *mutex)
{
+ assert(mutex->initialized);
+ mutex->initialized = false;
InitializeSRWLock(&mutex->lock);
}
void qemu_mutex_lock(QemuMutex *mutex)
{
+ assert(mutex->initialized);
AcquireSRWLockExclusive(&mutex->lock);
trace_qemu_mutex_locked(mutex);
}
@@ -63,6 +67,7 @@ int qemu_mutex_trylock(QemuMutex *mutex)
{
int owned;
+ assert(mutex->initialized);
owned = TryAcquireSRWLockExclusive(&mutex->lock);
if (owned) {
trace_qemu_mutex_locked(mutex);
@@ -73,6 +78,7 @@ int qemu_mutex_trylock(QemuMutex *mutex)
void qemu_mutex_unlock(QemuMutex *mutex)
{
+ assert(mutex->initialized);
trace_qemu_mutex_unlocked(mutex);
ReleaseSRWLockExclusive(&mutex->lock);
}
@@ -80,25 +86,31 @@ void qemu_mutex_unlock(QemuMutex *mutex)
void qemu_rec_mutex_init(QemuRecMutex *mutex)
{
InitializeCriticalSection(&mutex->lock);
+ mutex->initialized = true;
}
void qemu_rec_mutex_destroy(QemuRecMutex *mutex)
{
+ assert(mutex->initialized);
+ mutex->initialized = false;
DeleteCriticalSection(&mutex->lock);
}
void qemu_rec_mutex_lock(QemuRecMutex *mutex)
{
+ assert(mutex->initialized);
EnterCriticalSection(&mutex->lock);
}
int qemu_rec_mutex_trylock(QemuRecMutex *mutex)
{
+ assert(mutex->initialized);
return !TryEnterCriticalSection(&mutex->lock);
}
void qemu_rec_mutex_unlock(QemuRecMutex *mutex)
{
+ assert(mutex->initialized);
LeaveCriticalSection(&mutex->lock);
}
@@ -106,25 +118,31 @@ void qemu_cond_init(QemuCond *cond)
{
memset(cond, 0, sizeof(*cond));
InitializeConditionVariable(&cond->var);
+ cond->initialized = true;
}
void qemu_cond_destroy(QemuCond *cond)
{
+ assert(cond->initialized);
+ cond->initialized = false;
InitializeConditionVariable(&cond->var);
}
void qemu_cond_signal(QemuCond *cond)
{
+ assert(cond->initialized);
WakeConditionVariable(&cond->var);
}
void qemu_cond_broadcast(QemuCond *cond)
{
+ assert(cond->initialized);
WakeAllConditionVariable(&cond->var);
}
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
{
+ assert(cond->initialized);
trace_qemu_mutex_unlocked(mutex);
SleepConditionVariableSRW(&cond->var, &mutex->lock, INFINITE, 0);
trace_qemu_mutex_locked(mutex);
@@ -134,21 +152,28 @@ void qemu_sem_init(QemuSemaphore *sem, int init)
{
/* Manual reset. */
sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL);
+ sem->initialized = true;
}
void qemu_sem_destroy(QemuSemaphore *sem)
{
+ assert(sem->initialized);
+ sem->initialized = false;
CloseHandle(sem->sema);
}
void qemu_sem_post(QemuSemaphore *sem)
{
+ assert(sem->initialized);
ReleaseSemaphore(sem->sema, 1, NULL);
}
int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
{
- int rc = WaitForSingleObject(sem->sema, ms);
+ int rc;
+
+ assert(sem->initialized);
+ rc = WaitForSingleObject(sem->sema, ms);
if (rc == WAIT_OBJECT_0) {
return 0;
}
@@ -160,6 +185,7 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
void qemu_sem_wait(QemuSemaphore *sem)
{
+ assert(sem->initialized);
if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) {
error_exit(GetLastError(), __func__);
}
@@ -193,15 +219,19 @@ void qemu_event_init(QemuEvent *ev, bool init)
/* Manual reset. */
ev->event = CreateEvent(NULL, TRUE, TRUE, NULL);
ev->value = (init ? EV_SET : EV_FREE);
+ ev->initialized = true;
}
void qemu_event_destroy(QemuEvent *ev)
{
+ assert(ev->initialized);
+ ev->initialized = false;
CloseHandle(ev->event);
}
void qemu_event_set(QemuEvent *ev)
{
+ assert(ev->initialized);
/* qemu_event_set has release semantics, but because it *loads*
* ev->value we need a full memory barrier here.
*/
@@ -218,6 +248,7 @@ void qemu_event_reset(QemuEvent *ev)
{
unsigned value;
+ assert(ev->initialized);
value = atomic_read(&ev->value);
smp_mb_acquire();
if (value == EV_SET) {
@@ -232,6 +263,7 @@ void qemu_event_wait(QemuEvent *ev)
{
unsigned value;
+ assert(ev->initialized);
value = atomic_read(&ev->value);
smp_mb_acquire();
if (value != EV_SET) {
diff --git a/vl.c b/vl.c
index 36ff3f4..d17c863 100644
--- a/vl.c
+++ b/vl.c
@@ -3933,9 +3933,13 @@ int main(int argc, char **argv, char **envp)
configure_rtc(opts);
break;
case QEMU_OPTION_tb_size:
- tcg_tb_size = strtol(optarg, NULL, 0);
- if (tcg_tb_size < 0) {
- tcg_tb_size = 0;
+ if (!tcg_enabled()) {
+ error_report("TCG is disabled");
+ exit(1);
+ }
+ if (qemu_strtoul(optarg, NULL, 0, &tcg_tb_size) < 0) {
+ error_report("Invalid argument to -tb-size");
+ exit(1);
}
break;
case QEMU_OPTION_icount:
@@ -4481,7 +4485,9 @@ int main(int argc, char **argv, char **envp)
qemu_opts_del(icount_opts);
}
- qemu_tcg_configure(accel_opts, &error_fatal);
+ if (tcg_enabled()) {
+ qemu_tcg_configure(accel_opts, &error_fatal);
+ }
if (default_net) {
QemuOptsList *net = qemu_find_opts("net");