* QOM interface fix (Eduardo)
* RTC fixes (Gaohuai, Igor) * Memory leak fixes (Li Qiang, me) * Ctrl-a b regression (Marc-André) * Stubs cleanups and fixes (Leif, me) * hxtool tweak (me) * HAX support (Vincent) * QemuThread, exec.c and SCSI fixes (Roman, Xinhua, me) * PC_COMPAT_2_8 fix (Marcelo) * stronger bitmap assertions (Peter) -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQExBAABCAAbBQJYggc9FBxwYm9uemluaUByZWRoYXQuY29tAAoJEL/70l94x66D 5pMH/092iVHw1la8VmphQd8W7hkCHckvVbwaEJ+n4BP8MjeUNmYFJX+op9Qlpqfe ekYqQgK69v2UwuofVK2gqS+Y2EyFHivTESk5pS3SM3lTewV1fzCM/HVG3pTxV/ol V+eBnp+shrfNG3Eg7YThTqx4LkDUp24Pd3HJVblQZMVpqGzL2xUuUQzSf8F/eeQJ xO61pm0ovpCY5MCg3kPLx8GIkPAmcXo5jhMCTz5aLnQW6TO/mwx271a4UE2RTLZ7 cFjNhxdGSzlnn2RwId4HVYWGU42taW6mpa8NX1hVVUXa1A2qlAfi5N/WLaH0aGYR J5ZTIaXdPUBx2SrUmd8udj4a818= =H5BQ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging * QOM interface fix (Eduardo) * RTC fixes (Gaohuai, Igor) * Memory leak fixes (Li Qiang, me) * Ctrl-a b regression (Marc-André) * Stubs cleanups and fixes (Leif, me) * hxtool tweak (me) * HAX support (Vincent) * QemuThread, exec.c and SCSI fixes (Roman, Xinhua, me) * PC_COMPAT_2_8 fix (Marcelo) * stronger bitmap assertions (Peter) # gpg: Signature made Fri 20 Jan 2017 12:49:01 GMT # gpg: using RSA key 0xBFFBD25F78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: (35 commits) pc.h: move x-mach-use-reliable-get-clock compat entry to PC_COMPAT_2_8 bitmap: assert that start and nr are non negative Revert "win32: don't run subprocess tests on Mingw32 platform" hax: add Darwin support Plumb the HAXM-based hardware acceleration support target/i386: Add Intel HAX files kvm: move cpu synchronization code KVM: PPC: eliminate unnecessary duplicate constants ramblock-notifier: new char: fix ctrl-a b not working exec: Add missing rcu_read_unlock x86: ioapic: fix fail migration when irqchip=split x86: ioapic: dump version for "info ioapic" x86: ioapic: add traces for ioapic hxtool: emit Texinfo headings as @subsection qemu-thread: fix qemu_thread_set_name() race in qemu_thread_create() serial: fix memory leak in serial exit scsi-block: fix direction of BYTCHK test for VERIFY commands pc: fix crash in rtc_set_memory() if initial cpu is marked as hotplugged acpi: filter based on CONFIG_ACPI_X86 rather than TARGET ... # Conflicts: # include/hw/i386/pc.h
This commit is contained in:
commit
598cf1c805
MAINTAINERSMakefile.targetarch_init.cconfigurecpus.cexec.cgdbstub.chax-stub.ciohandler.c
hw
include
exec
hw
qemu
qom
sysemu
migration
monitor.cnuma.cqemu-char.cqemu-options-wrapper.hqemu-options.hxqom
scripts
stubs
Makefile.objscpus.cfdset-add-fd.cfdset-find-fd.cfdset-get-fd.cfdset-remove-fd.cfdset.cget-next-serial.ciohandler.ckvm.cmigration-colo.cmon-is-qmp.cmonitor-init.cmonitor.creplay-user.creset.c
target
@ -1501,6 +1501,7 @@ M: Riku Voipio <riku.voipio@iki.fi>
|
||||
S: Maintained
|
||||
F: thunk.c
|
||||
F: user-exec.c
|
||||
F: user-exec-stub.c
|
||||
|
||||
BSD user
|
||||
S: Orphan
|
||||
|
@ -97,6 +97,7 @@ obj-y += target/$(TARGET_BASE_ARCH)/
|
||||
obj-y += disas.o
|
||||
obj-y += tcg-runtime.o
|
||||
obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o
|
||||
obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o
|
||||
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
|
||||
|
||||
obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/decContext.o
|
||||
@ -115,7 +116,7 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) \
|
||||
-I$(SRC_PATH)/linux-user
|
||||
|
||||
obj-y += linux-user/
|
||||
obj-y += gdbstub.o thunk.o user-exec.o
|
||||
obj-y += gdbstub.o thunk.o user-exec.o user-exec-stub.o
|
||||
|
||||
endif #CONFIG_LINUX_USER
|
||||
|
||||
@ -128,7 +129,7 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ABI_DIR) \
|
||||
-I$(SRC_PATH)/bsd-user/$(HOST_VARIANT_DIR)
|
||||
|
||||
obj-y += bsd-user/
|
||||
obj-y += gdbstub.o user-exec.o
|
||||
obj-y += gdbstub.o user-exec.o user-exec-stub.o
|
||||
|
||||
endif #CONFIG_BSD_USER
|
||||
|
||||
|
21
arch_init.c
21
arch_init.c
@ -28,7 +28,6 @@
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/audio/audio.h"
|
||||
#include "hw/smbios/smbios.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qmp-commands.h"
|
||||
@ -235,26 +234,6 @@ void audio_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
void do_acpitable_option(const QemuOpts *opts)
|
||||
{
|
||||
#ifdef TARGET_I386
|
||||
Error *err = NULL;
|
||||
|
||||
acpi_table_add(opts, &err);
|
||||
if (err) {
|
||||
error_reportf_err(err, "Wrong acpi table provided: ");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void do_smbios_option(QemuOpts *opts)
|
||||
{
|
||||
#ifdef TARGET_I386
|
||||
smbios_entry_add(opts);
|
||||
#endif
|
||||
}
|
||||
|
||||
int kvm_available(void)
|
||||
{
|
||||
#ifdef CONFIG_KVM
|
||||
|
27
configure
vendored
27
configure
vendored
@ -228,7 +228,7 @@ vhost_net="no"
|
||||
vhost_scsi="no"
|
||||
vhost_vsock="no"
|
||||
kvm="no"
|
||||
colo="yes"
|
||||
hax="no"
|
||||
rdma=""
|
||||
gprof="no"
|
||||
debug_tcg="no"
|
||||
@ -562,6 +562,7 @@ CYGWIN*)
|
||||
;;
|
||||
MINGW32*)
|
||||
mingw32="yes"
|
||||
hax="yes"
|
||||
audio_possible_drivers="dsound sdl"
|
||||
if check_include dsound.h; then
|
||||
audio_drv_list="dsound"
|
||||
@ -611,6 +612,7 @@ OpenBSD)
|
||||
Darwin)
|
||||
bsd="yes"
|
||||
darwin="yes"
|
||||
hax="yes"
|
||||
LDFLAGS_SHARED="-bundle -undefined dynamic_lookup"
|
||||
if [ "$cpu" = "x86_64" ] ; then
|
||||
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
|
||||
@ -920,9 +922,9 @@ for opt do
|
||||
;;
|
||||
--enable-kvm) kvm="yes"
|
||||
;;
|
||||
--disable-colo) colo="no"
|
||||
--disable-hax) hax="no"
|
||||
;;
|
||||
--enable-colo) colo="yes"
|
||||
--enable-hax) hax="yes"
|
||||
;;
|
||||
--disable-tcg-interpreter) tcg_interpreter="no"
|
||||
;;
|
||||
@ -1372,7 +1374,7 @@ disabled with --disable-FEATURE, default is enabled if available:
|
||||
fdt fdt device tree
|
||||
bluez bluez stack connectivity
|
||||
kvm KVM acceleration support
|
||||
colo COarse-grain LOck-stepping VM for Non-stop Service
|
||||
hax HAX acceleration support
|
||||
rdma RDMA-based migration support
|
||||
vde support for vde network
|
||||
netmap support for netmap network
|
||||
@ -3077,7 +3079,7 @@ fi
|
||||
|
||||
# g_test_trap_subprocess added in 2.38. Used by some tests.
|
||||
glib_subprocess=yes
|
||||
if test "$mingw32" = "yes" || ! $pkg_config --atleast-version=2.38 glib-2.0; then
|
||||
if ! $pkg_config --atleast-version=2.38 glib-2.0; then
|
||||
glib_subprocess=no
|
||||
fi
|
||||
|
||||
@ -5062,7 +5064,7 @@ echo "Linux AIO support $linux_aio"
|
||||
echo "ATTR/XATTR support $attr"
|
||||
echo "Install blobs $blobs"
|
||||
echo "KVM support $kvm"
|
||||
echo "COLO support $colo"
|
||||
echo "HAX support $hax"
|
||||
echo "RDMA support $rdma"
|
||||
echo "TCG interpreter $tcg_interpreter"
|
||||
echo "fdt support $fdt"
|
||||
@ -5701,10 +5703,6 @@ if have_backend "syslog"; then
|
||||
fi
|
||||
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
|
||||
|
||||
if test "$colo" = "yes"; then
|
||||
echo "CONFIG_COLO=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$rdma" = "yes" ; then
|
||||
echo "CONFIG_RDMA=y" >> $config_host_mak
|
||||
fi
|
||||
@ -6050,6 +6048,15 @@ case "$target_name" in
|
||||
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 test "$target_bigendian" = "yes" ; then
|
||||
echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
|
||||
fi
|
||||
|
79
cpus.c
79
cpus.c
@ -33,7 +33,9 @@
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "sysemu/dma.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hax.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
@ -1220,6 +1222,46 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *qemu_hax_cpu_thread_fn(void *arg)
|
||||
{
|
||||
CPUState *cpu = arg;
|
||||
int r;
|
||||
qemu_thread_get_self(cpu->thread);
|
||||
qemu_mutex_lock(&qemu_global_mutex);
|
||||
|
||||
cpu->thread_id = qemu_get_thread_id();
|
||||
cpu->created = true;
|
||||
cpu->halted = 0;
|
||||
current_cpu = cpu;
|
||||
|
||||
hax_init_vcpu(cpu);
|
||||
qemu_cond_signal(&qemu_cpu_cond);
|
||||
|
||||
while (1) {
|
||||
if (cpu_can_run(cpu)) {
|
||||
r = hax_smp_cpu_exec(cpu);
|
||||
if (r == EXCP_DEBUG) {
|
||||
cpu_handle_guest_debug(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
while (cpu_thread_is_idle(cpu)) {
|
||||
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
SleepEx(0, TRUE);
|
||||
#endif
|
||||
qemu_wait_io_event_common(cpu);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void CALLBACK dummy_apc_func(ULONG_PTR unused)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static void qemu_cpu_kick_thread(CPUState *cpu)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
@ -1235,7 +1277,13 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
|
||||
exit(1);
|
||||
}
|
||||
#else /* _WIN32 */
|
||||
abort();
|
||||
if (!qemu_cpu_is_self(cpu)) {
|
||||
if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) {
|
||||
fprintf(stderr, "%s: QueueUserAPC failed with error %lu\n",
|
||||
__func__, GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1258,6 +1306,13 @@ void qemu_cpu_kick(CPUState *cpu)
|
||||
if (tcg_enabled()) {
|
||||
qemu_cpu_kick_no_halt();
|
||||
} else {
|
||||
if (hax_enabled()) {
|
||||
/*
|
||||
* FIXME: race condition with the exit_request check in
|
||||
* hax_vcpu_hax_exec
|
||||
*/
|
||||
cpu->exit_request = 1;
|
||||
}
|
||||
qemu_cpu_kick_thread(cpu);
|
||||
}
|
||||
}
|
||||
@ -1418,6 +1473,26 @@ static void qemu_tcg_init_vcpu(CPUState *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
static void qemu_hax_start_vcpu(CPUState *cpu)
|
||||
{
|
||||
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||
|
||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
|
||||
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HAX",
|
||||
cpu->cpu_index);
|
||||
qemu_thread_create(cpu->thread, thread_name, qemu_hax_cpu_thread_fn,
|
||||
cpu, QEMU_THREAD_JOINABLE);
|
||||
#ifdef _WIN32
|
||||
cpu->hThread = qemu_thread_get_handle(cpu->thread);
|
||||
#endif
|
||||
while (!cpu->created) {
|
||||
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void qemu_kvm_start_vcpu(CPUState *cpu)
|
||||
{
|
||||
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||
@ -1468,6 +1543,8 @@ void qemu_init_vcpu(CPUState *cpu)
|
||||
|
||||
if (kvm_enabled()) {
|
||||
qemu_kvm_start_vcpu(cpu);
|
||||
} else if (hax_enabled()) {
|
||||
qemu_hax_start_vcpu(cpu);
|
||||
} else if (tcg_enabled()) {
|
||||
qemu_tcg_init_vcpu(cpu);
|
||||
} else {
|
||||
|
6
exec.c
6
exec.c
@ -1687,6 +1687,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
||||
qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_HUGEPAGE);
|
||||
/* MADV_DONTFORK is also needed by KVM in absence of synchronous MMU */
|
||||
qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_DONTFORK);
|
||||
ram_block_notify_add(new_block->host, new_block->max_length);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1817,6 +1818,10 @@ void qemu_ram_free(RAMBlock *block)
|
||||
return;
|
||||
}
|
||||
|
||||
if (block->host) {
|
||||
ram_block_notify_remove(block->host, block->max_length);
|
||||
}
|
||||
|
||||
qemu_mutex_lock_ramlist();
|
||||
QLIST_REMOVE_RCU(block, next);
|
||||
ram_list.mru_block = NULL;
|
||||
@ -2960,6 +2965,7 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_
|
||||
if (!memory_access_is_direct(mr, is_write)) {
|
||||
l = memory_access_size(mr, l, addr);
|
||||
if (!memory_region_access_valid(mr, xlat, l, is_write)) {
|
||||
rcu_read_unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define MAX_PACKET_LENGTH 4096
|
||||
|
||||
#include "qemu/sockets.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
34
hax-stub.c
Normal file
34
hax-stub.c
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* QEMU HAXM support
|
||||
*
|
||||
* Copyright (c) 2015, Intel Corporation
|
||||
*
|
||||
* Copyright 2016 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/hax.h"
|
||||
|
||||
int hax_sync_vcpus(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hax_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int hax_smp_cpu_exec(CPUState *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
devices-dirs-$(call land, $(CONFIG_VIRTIO),$(call land,$(CONFIG_VIRTFS),$(CONFIG_PCI))) += 9pfs/
|
||||
devices-dirs-$(CONFIG_ACPI) += acpi/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += acpi/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += adc/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += audio/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += block/
|
||||
@ -29,11 +29,11 @@ devices-dirs-$(CONFIG_SOFTMMU) += timer/
|
||||
devices-dirs-$(CONFIG_TPM) += tpm/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += usb/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += vfio/
|
||||
devices-dirs-$(CONFIG_VIRTIO) += virtio/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += virtio/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += watchdog/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += xen/
|
||||
devices-dirs-$(CONFIG_MEM_HOTPLUG) += mem/
|
||||
devices-dirs-$(CONFIG_SMBIOS) += smbios/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += smbios/
|
||||
devices-dirs-y += core/
|
||||
common-obj-y += $(devices-dirs-y)
|
||||
obj-y += $(devices-dirs-y)
|
||||
|
@ -1,10 +1,19 @@
|
||||
ifeq ($(CONFIG_ACPI),y)
|
||||
common-obj-$(CONFIG_ACPI_X86) += core.o piix4.o pcihp.o
|
||||
common-obj-$(CONFIG_ACPI_X86_ICH) += ich9.o tco.o
|
||||
common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o
|
||||
common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
|
||||
common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
|
||||
common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
|
||||
common-obj-$(CONFIG_ACPI) += acpi_interface.o
|
||||
common-obj-$(CONFIG_ACPI) += bios-linker-loader.o
|
||||
common-obj-$(CONFIG_ACPI) += aml-build.o
|
||||
common-obj-$(call land,$(CONFIG_ACPI),$(CONFIG_IPMI)) += ipmi.o
|
||||
common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
|
||||
|
||||
common-obj-y += acpi_interface.o
|
||||
common-obj-y += bios-linker-loader.o
|
||||
common-obj-y += aml-build.o
|
||||
|
||||
common-obj-$(CONFIG_IPMI) += ipmi.o
|
||||
common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o
|
||||
else
|
||||
common-obj-y += acpi-stub.o
|
||||
endif
|
||||
common-obj-$(CONFIG_ALL) += acpi-stub.o ipmi-stub.o
|
||||
|
29
hw/acpi/acpi-stub.c
Normal file
29
hw/acpi/acpi-stub.c
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* ACPI stubs for platforms that don't support ACPI.
|
||||
*
|
||||
* Copyright (c) 2006 Fabrice Bellard
|
||||
* Copyright (c) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "hw/acpi/acpi.h"
|
||||
|
||||
void acpi_table_add(const QemuOpts *opts, Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
}
|
@ -906,6 +906,16 @@ void serial_realize_core(SerialState *s, Error **errp)
|
||||
void serial_exit_core(SerialState *s)
|
||||
{
|
||||
qemu_chr_fe_deinit(&s->chr);
|
||||
|
||||
timer_del(s->modem_status_poll);
|
||||
timer_free(s->modem_status_poll);
|
||||
|
||||
timer_del(s->fifo_timeout_timer);
|
||||
timer_free(s->fifo_timeout_timer);
|
||||
|
||||
fifo8_destroy(&s->recv_fifo);
|
||||
fifo8_destroy(&s->xmit_fifo);
|
||||
|
||||
qemu_unregister_reset(serial_reset, s);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# core qdev-related obj files, also used by *-user:
|
||||
common-obj-y += qdev.o qdev-properties.o
|
||||
common-obj-y += bus.o
|
||||
common-obj-y += bus.o reset.o
|
||||
common-obj-y += fw-path-provider.o
|
||||
# irq.o needed for qdev GPIO handling:
|
||||
common-obj-y += irq.o
|
||||
|
72
hw/core/reset.c
Normal file
72
hw/core/reset.c
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Reset handlers.
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright (c) 2016 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "sysemu/reset.h"
|
||||
|
||||
/* reset/shutdown handler */
|
||||
|
||||
typedef struct QEMUResetEntry {
|
||||
QTAILQ_ENTRY(QEMUResetEntry) entry;
|
||||
QEMUResetHandler *func;
|
||||
void *opaque;
|
||||
} QEMUResetEntry;
|
||||
|
||||
static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers =
|
||||
QTAILQ_HEAD_INITIALIZER(reset_handlers);
|
||||
|
||||
void qemu_register_reset(QEMUResetHandler *func, void *opaque)
|
||||
{
|
||||
QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry));
|
||||
|
||||
re->func = func;
|
||||
re->opaque = opaque;
|
||||
QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
|
||||
}
|
||||
|
||||
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
|
||||
{
|
||||
QEMUResetEntry *re;
|
||||
|
||||
QTAILQ_FOREACH(re, &reset_handlers, entry) {
|
||||
if (re->func == func && re->opaque == opaque) {
|
||||
QTAILQ_REMOVE(&reset_handlers, re, entry);
|
||||
g_free(re);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void qemu_devices_reset(void)
|
||||
{
|
||||
QEMUResetEntry *re, *nre;
|
||||
|
||||
/* reset all devices */
|
||||
QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
|
||||
re->func(re->opaque);
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "cpu.h"
|
||||
#include "hw/i386/apic_internal.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "target/i386/kvm_i386.h"
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "hw/i386/apic_internal.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
@ -1820,8 +1820,10 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
|
||||
|
||||
/* increment the number of CPUs */
|
||||
pcms->boot_cpus++;
|
||||
if (dev->hotplugged) {
|
||||
if (pcms->rtc) {
|
||||
rtc_set_cpus_count(pcms->rtc, pcms->boot_cpus);
|
||||
}
|
||||
if (pcms->fw_cfg) {
|
||||
fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "hw/i386/apic.h"
|
||||
#include "hw/i386/apic_internal.h"
|
||||
#include "trace.h"
|
||||
#include "sysemu/hax.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "hw/qdev.h"
|
||||
#include "hw/sysbus.h"
|
||||
@ -316,7 +317,7 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
/* Note: We need at least 1M to map the VAPIC option ROM */
|
||||
if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
|
||||
ram_size >= 1024 * 1024) {
|
||||
!hax_enabled() && ram_size >= 1024 * 1024) {
|
||||
vapic = sysbus_create_simple("kvmvapic", -1, NULL);
|
||||
}
|
||||
s->vapic = vapic;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "target/i386/cpu.h"
|
||||
#include "hw/i386/apic-msidef.h"
|
||||
#include "hw/i386/x86-iommu.h"
|
||||
#include "trace.h"
|
||||
|
||||
//#define DEBUG_IOAPIC
|
||||
|
||||
@ -115,6 +116,7 @@ static void ioapic_service(IOAPICCommonState *s)
|
||||
s->irr &= ~mask;
|
||||
} else {
|
||||
coalesce = s->ioredtbl[i] & IOAPIC_LVT_REMOTE_IRR;
|
||||
trace_ioapic_set_remote_irr(i);
|
||||
s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR;
|
||||
}
|
||||
|
||||
@ -220,6 +222,8 @@ void ioapic_eoi_broadcast(int vector)
|
||||
uint64_t entry;
|
||||
int i, n;
|
||||
|
||||
trace_ioapic_eoi_broadcast(vector);
|
||||
|
||||
for (i = 0; i < MAX_IOAPICS; i++) {
|
||||
s = ioapics[i];
|
||||
if (!s) {
|
||||
@ -229,6 +233,7 @@ void ioapic_eoi_broadcast(int vector)
|
||||
entry = s->ioredtbl[n];
|
||||
if ((entry & IOAPIC_LVT_REMOTE_IRR)
|
||||
&& (entry & IOAPIC_VECTOR_MASK) == vector) {
|
||||
trace_ioapic_clear_remote_irr(n, vector);
|
||||
s->ioredtbl[n] = entry & ~IOAPIC_LVT_REMOTE_IRR;
|
||||
if (!(entry & IOAPIC_LVT_MASKED) && (s->irr & (1 << n))) {
|
||||
ioapic_service(s);
|
||||
@ -256,7 +261,9 @@ ioapic_mem_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
int index;
|
||||
uint32_t val = 0;
|
||||
|
||||
switch (addr & 0xff) {
|
||||
addr &= 0xff;
|
||||
|
||||
switch (addr) {
|
||||
case IOAPIC_IOREGSEL:
|
||||
val = s->ioregsel;
|
||||
break;
|
||||
@ -286,6 +293,9 @@ ioapic_mem_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
DPRINTF("read: %08x = %08x\n", s->ioregsel, val);
|
||||
break;
|
||||
}
|
||||
|
||||
trace_ioapic_mem_read(addr, size, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -324,7 +334,10 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
IOAPICCommonState *s = opaque;
|
||||
int index;
|
||||
|
||||
switch (addr & 0xff) {
|
||||
addr &= 0xff;
|
||||
trace_ioapic_mem_write(addr, size, val);
|
||||
|
||||
switch (addr) {
|
||||
case IOAPIC_IOREGSEL:
|
||||
s->ioregsel = val;
|
||||
break;
|
||||
@ -426,6 +439,11 @@ static void ioapic_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
k->realize = ioapic_realize;
|
||||
/*
|
||||
* If APIC is in kernel, we need to update the kernel cache after
|
||||
* migration, otherwise first 24 gsi routes will be invalid.
|
||||
*/
|
||||
k->post_load = ioapic_update_kvm_routes;
|
||||
dc->reset = ioapic_reset_common;
|
||||
dc->props = ioapic_properties;
|
||||
}
|
||||
|
@ -58,7 +58,8 @@ void ioapic_print_redtbl(Monitor *mon, IOAPICCommonState *s)
|
||||
uint32_t remote_irr = 0;
|
||||
int i;
|
||||
|
||||
monitor_printf(mon, "ioapic id=0x%02x sel=0x%02x", s->id, s->ioregsel);
|
||||
monitor_printf(mon, "ioapic ver=0x%x id=0x%02x sel=0x%02x",
|
||||
s->version, s->id, s->ioregsel);
|
||||
if (s->ioregsel) {
|
||||
monitor_printf(mon, " (redir[%u])\n",
|
||||
(s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1);
|
||||
|
@ -14,6 +14,13 @@ apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t
|
||||
apic_mem_readl(uint64_t addr, uint32_t val) "%"PRIx64" = %08x"
|
||||
apic_mem_writel(uint64_t addr, uint32_t val) "%"PRIx64" = %08x"
|
||||
|
||||
# hw/intc/ioapic.c
|
||||
ioapic_set_remote_irr(int n) "set remote irr for pin %d"
|
||||
ioapic_clear_remote_irr(int n, int vector) "clear remote irr for pin %d vector %d"
|
||||
ioapic_eoi_broadcast(int vector) "EOI broadcast for vector %d"
|
||||
ioapic_mem_read(uint8_t addr, uint8_t size, uint32_t val) "ioapic mem read addr 0x%"PRIx8" size 0x%"PRIx8" retval 0x%"PRIx32
|
||||
ioapic_mem_write(uint8_t addr, uint8_t size, uint32_t val) "ioapic mem write addr 0x%"PRIx8" size 0x%"PRIx8" val 0x%"PRIx32
|
||||
|
||||
# hw/intc/slavio_intctl.c
|
||||
slavio_intctl_mem_readl(uint32_t cpu, uint64_t addr, uint32_t ret) "read cpu %d reg 0x%"PRIx64" = %x"
|
||||
slavio_intctl_mem_writel(uint32_t cpu, uint64_t addr, uint32_t val) "write cpu %d reg 0x%"PRIx64" = %x"
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "hw/hw.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "hw/qdev.h"
|
||||
|
||||
//#define VMPORT_DEBUG
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "hw/hw.h"
|
||||
#include "qemu/log.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "target/ppc/cpu.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
|
@ -29,9 +29,9 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "e500.h"
|
||||
|
||||
#define MAX_CPUS 32
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "migration/migration.h"
|
||||
#include "mmu-hash64.h"
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
@ -9,7 +10,6 @@
|
||||
#include "mmu-hash64.h"
|
||||
#include "cpu-models.h"
|
||||
#include "trace.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "hw/ppc/spapr_ovec.h"
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "s390-pci-bus.h"
|
||||
#include "exec/memory-internal.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
|
||||
/* #define DEBUG_S390PCI_INST */
|
||||
#ifdef DEBUG_S390PCI_INST
|
||||
|
@ -683,14 +683,14 @@ static int megasas_map_dcmd(MegasasState *s, MegasasCmd *cmd)
|
||||
trace_megasas_dcmd_invalid_sge(cmd->index,
|
||||
cmd->frame->header.sge_count);
|
||||
cmd->iov_size = 0;
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
iov_pa = megasas_sgl_get_addr(cmd, &cmd->frame->dcmd.sgl);
|
||||
iov_size = megasas_sgl_get_len(cmd, &cmd->frame->dcmd.sgl);
|
||||
pci_dma_sglist_init(&cmd->qsg, PCI_DEVICE(s), 1);
|
||||
qemu_sglist_add(&cmd->qsg, iov_pa, iov_size);
|
||||
cmd->iov_size = iov_size;
|
||||
return cmd->iov_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void megasas_finish_dcmd(MegasasCmd *cmd, uint32_t iov_size)
|
||||
@ -1559,19 +1559,20 @@ static const struct dcmd_cmd_tbl_t {
|
||||
|
||||
static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd)
|
||||
{
|
||||
int opcode, len;
|
||||
int opcode;
|
||||
int retval = 0;
|
||||
size_t len;
|
||||
const struct dcmd_cmd_tbl_t *cmdptr = dcmd_cmd_tbl;
|
||||
|
||||
opcode = le32_to_cpu(cmd->frame->dcmd.opcode);
|
||||
trace_megasas_handle_dcmd(cmd->index, opcode);
|
||||
len = megasas_map_dcmd(s, cmd);
|
||||
if (len < 0) {
|
||||
if (megasas_map_dcmd(s, cmd) < 0) {
|
||||
return MFI_STAT_MEMORY_NOT_AVAILABLE;
|
||||
}
|
||||
while (cmdptr->opcode != -1 && cmdptr->opcode != opcode) {
|
||||
cmdptr++;
|
||||
}
|
||||
len = cmd->iov_size;
|
||||
if (cmdptr->opcode == -1) {
|
||||
trace_megasas_dcmd_unhandled(cmd->index, opcode, len);
|
||||
retval = megasas_dcmd_dummy(s, cmd);
|
||||
|
@ -2701,7 +2701,7 @@ static bool scsi_block_is_passthrough(SCSIDiskState *s, uint8_t *buf)
|
||||
* for the number of logical blocks specified in the length
|
||||
* field). For other modes, do not use scatter/gather operation.
|
||||
*/
|
||||
if ((buf[1] & 6) != 2) {
|
||||
if ((buf[1] & 6) == 2) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -1,2 +1,10 @@
|
||||
common-obj-$(CONFIG_SMBIOS) += smbios.o
|
||||
common-obj-$(call land,$(CONFIG_SMBIOS),$(CONFIG_IPMI)) += smbios_type_38.o
|
||||
ifeq ($(CONFIG_SMBIOS),y)
|
||||
common-obj-y += smbios.o
|
||||
common-obj-$(CONFIG_IPMI) += smbios_type_38.o
|
||||
common-obj-$(call lnot,$(CONFIG_IPMI)) += smbios_type_38-stub.o
|
||||
else
|
||||
common-obj-y += smbios-stub.o
|
||||
endif
|
||||
|
||||
common-obj-$(CONFIG_ALL) += smbios-stub.o
|
||||
common-obj-$(CONFIG_ALL) += smbios_type_38-stub.o
|
||||
|
31
hw/smbios/smbios-stub.c
Normal file
31
hw/smbios/smbios-stub.c
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* SMBIOS stubs for platforms that don't support SMBIOS.
|
||||
*
|
||||
* Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
|
||||
* VA Linux Systems Japan K.K.
|
||||
* Copyright (c) 2016 Leif Lindholm <leif.lindholm@linaro.org>
|
||||
* Linaro Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "hw/smbios/smbios.h"
|
||||
|
||||
void smbios_entry_add(QemuOpts *opts, Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
}
|
@ -882,7 +882,7 @@ static void save_opt(const char **dest, QemuOpts *opts, const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
void smbios_entry_add(QemuOpts *opts)
|
||||
void smbios_entry_add(QemuOpts *opts, Error **errp)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
|
@ -946,11 +946,23 @@ static Property mc146818rtc_properties[] = {
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void rtc_resetdev(DeviceState *d)
|
||||
{
|
||||
RTCState *s = MC146818_RTC(d);
|
||||
|
||||
/* Reason: VM do suspend self will set 0xfe
|
||||
* Reset any values other than 0xfe(Guest suspend case) */
|
||||
if (s->cmos_data[0x0f] != 0xfe) {
|
||||
s->cmos_data[0x0f] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
static void rtc_class_initfn(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = rtc_realizefn;
|
||||
dc->reset = rtc_resetdev;
|
||||
dc->vmsd = &vmstate_rtc;
|
||||
dc->props = mc146818rtc_properties;
|
||||
/* Reason: needs to be wired up by rtc_init() */
|
||||
|
@ -407,7 +407,7 @@ static int init_event_notifier(EmulatedState *card)
|
||||
DPRINTF(card, 2, "event notifier creation failed\n");
|
||||
return -1;
|
||||
}
|
||||
event_notifier_set_handler(&card->notifier, false, card_event_handler);
|
||||
event_notifier_set_handler(&card->notifier, card_event_handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
ifeq ($(CONFIG_VIRTIO),y)
|
||||
common-obj-y += virtio-rng.o
|
||||
common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
|
||||
common-obj-y += virtio-bus.o
|
||||
@ -5,7 +6,10 @@ common-obj-y += virtio-mmio.o
|
||||
|
||||
obj-y += virtio.o virtio-balloon.o
|
||||
obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
|
||||
|
||||
obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock.o
|
||||
obj-y += virtio-crypto.o
|
||||
obj-$(CONFIG_VIRTIO_PCI) += virtio-crypto-pci.o
|
||||
endif
|
||||
|
||||
common-obj-$(call lnot,$(CONFIG_LINUX)) += vhost-stub.o
|
||||
common-obj-$(CONFIG_ALL) += vhost-stub.o
|
||||
|
@ -2082,10 +2082,10 @@ void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
|
||||
bool with_irqfd)
|
||||
{
|
||||
if (assign && !with_irqfd) {
|
||||
event_notifier_set_handler(&vq->guest_notifier, false,
|
||||
event_notifier_set_handler(&vq->guest_notifier,
|
||||
virtio_queue_guest_notifier_read);
|
||||
} else {
|
||||
event_notifier_set_handler(&vq->guest_notifier, false, NULL);
|
||||
event_notifier_set_handler(&vq->guest_notifier, NULL);
|
||||
}
|
||||
if (!assign) {
|
||||
/* Test and clear notifier before closing it,
|
||||
@ -2257,7 +2257,7 @@ static int virtio_device_start_ioeventfd_impl(VirtIODevice *vdev)
|
||||
err = r;
|
||||
goto assign_error;
|
||||
}
|
||||
event_notifier_set_handler(&vq->host_notifier, true,
|
||||
event_notifier_set_handler(&vq->host_notifier,
|
||||
virtio_queue_host_notifier_read);
|
||||
}
|
||||
|
||||
@ -2278,7 +2278,7 @@ assign_error:
|
||||
continue;
|
||||
}
|
||||
|
||||
event_notifier_set_handler(&vq->host_notifier, true, NULL);
|
||||
event_notifier_set_handler(&vq->host_notifier, NULL);
|
||||
r = virtio_bus_set_host_notifier(qbus, n, false);
|
||||
assert(r >= 0);
|
||||
}
|
||||
@ -2304,7 +2304,7 @@ static void virtio_device_stop_ioeventfd_impl(VirtIODevice *vdev)
|
||||
if (!virtio_queue_get_num(vdev, n)) {
|
||||
continue;
|
||||
}
|
||||
event_notifier_set_handler(&vq->host_notifier, true, NULL);
|
||||
event_notifier_set_handler(&vq->host_notifier, NULL);
|
||||
r = virtio_bus_set_host_notifier(qbus, n, false);
|
||||
assert(r >= 0);
|
||||
}
|
||||
|
@ -16,16 +16,12 @@
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
#define DIRTY_MEMORY_VGA 0
|
||||
#define DIRTY_MEMORY_CODE 1
|
||||
#define DIRTY_MEMORY_MIGRATION 2
|
||||
#define DIRTY_MEMORY_NUM 3 /* num of dirty bits */
|
||||
|
||||
#include "exec/cpu-common.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "exec/hwaddr.h"
|
||||
#endif
|
||||
#include "exec/memattrs.h"
|
||||
#include "exec/ramlist.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/int128.h"
|
||||
#include "qemu/notify.h"
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "hw/xen/xen.h"
|
||||
#include "exec/ramlist.h"
|
||||
|
||||
struct RAMBlock {
|
||||
struct rcu_head rcu;
|
||||
@ -35,6 +36,7 @@ struct RAMBlock {
|
||||
char idstr[256];
|
||||
/* RCU-enabled, writes protected by the ramlist lock */
|
||||
QLIST_ENTRY(RAMBlock) next;
|
||||
QLIST_HEAD(, RAMBlockNotifier) ramblock_notifiers;
|
||||
int fd;
|
||||
size_t page_size;
|
||||
};
|
||||
@ -50,51 +52,7 @@ static inline void *ramblock_ptr(RAMBlock *block, ram_addr_t offset)
|
||||
return (char *)block->host + offset;
|
||||
}
|
||||
|
||||
/* The dirty memory bitmap is split into fixed-size blocks to allow growth
|
||||
* under RCU. The bitmap for a block can be accessed as follows:
|
||||
*
|
||||
* rcu_read_lock();
|
||||
*
|
||||
* DirtyMemoryBlocks *blocks =
|
||||
* atomic_rcu_read(&ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]);
|
||||
*
|
||||
* ram_addr_t idx = (addr >> TARGET_PAGE_BITS) / DIRTY_MEMORY_BLOCK_SIZE;
|
||||
* unsigned long *block = blocks.blocks[idx];
|
||||
* ...access block bitmap...
|
||||
*
|
||||
* rcu_read_unlock();
|
||||
*
|
||||
* Remember to check for the end of the block when accessing a range of
|
||||
* addresses. Move on to the next block if you reach the end.
|
||||
*
|
||||
* Organization into blocks allows dirty memory to grow (but not shrink) under
|
||||
* RCU. When adding new RAMBlocks requires the dirty memory to grow, a new
|
||||
* DirtyMemoryBlocks array is allocated with pointers to existing blocks kept
|
||||
* the same. Other threads can safely access existing blocks while dirty
|
||||
* memory is being grown. When no threads are using the old DirtyMemoryBlocks
|
||||
* anymore it is freed by RCU (but the underlying blocks stay because they are
|
||||
* pointed to from the new DirtyMemoryBlocks).
|
||||
*/
|
||||
#define DIRTY_MEMORY_BLOCK_SIZE ((ram_addr_t)256 * 1024 * 8)
|
||||
typedef struct {
|
||||
struct rcu_head rcu;
|
||||
unsigned long *blocks[];
|
||||
} DirtyMemoryBlocks;
|
||||
|
||||
typedef struct RAMList {
|
||||
QemuMutex mutex;
|
||||
RAMBlock *mru_block;
|
||||
/* RCU-enabled, writes protected by the ramlist lock. */
|
||||
QLIST_HEAD(, RAMBlock) blocks;
|
||||
DirtyMemoryBlocks *dirty_memory[DIRTY_MEMORY_NUM];
|
||||
uint32_t version;
|
||||
} RAMList;
|
||||
extern RAMList ram_list;
|
||||
|
||||
ram_addr_t last_ram_offset(void);
|
||||
void qemu_mutex_lock_ramlist(void);
|
||||
void qemu_mutex_unlock_ramlist(void);
|
||||
|
||||
RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
|
||||
bool share, const char *mem_path,
|
||||
Error **errp);
|
||||
|
72
include/exec/ramlist.h
Normal file
72
include/exec/ramlist.h
Normal file
@ -0,0 +1,72 @@
|
||||
#ifndef RAMLIST_H
|
||||
#define RAMLIST_H
|
||||
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/rcu.h"
|
||||
|
||||
typedef struct RAMBlockNotifier RAMBlockNotifier;
|
||||
|
||||
#define DIRTY_MEMORY_VGA 0
|
||||
#define DIRTY_MEMORY_CODE 1
|
||||
#define DIRTY_MEMORY_MIGRATION 2
|
||||
#define DIRTY_MEMORY_NUM 3 /* num of dirty bits */
|
||||
|
||||
/* The dirty memory bitmap is split into fixed-size blocks to allow growth
|
||||
* under RCU. The bitmap for a block can be accessed as follows:
|
||||
*
|
||||
* rcu_read_lock();
|
||||
*
|
||||
* DirtyMemoryBlocks *blocks =
|
||||
* atomic_rcu_read(&ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]);
|
||||
*
|
||||
* ram_addr_t idx = (addr >> TARGET_PAGE_BITS) / DIRTY_MEMORY_BLOCK_SIZE;
|
||||
* unsigned long *block = blocks.blocks[idx];
|
||||
* ...access block bitmap...
|
||||
*
|
||||
* rcu_read_unlock();
|
||||
*
|
||||
* Remember to check for the end of the block when accessing a range of
|
||||
* addresses. Move on to the next block if you reach the end.
|
||||
*
|
||||
* Organization into blocks allows dirty memory to grow (but not shrink) under
|
||||
* RCU. When adding new RAMBlocks requires the dirty memory to grow, a new
|
||||
* DirtyMemoryBlocks array is allocated with pointers to existing blocks kept
|
||||
* the same. Other threads can safely access existing blocks while dirty
|
||||
* memory is being grown. When no threads are using the old DirtyMemoryBlocks
|
||||
* anymore it is freed by RCU (but the underlying blocks stay because they are
|
||||
* pointed to from the new DirtyMemoryBlocks).
|
||||
*/
|
||||
#define DIRTY_MEMORY_BLOCK_SIZE ((ram_addr_t)256 * 1024 * 8)
|
||||
typedef struct {
|
||||
struct rcu_head rcu;
|
||||
unsigned long *blocks[];
|
||||
} DirtyMemoryBlocks;
|
||||
|
||||
typedef struct RAMList {
|
||||
QemuMutex mutex;
|
||||
RAMBlock *mru_block;
|
||||
/* RCU-enabled, writes protected by the ramlist lock. */
|
||||
QLIST_HEAD(, RAMBlock) blocks;
|
||||
DirtyMemoryBlocks *dirty_memory[DIRTY_MEMORY_NUM];
|
||||
uint32_t version;
|
||||
QLIST_HEAD(, RAMBlockNotifier) ramblock_notifiers;
|
||||
} RAMList;
|
||||
extern RAMList ram_list;
|
||||
|
||||
void qemu_mutex_lock_ramlist(void);
|
||||
void qemu_mutex_unlock_ramlist(void);
|
||||
|
||||
struct RAMBlockNotifier {
|
||||
void (*ram_block_added)(RAMBlockNotifier *n, void *host, size_t size);
|
||||
void (*ram_block_removed)(RAMBlockNotifier *n, void *host, size_t size);
|
||||
QLIST_ENTRY(RAMBlockNotifier) next;
|
||||
};
|
||||
|
||||
void ram_block_notifier_add(RAMBlockNotifier *n);
|
||||
void ram_block_notifier_remove(RAMBlockNotifier *n);
|
||||
void ram_block_notify_add(void *host, size_t size);
|
||||
void ram_block_notify_remove(void *host, size_t size);
|
||||
|
||||
|
||||
#endif /* RAMLIST_H */
|
@ -12,11 +12,7 @@
|
||||
#include "hw/irq.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qemu/module.h"
|
||||
|
||||
typedef void QEMUResetHandler(void *opaque);
|
||||
|
||||
void qemu_register_reset(QEMUResetHandler *func, void *opaque);
|
||||
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
|
||||
#include "sysemu/reset.h"
|
||||
|
||||
void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||
|
||||
|
@ -376,15 +376,14 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||
|
||||
#define PC_COMPAT_2_8 \
|
||||
HW_COMPAT_2_8 \
|
||||
|
||||
|
||||
#define PC_COMPAT_2_7 \
|
||||
HW_COMPAT_2_7 \
|
||||
{\
|
||||
.driver = "kvmclock",\
|
||||
.property = "x-mach-use-reliable-get-clock",\
|
||||
.value = "off",\
|
||||
},\
|
||||
|
||||
#define PC_COMPAT_2_7 \
|
||||
HW_COMPAT_2_7 \
|
||||
{\
|
||||
.driver = TYPE_X86_CPU,\
|
||||
.property = "l3-cache",\
|
||||
|
@ -257,7 +257,7 @@ struct smbios_type_127 {
|
||||
struct smbios_structure_header header;
|
||||
} QEMU_PACKED;
|
||||
|
||||
void smbios_entry_add(QemuOpts *opts);
|
||||
void smbios_entry_add(QemuOpts *opts, Error **errp);
|
||||
void smbios_set_cpuid(uint32_t version, uint32_t features);
|
||||
void smbios_set_defaults(const char *manufacturer, const char *product,
|
||||
const char *version, bool legacy_mode,
|
||||
|
@ -34,9 +34,6 @@ int event_notifier_init(EventNotifier *, int active);
|
||||
void event_notifier_cleanup(EventNotifier *);
|
||||
int event_notifier_set(EventNotifier *);
|
||||
int event_notifier_test_and_clear(EventNotifier *);
|
||||
int event_notifier_set_handler(EventNotifier *,
|
||||
bool is_external,
|
||||
EventNotifierHandler *);
|
||||
|
||||
#ifdef CONFIG_POSIX
|
||||
void event_notifier_init_fd(EventNotifier *, int fd);
|
||||
|
@ -203,6 +203,21 @@ void qemu_set_fd_handler(int fd,
|
||||
IOHandler *fd_write,
|
||||
void *opaque);
|
||||
|
||||
|
||||
/**
|
||||
* event_notifier_set_handler: Register an EventNotifier with the main loop
|
||||
*
|
||||
* This function tells the main loop to wake up whenever the
|
||||
* #EventNotifier was set.
|
||||
*
|
||||
* @e: The #EventNotifier to be observed.
|
||||
*
|
||||
* @handler: A level-triggered callback that is fired when @e
|
||||
* has been set. @e is passed to it as a parameter.
|
||||
*/
|
||||
void event_notifier_set_handler(EventNotifier *e,
|
||||
EventNotifierHandler *handler);
|
||||
|
||||
GSource *iohandler_get_g_source(void);
|
||||
AioContext *iohandler_get_aio_context(void);
|
||||
#ifdef CONFIG_POSIX
|
||||
|
@ -227,6 +227,8 @@ struct CPUWatchpoint {
|
||||
struct KVMState;
|
||||
struct kvm_run;
|
||||
|
||||
struct hax_vcpu_state;
|
||||
|
||||
#define TB_JMP_CACHE_BITS 12
|
||||
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
|
||||
|
||||
@ -392,6 +394,9 @@ struct CPUState {
|
||||
(absolute value) offset as small as possible. This reduces code
|
||||
size, especially for hosts without large memory offsets. */
|
||||
uint32_t tcg_exit_req;
|
||||
|
||||
bool hax_vcpu_dirty;
|
||||
struct hax_vcpu_state *hax_vcpu;
|
||||
};
|
||||
|
||||
QTAILQ_HEAD(CPUTailQ, CPUState);
|
||||
|
@ -28,8 +28,6 @@ enum {
|
||||
extern const uint32_t arch_type;
|
||||
|
||||
void select_soundhw(const char *optarg);
|
||||
void do_acpitable_option(const QemuOpts *opts);
|
||||
void do_smbios_option(QemuOpts *opts);
|
||||
void audio_init(void);
|
||||
int kvm_available(void);
|
||||
int xen_available(void);
|
||||
|
56
include/sysemu/hax.h
Normal file
56
include/sysemu/hax.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* QEMU HAXM support
|
||||
*
|
||||
* Copyright IBM, Corp. 2008
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* Copyright (c) 2011 Intel Corporation
|
||||
* Written by:
|
||||
* Jiang Yunhong<yunhong.jiang@intel.com>
|
||||
* Xin Xiaohui<xiaohui.xin@intel.com>
|
||||
* Zhang Xiantao<xiantao.zhang@intel.com>
|
||||
*
|
||||
* Copyright 2016 Google, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_HAX_H
|
||||
#define QEMU_HAX_H
|
||||
|
||||
#include "config-host.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
int hax_sync_vcpus(void);
|
||||
int hax_init_vcpu(CPUState *cpu);
|
||||
int hax_smp_cpu_exec(CPUState *cpu);
|
||||
int hax_populate_ram(uint64_t va, uint32_t size);
|
||||
|
||||
void hax_cpu_synchronize_state(CPUState *cpu);
|
||||
void hax_cpu_synchronize_post_reset(CPUState *cpu);
|
||||
void hax_cpu_synchronize_post_init(CPUState *cpu);
|
||||
|
||||
#ifdef CONFIG_HAX
|
||||
|
||||
int hax_enabled(void);
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "exec/memory.h"
|
||||
int hax_vcpu_destroy(CPUState *cpu);
|
||||
void hax_raise_event(CPUState *cpu);
|
||||
void hax_reset_vcpu_state(void *opaque);
|
||||
#include "target/i386/hax-interface.h"
|
||||
#include "target/i386/hax-i386.h"
|
||||
|
||||
#else /* CONFIG_HAX */
|
||||
|
||||
#define hax_enabled() (0)
|
||||
|
||||
#endif /* CONFIG_HAX */
|
||||
|
||||
#endif /* QEMU_HAX_H */
|
48
include/sysemu/hw_accel.h
Normal file
48
include/sysemu/hw_accel.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* QEMU Hardware accelertors support
|
||||
*
|
||||
* Copyright 2016 Google, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_HW_ACCEL_H
|
||||
#define QEMU_HW_ACCEL_H
|
||||
|
||||
#include "qom/cpu.h"
|
||||
#include "sysemu/hax.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
static inline void cpu_synchronize_state(CPUState *cpu)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
kvm_cpu_synchronize_state(cpu);
|
||||
}
|
||||
if (hax_enabled()) {
|
||||
hax_cpu_synchronize_state(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cpu_synchronize_post_reset(CPUState *cpu)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
kvm_cpu_synchronize_post_reset(cpu);
|
||||
}
|
||||
if (hax_enabled()) {
|
||||
hax_cpu_synchronize_post_reset(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cpu_synchronize_post_init(CPUState *cpu)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
kvm_cpu_synchronize_post_init(cpu);
|
||||
}
|
||||
if (hax_enabled()) {
|
||||
hax_cpu_synchronize_post_init(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* QEMU_HW_ACCEL_H */
|
@ -461,29 +461,6 @@ void kvm_cpu_synchronize_state(CPUState *cpu);
|
||||
void kvm_cpu_synchronize_post_reset(CPUState *cpu);
|
||||
void kvm_cpu_synchronize_post_init(CPUState *cpu);
|
||||
|
||||
/* generic hooks - to be moved/refactored once there are more users */
|
||||
|
||||
static inline void cpu_synchronize_state(CPUState *cpu)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
kvm_cpu_synchronize_state(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cpu_synchronize_post_reset(CPUState *cpu)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
kvm_cpu_synchronize_post_reset(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cpu_synchronize_post_init(CPUState *cpu)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
kvm_cpu_synchronize_post_init(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_irqchip_add_msi_route - Add MSI route for specific vector
|
||||
* @s: KVM state
|
||||
|
10
include/sysemu/reset.h
Normal file
10
include/sysemu/reset.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef QEMU_SYSEMU_RESET_H
|
||||
#define QEMU_SYSEMU_RESET_H
|
||||
|
||||
typedef void QEMUResetHandler(void *opaque);
|
||||
|
||||
void qemu_register_reset(QEMUResetHandler *func, void *opaque);
|
||||
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
|
||||
void qemu_devices_reset(void);
|
||||
|
||||
#endif
|
@ -63,7 +63,6 @@ void qemu_system_vmstop_request_prepare(void);
|
||||
int qemu_shutdown_requested_get(void);
|
||||
int qemu_reset_requested_get(void);
|
||||
void qemu_system_killed(int signal, pid_t pid);
|
||||
void qemu_devices_reset(void);
|
||||
void qemu_system_reset(bool report);
|
||||
void qemu_system_guest_panicked(void);
|
||||
size_t qemu_target_page_bits(void);
|
||||
|
@ -66,6 +66,14 @@ void qemu_set_fd_handler(int fd,
|
||||
fd_read, fd_write, NULL, opaque);
|
||||
}
|
||||
|
||||
void event_notifier_set_handler(EventNotifier *e,
|
||||
EventNotifierHandler *handler)
|
||||
{
|
||||
iohandler_init();
|
||||
aio_set_event_notifier(iohandler_ctx, e, false,
|
||||
handler, NULL);
|
||||
}
|
||||
|
||||
/* reaping of zombies. right now we're not passing the status to
|
||||
anyone, but it would be possible to add a callback. */
|
||||
#ifndef _WIN32
|
||||
|
@ -1,7 +1,6 @@
|
||||
common-obj-y += migration.o socket.o fd.o exec.o
|
||||
common-obj-y += tls.o
|
||||
common-obj-y += colo-comm.o
|
||||
common-obj-$(CONFIG_COLO) += colo.o colo-failover.o
|
||||
common-obj-y += colo-comm.o colo.o colo-failover.o
|
||||
common-obj-y += vmstate.o
|
||||
common-obj-y += qemu-file.o
|
||||
common-obj-y += qemu-file-channel.o
|
||||
|
@ -50,7 +50,7 @@
|
||||
#include "sysemu/balloon.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "migration/migration.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "qemu/acl.h"
|
||||
#include "sysemu/tpm.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
|
29
numa.c
29
numa.c
@ -25,6 +25,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/numa.h"
|
||||
#include "exec/cpu-common.h"
|
||||
#include "exec/ramlist.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "qom/cpu.h"
|
||||
#include "qemu/error-report.h"
|
||||
@ -572,3 +573,31 @@ int numa_get_node_for_cpu(int idx)
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void ram_block_notifier_add(RAMBlockNotifier *n)
|
||||
{
|
||||
QLIST_INSERT_HEAD(&ram_list.ramblock_notifiers, n, next);
|
||||
}
|
||||
|
||||
void ram_block_notifier_remove(RAMBlockNotifier *n)
|
||||
{
|
||||
QLIST_REMOVE(n, next);
|
||||
}
|
||||
|
||||
void ram_block_notify_add(void *host, size_t size)
|
||||
{
|
||||
RAMBlockNotifier *notifier;
|
||||
|
||||
QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) {
|
||||
notifier->ram_block_added(notifier, host, size);
|
||||
}
|
||||
}
|
||||
|
||||
void ram_block_notify_remove(void *host, size_t size)
|
||||
{
|
||||
RAMBlockNotifier *notifier;
|
||||
|
||||
QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) {
|
||||
notifier->ram_block_removed(notifier, host, size);
|
||||
}
|
||||
}
|
||||
|
15
qemu-char.c
15
qemu-char.c
@ -499,7 +499,7 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
|
||||
|
||||
static void remove_fd_in_watch(CharDriverState *chr);
|
||||
static void mux_chr_set_handlers(CharDriverState *chr, GMainContext *context);
|
||||
static void mux_set_focus(MuxDriver *d, int focus);
|
||||
static void mux_set_focus(CharDriverState *chr, int focus);
|
||||
|
||||
static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
@ -666,7 +666,7 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
|
||||
case 'c':
|
||||
assert(d->mux_cnt > 0); /* handler registered with first fe */
|
||||
/* Switch to the next registered device */
|
||||
mux_set_focus(d, (d->focus + 1) % d->mux_cnt);
|
||||
mux_set_focus(chr, (d->focus + 1) % d->mux_cnt);
|
||||
break;
|
||||
case 't':
|
||||
d->timestamps = !d->timestamps;
|
||||
@ -826,8 +826,10 @@ static void mux_chr_set_handlers(CharDriverState *chr, GMainContext *context)
|
||||
context, true);
|
||||
}
|
||||
|
||||
static void mux_set_focus(MuxDriver *d, int focus)
|
||||
static void mux_set_focus(CharDriverState *chr, int focus)
|
||||
{
|
||||
MuxDriver *d = chr->opaque;
|
||||
|
||||
assert(focus >= 0);
|
||||
assert(focus < d->mux_cnt);
|
||||
|
||||
@ -836,6 +838,7 @@ static void mux_set_focus(MuxDriver *d, int focus)
|
||||
}
|
||||
|
||||
d->focus = focus;
|
||||
chr->be = d->backends[focus];
|
||||
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
|
||||
}
|
||||
|
||||
@ -935,7 +938,9 @@ void qemu_chr_fe_deinit(CharBackend *b)
|
||||
|
||||
if (b->chr) {
|
||||
qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, true);
|
||||
b->chr->be = NULL;
|
||||
if (b->chr->be == b) {
|
||||
b->chr->be = NULL;
|
||||
}
|
||||
if (b->chr->is_mux) {
|
||||
MuxDriver *d = b->chr->opaque;
|
||||
d->backends[b->tag] = NULL;
|
||||
@ -999,7 +1004,7 @@ void qemu_chr_fe_take_focus(CharBackend *b)
|
||||
}
|
||||
|
||||
if (b->chr->is_mux) {
|
||||
mux_set_focus(b->chr->opaque, b->tag);
|
||||
mux_set_focus(b->chr, b->tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#define ARCHHEADING(text, arch_mask) \
|
||||
if ((arch_mask) & arch_type) \
|
||||
puts(stringify(text));
|
||||
puts(stringify(text) ":");
|
||||
|
||||
#define DEFHEADING(text) ARCHHEADING(text, QEMU_ARCH_ALL)
|
||||
|
||||
|
@ -6,7 +6,7 @@ HXCOMM construct option structures, enums and help message for specified
|
||||
HXCOMM architectures.
|
||||
HXCOMM HXCOMM can be used for comments, discarded from both texi and C
|
||||
|
||||
DEFHEADING(Standard options:)
|
||||
DEFHEADING(Standard options)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@ -468,7 +468,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Block device options:)
|
||||
DEFHEADING(Block device options)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@ -856,7 +856,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(USB options:)
|
||||
DEFHEADING(USB options)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@ -920,7 +920,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Display options:)
|
||||
DEFHEADING(Display options)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@ -1449,7 +1449,7 @@ STEXI
|
||||
ETEXI
|
||||
ARCHHEADING(, QEMU_ARCH_I386)
|
||||
|
||||
ARCHHEADING(i386 target only:, QEMU_ARCH_I386)
|
||||
ARCHHEADING(i386 target only, QEMU_ARCH_I386)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@ -1565,7 +1565,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Network options:)
|
||||
DEFHEADING(Network options)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@ -2146,7 +2146,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Character device options:)
|
||||
DEFHEADING(Character device options)
|
||||
STEXI
|
||||
|
||||
The general form of a character device option is:
|
||||
@ -2481,7 +2481,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Device URL Syntax:)
|
||||
DEFHEADING(Device URL Syntax)
|
||||
STEXI
|
||||
|
||||
In addition to using normal file images for the emulated storage devices,
|
||||
@ -2711,7 +2711,7 @@ STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
DEFHEADING(Bluetooth(R) options:)
|
||||
DEFHEADING(Bluetooth(R) options)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@ -2787,7 +2787,7 @@ ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
#ifdef CONFIG_TPM
|
||||
DEFHEADING(TPM device options:)
|
||||
DEFHEADING(TPM device options)
|
||||
|
||||
DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \
|
||||
"-tpmdev passthrough,id=id[,path=path][,cancel-path=path]\n"
|
||||
@ -2861,7 +2861,7 @@ DEFHEADING()
|
||||
|
||||
#endif
|
||||
|
||||
DEFHEADING(Linux/Multiboot boot specific:)
|
||||
DEFHEADING(Linux/Multiboot boot specific)
|
||||
STEXI
|
||||
|
||||
When using these options, you can use a given Linux or Multiboot
|
||||
@ -2917,7 +2917,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Debug/Expert options:)
|
||||
DEFHEADING(Debug/Expert options)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@ -3280,6 +3280,17 @@ Enable KVM full virtualization support. This option is only available
|
||||
if KVM support is enabled when compiling.
|
||||
ETEXI
|
||||
|
||||
DEF("enable-hax", 0, QEMU_OPTION_enable_hax, \
|
||||
"-enable-hax enable HAX virtualization support\n", QEMU_ARCH_I386)
|
||||
STEXI
|
||||
@item -enable-hax
|
||||
@findex -enable-hax
|
||||
Enable HAX (Hardware-based Acceleration eXecution) support. This option
|
||||
is only available if HAX support is enabled when compiling. HAX is only
|
||||
applicable to MAC and Windows platform, and thus does not conflict with
|
||||
KVM.
|
||||
ETEXI
|
||||
|
||||
DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid,
|
||||
"-xen-domid id specify xen guest domain id\n", QEMU_ARCH_ALL)
|
||||
DEF("xen-create", 0, QEMU_OPTION_xen_create,
|
||||
@ -3775,7 +3786,14 @@ Dump json-encoded vmstate information for current machine type to file
|
||||
in @var{file}
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
DEFHEADING(Generic object creation)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
|
||||
DEF("object", HAS_ARG, QEMU_OPTION_object,
|
||||
"-object TYPENAME[,PROP1=VALUE1,...]\n"
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qom/cpu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qemu/log.h"
|
||||
#include "exec/log.h"
|
||||
|
@ -272,6 +272,12 @@ static void type_initialize(TypeImpl *ti)
|
||||
|
||||
ti->class_size = type_class_get_size(ti);
|
||||
ti->instance_size = type_object_get_size(ti);
|
||||
/* Any type with zero instance_size is implicitly abstract.
|
||||
* This means interface types are all abstract.
|
||||
*/
|
||||
if (ti->instance_size == 0) {
|
||||
ti->abstract = true;
|
||||
}
|
||||
|
||||
ti->class = g_malloc0(ti->class_size);
|
||||
|
||||
|
@ -16,6 +16,13 @@ hxtoh()
|
||||
done
|
||||
}
|
||||
|
||||
print_texi_heading()
|
||||
{
|
||||
if test "$*" != ""; then
|
||||
printf "@subsection %s\n" "$*"
|
||||
fi
|
||||
}
|
||||
|
||||
hxtotexi()
|
||||
{
|
||||
flag=0
|
||||
@ -45,10 +52,10 @@ hxtotexi()
|
||||
fi
|
||||
;;
|
||||
DEFHEADING*)
|
||||
printf '%s\n' "$(expr "$str" : "DEFHEADING(\(.*\))")"
|
||||
print_texi_heading "$(expr "$str" : "DEFHEADING(\(.*\))")"
|
||||
;;
|
||||
ARCHHEADING*)
|
||||
printf '%s\n' "$(expr "$str" : "ARCHHEADING(\(.*\),.*)")"
|
||||
print_texi_heading "$(expr "$str" : "ARCHHEADING(\(.*\),.*)")"
|
||||
;;
|
||||
*)
|
||||
test $flag -eq 1 && printf '%s\n' "$str"
|
||||
|
@ -10,26 +10,18 @@ stub-obj-y += cpu-get-clock.o
|
||||
stub-obj-y += cpu-get-icount.o
|
||||
stub-obj-y += dump.o
|
||||
stub-obj-y += error-printf.o
|
||||
stub-obj-y += fdset-add-fd.o
|
||||
stub-obj-y += fdset-find-fd.o
|
||||
stub-obj-y += fdset-get-fd.o
|
||||
stub-obj-y += fdset-remove-fd.o
|
||||
stub-obj-y += fdset.o
|
||||
stub-obj-y += gdbstub.o
|
||||
stub-obj-y += get-fd.o
|
||||
stub-obj-y += get-next-serial.o
|
||||
stub-obj-y += get-vm-name.o
|
||||
stub-obj-y += iothread.o
|
||||
stub-obj-y += iothread-lock.o
|
||||
stub-obj-y += is-daemonized.o
|
||||
stub-obj-y += machine-init-done.o
|
||||
stub-obj-y += migr-blocker.o
|
||||
stub-obj-y += mon-is-qmp.o
|
||||
stub-obj-y += monitor-init.o
|
||||
stub-obj-y += monitor.o
|
||||
stub-obj-y += notify-event.o
|
||||
stub-obj-y += qtest.o
|
||||
stub-obj-y += replay.o
|
||||
stub-obj-y += replay-user.o
|
||||
stub-obj-y += reset.o
|
||||
stub-obj-y += runstate-check.o
|
||||
stub-obj-y += set-fd-handler.o
|
||||
stub-obj-y += slirp.o
|
||||
@ -39,14 +31,7 @@ stub-obj-y += uuid.o
|
||||
stub-obj-y += vm-stop.o
|
||||
stub-obj-y += vmstate.o
|
||||
stub-obj-$(CONFIG_WIN32) += fd-register.o
|
||||
stub-obj-y += cpus.o
|
||||
stub-obj-y += kvm.o
|
||||
stub-obj-y += qmp_pc_dimm_device_list.o
|
||||
stub-obj-y += target-monitor-defs.o
|
||||
stub-obj-y += target-get-monitor-def.o
|
||||
stub-obj-y += vhost.o
|
||||
stub-obj-y += iohandler.o
|
||||
stub-obj-y += smbios_type_38.o
|
||||
stub-obj-y += ipmi.o
|
||||
stub-obj-y += pc_madt_cpu_entry.o
|
||||
stub-obj-y += migration-colo.o
|
||||
|
11
stubs/cpus.c
11
stubs/cpus.c
@ -1,11 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qom/cpu.h"
|
||||
|
||||
void cpu_resume(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void qemu_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
|
||||
{
|
||||
return -1;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
int monitor_fdset_dup_fd_find(int dup_fd)
|
||||
{
|
||||
return -1;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
int monitor_fdset_get_fd(int64_t fdset_id, int flags)
|
||||
{
|
||||
return -1;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
void monitor_fdset_dup_fd_remove(int dupfd)
|
||||
{
|
||||
}
|
22
stubs/fdset.c
Normal file
22
stubs/fdset.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int monitor_fdset_dup_fd_find(int dup_fd)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int monitor_fdset_get_fd(int64_t fdset_id, int flags)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void monitor_fdset_dup_fd_remove(int dupfd)
|
||||
{
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
CharDriverState *serial_hds[0];
|
@ -1,8 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
AioContext *iohandler_get_aio_context(void)
|
||||
{
|
||||
abort();
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
int kvm_arch_irqchip_create(MachineState *ms, KVMState *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* COarse-grain LOck-stepping Virtual Machines for Non-stop Service (COLO)
|
||||
* (a.k.a. Fault Tolerance or Continuous Replication)
|
||||
*
|
||||
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
||||
* Copyright (c) 2016 FUJITSU LIMITED
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* 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 "migration/colo.h"
|
||||
#include "qmp-commands.h"
|
||||
|
||||
bool colo_supported(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool migration_in_colo_state(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool migration_incoming_in_colo_state(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void migrate_start_colo_process(MigrationState *s)
|
||||
{
|
||||
}
|
||||
|
||||
void *colo_process_incoming_thread(void *opaque)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void qmp_x_colo_lost_heartbeat(Error **errp)
|
||||
{
|
||||
error_setg(errp, "COLO is not supported, please rerun configure"
|
||||
" with --enable-colo option in order to support"
|
||||
" COLO feature");
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
Monitor *cur_mon;
|
||||
|
||||
bool monitor_cur_is_qmp(void)
|
||||
{
|
||||
return false;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
void monitor_init(CharDriverState *chr, int flags)
|
||||
{
|
||||
}
|
@ -3,8 +3,14 @@
|
||||
#include "qemu-common.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
Monitor *cur_mon = NULL;
|
||||
|
||||
int monitor_get_fd(Monitor *mon, const char *name, Error **errp)
|
||||
{
|
||||
error_setg(errp, "only QEMU supports file descriptor passing");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void monitor_init(CharDriverState *chr, int flags)
|
||||
{
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* replay.c
|
||||
*
|
||||
* Copyright (c) 2010-2015 Institute for System Programming
|
||||
* of the Russian Academy of Sciences.
|
||||
*
|
||||
* 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 "sysemu/replay.h"
|
||||
|
||||
bool replay_exception(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool replay_has_exception(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool replay_interrupt(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool replay_has_interrupt(void)
|
||||
{
|
||||
return false;
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
|
||||
/* Stub functions for binaries that never call qemu_devices_reset(),
|
||||
* and don't need to keep track of the reset handler list.
|
||||
*/
|
||||
|
||||
void qemu_register_reset(QEMUResetHandler *func, void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
|
||||
{
|
||||
}
|
@ -31,7 +31,7 @@
|
||||
#endif
|
||||
#include "hw/arm/arm.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "kvm_arm.h"
|
||||
|
||||
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
|
@ -5,3 +5,10 @@ obj-y += gdbstub.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
|
||||
# HAX support
|
||||
ifdef CONFIG_WIN32
|
||||
obj-$(CONFIG_HAX) += hax-all.o hax-mem.o hax-windows.o
|
||||
endif
|
||||
ifdef CONFIG_DARWIN
|
||||
obj-$(CONFIG_HAX) += hax-all.o hax-mem.o hax-darwin.o
|
||||
endif
|
||||
|
1155
target/i386/hax-all.c
Normal file
1155
target/i386/hax-all.c
Normal file
File diff suppressed because it is too large
Load Diff
316
target/i386/hax-darwin.c
Normal file
316
target/i386/hax-darwin.c
Normal file
@ -0,0 +1,316 @@
|
||||
/*
|
||||
* QEMU HAXM support
|
||||
*
|
||||
* Copyright (c) 2011 Intel Corporation
|
||||
* Written by:
|
||||
* Jiang Yunhong<yunhong.jiang@intel.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.
|
||||
*
|
||||
*/
|
||||
|
||||
/* HAX module interface - darwin version */
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "target/i386/hax-i386.h"
|
||||
|
||||
hax_fd hax_mod_open(void)
|
||||
{
|
||||
int fd = open("/dev/HAX", O_RDWR);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Failed to open the hax module\n");
|
||||
}
|
||||
|
||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int hax_populate_ram(uint64_t va, uint32_t size)
|
||||
{
|
||||
int ret;
|
||||
struct hax_alloc_ram_info info;
|
||||
|
||||
if (!hax_global.vm || !hax_global.vm->fd) {
|
||||
fprintf(stderr, "Allocate memory before vm create?\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info.size = size;
|
||||
info.va = va;
|
||||
ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_ALLOC_RAM, &info);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to allocate %x memory\n", size);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags)
|
||||
{
|
||||
struct hax_set_ram_info info;
|
||||
int ret;
|
||||
|
||||
info.pa_start = start_pa;
|
||||
info.size = size;
|
||||
info.va = host_va;
|
||||
info.flags = (uint8_t) flags;
|
||||
|
||||
ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_SET_RAM, &info);
|
||||
if (ret < 0) {
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ioctl(hax->fd, HAX_IOCTL_CAPABILITY, cap);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "Failed to get HAX capability\n");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ioctl(hax->fd, HAX_IOCTL_VERSION, version);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "Failed to get HAX version\n");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *hax_vm_devfs_string(int vm_id)
|
||||
{
|
||||
char *name;
|
||||
|
||||
if (vm_id > MAX_VM_ID) {
|
||||
fprintf(stderr, "Too big VM id\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define HAX_VM_DEVFS "/dev/hax_vm/vmxx"
|
||||
name = g_strdup(HAX_VM_DEVFS);
|
||||
if (!name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(name, sizeof HAX_VM_DEVFS, "/dev/hax_vm/vm%02d", vm_id);
|
||||
return name;
|
||||
}
|
||||
|
||||
static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
|
||||
{
|
||||
char *name;
|
||||
|
||||
if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID) {
|
||||
fprintf(stderr, "Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define HAX_VCPU_DEVFS "/dev/hax_vmxx/vcpuxx"
|
||||
name = g_strdup(HAX_VCPU_DEVFS);
|
||||
if (!name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(name, sizeof HAX_VCPU_DEVFS, "/dev/hax_vm%02d/vcpu%02d",
|
||||
vm_id, vcpu_id);
|
||||
return name;
|
||||
}
|
||||
|
||||
int hax_host_create_vm(struct hax_state *hax, int *vmid)
|
||||
{
|
||||
int ret;
|
||||
int vm_id = 0;
|
||||
|
||||
if (hax_invalid_fd(hax->fd)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (hax->vm) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ioctl(hax->fd, HAX_IOCTL_CREATE_VM, &vm_id);
|
||||
*vmid = vm_id;
|
||||
return ret;
|
||||
}
|
||||
|
||||
hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
|
||||
{
|
||||
hax_fd fd;
|
||||
char *vm_name = NULL;
|
||||
|
||||
vm_name = hax_vm_devfs_string(vm_id);
|
||||
if (!vm_name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open(vm_name, O_RDWR);
|
||||
g_free(vm_name);
|
||||
|
||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (hax_invalid_fd(vm_fd)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = ioctl(vm_fd, HAX_VM_IOCTL_NOTIFY_QEMU_VERSION, qversion);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to notify qemu API version\n");
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Simply assume the size should be bigger than the hax_tunnel,
|
||||
* since the hax_tunnel can be extended later with compatibility considered
|
||||
*/
|
||||
int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ioctl(vm_fd, HAX_VM_IOCTL_VCPU_CREATE, &vcpuid);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to create vcpu %x\n", vcpuid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
|
||||
{
|
||||
char *devfs_path = NULL;
|
||||
hax_fd fd;
|
||||
|
||||
devfs_path = hax_vcpu_devfs_string(vmid, vcpuid);
|
||||
if (!devfs_path) {
|
||||
fprintf(stderr, "Failed to get the devfs\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fd = open(devfs_path, O_RDWR);
|
||||
g_free(devfs_path);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Failed to open the vcpu devfs\n");
|
||||
}
|
||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
|
||||
{
|
||||
int ret;
|
||||
struct hax_tunnel_info info;
|
||||
|
||||
ret = ioctl(vcpu->fd, HAX_VCPU_IOCTL_SETUP_TUNNEL, &info);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Failed to setup the hax tunnel\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!valid_hax_tunnel_size(info.size)) {
|
||||
fprintf(stderr, "Invalid hax tunnel size %x\n", info.size);
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
vcpu->tunnel = (struct hax_tunnel *) (intptr_t) (info.va);
|
||||
vcpu->iobuf = (unsigned char *) (intptr_t) (info.io_va);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hax_vcpu_run(struct hax_vcpu_state *vcpu)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ioctl(vcpu->fd, HAX_VCPU_IOCTL_RUN, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set)
|
||||
{
|
||||
int ret, fd;
|
||||
|
||||
fd = hax_vcpu_get_fd(env);
|
||||
if (fd <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (set) {
|
||||
ret = ioctl(fd, HAX_VCPU_IOCTL_SET_FPU, fl);
|
||||
} else {
|
||||
ret = ioctl(fd, HAX_VCPU_IOCTL_GET_FPU, fl);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set)
|
||||
{
|
||||
int ret, fd;
|
||||
|
||||
fd = hax_vcpu_get_fd(env);
|
||||
if (fd <= 0) {
|
||||
return -1;
|
||||
}
|
||||
if (set) {
|
||||
ret = ioctl(fd, HAX_VCPU_IOCTL_SET_MSRS, msrs);
|
||||
} else {
|
||||
ret = ioctl(fd, HAX_VCPU_IOCTL_GET_MSRS, msrs);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set)
|
||||
{
|
||||
int ret, fd;
|
||||
|
||||
fd = hax_vcpu_get_fd(env);
|
||||
if (fd <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (set) {
|
||||
ret = ioctl(fd, HAX_VCPU_SET_REGS, state);
|
||||
} else {
|
||||
ret = ioctl(fd, HAX_VCPU_GET_REGS, state);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hax_inject_interrupt(CPUArchState *env, int vector)
|
||||
{
|
||||
int ret, fd;
|
||||
|
||||
fd = hax_vcpu_get_fd(env);
|
||||
if (fd <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, HAX_VCPU_IOCTL_INTERRUPT, &vector);
|
||||
return ret;
|
||||
}
|
63
target/i386/hax-darwin.h
Normal file
63
target/i386/hax-darwin.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* QEMU HAXM support
|
||||
*
|
||||
* Copyright (c) 2011 Intel Corporation
|
||||
* Written by:
|
||||
* Jiang Yunhong<yunhong.jiang@intel.com>
|
||||
* Xin Xiaohui<xiaohui.xin@intel.com>
|
||||
* Zhang Xiantao<xiantao.zhang@intel.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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TARGET_I386_HAX_DARWIN_H
|
||||
#define TARGET_I386_HAX_DARWIN_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define HAX_INVALID_FD (-1)
|
||||
static inline int hax_invalid_fd(hax_fd fd)
|
||||
{
|
||||
return fd <= 0;
|
||||
}
|
||||
|
||||
static inline void hax_mod_close(struct hax_state *hax)
|
||||
{
|
||||
close(hax->fd);
|
||||
}
|
||||
|
||||
static inline void hax_close_fd(hax_fd fd)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* HAX model level ioctl */
|
||||
#define HAX_IOCTL_VERSION _IOWR(0, 0x20, struct hax_module_version)
|
||||
#define HAX_IOCTL_CREATE_VM _IOWR(0, 0x21, uint32_t)
|
||||
#define HAX_IOCTL_DESTROY_VM _IOW(0, 0x22, uint32_t)
|
||||
#define HAX_IOCTL_CAPABILITY _IOR(0, 0x23, struct hax_capabilityinfo)
|
||||
|
||||
#define HAX_VM_IOCTL_VCPU_CREATE _IOWR(0, 0x80, uint32_t)
|
||||
#define HAX_VM_IOCTL_ALLOC_RAM _IOWR(0, 0x81, struct hax_alloc_ram_info)
|
||||
#define HAX_VM_IOCTL_SET_RAM _IOWR(0, 0x82, struct hax_set_ram_info)
|
||||
#define HAX_VM_IOCTL_VCPU_DESTROY _IOW(0, 0x83, uint32_t)
|
||||
#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION _IOW(0, 0x84, struct hax_qemu_version)
|
||||
|
||||
#define HAX_VCPU_IOCTL_RUN _IO(0, 0xc0)
|
||||
#define HAX_VCPU_IOCTL_SET_MSRS _IOWR(0, 0xc1, struct hax_msr_data)
|
||||
#define HAX_VCPU_IOCTL_GET_MSRS _IOWR(0, 0xc2, struct hax_msr_data)
|
||||
|
||||
#define HAX_VCPU_IOCTL_SET_FPU _IOW(0, 0xc3, struct fx_layout)
|
||||
#define HAX_VCPU_IOCTL_GET_FPU _IOR(0, 0xc4, struct fx_layout)
|
||||
|
||||
#define HAX_VCPU_IOCTL_SETUP_TUNNEL _IOWR(0, 0xc5, struct hax_tunnel_info)
|
||||
#define HAX_VCPU_IOCTL_INTERRUPT _IOWR(0, 0xc6, uint32_t)
|
||||
#define HAX_VCPU_SET_REGS _IOWR(0, 0xc7, struct vcpu_state_t)
|
||||
#define HAX_VCPU_GET_REGS _IOWR(0, 0xc8, struct vcpu_state_t)
|
||||
|
||||
#endif /* TARGET_I386_HAX_DARWIN_H */
|
94
target/i386/hax-i386.h
Normal file
94
target/i386/hax-i386.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* QEMU HAXM support
|
||||
*
|
||||
* Copyright (c) 2011 Intel Corporation
|
||||
* Written by:
|
||||
* Jiang Yunhong<yunhong.jiang@intel.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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HAX_I386_H
|
||||
#define _HAX_I386_H
|
||||
|
||||
#include "cpu.h"
|
||||
#include "sysemu/hax.h"
|
||||
|
||||
#ifdef CONFIG_DARWIN
|
||||
typedef int hax_fd;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WIN32
|
||||
typedef HANDLE hax_fd;
|
||||
#endif
|
||||
|
||||
extern struct hax_state hax_global;
|
||||
struct hax_vcpu_state {
|
||||
hax_fd fd;
|
||||
int vcpu_id;
|
||||
struct hax_tunnel *tunnel;
|
||||
unsigned char *iobuf;
|
||||
};
|
||||
|
||||
struct hax_state {
|
||||
hax_fd fd; /* the global hax device interface */
|
||||
uint32_t version;
|
||||
struct hax_vm *vm;
|
||||
uint64_t mem_quota;
|
||||
};
|
||||
|
||||
#define HAX_MAX_VCPU 0x10
|
||||
#define MAX_VM_ID 0x40
|
||||
#define MAX_VCPU_ID 0x40
|
||||
|
||||
struct hax_vm {
|
||||
hax_fd fd;
|
||||
int id;
|
||||
struct hax_vcpu_state *vcpus[HAX_MAX_VCPU];
|
||||
};
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
/* Functions exported to host specific mode */
|
||||
hax_fd hax_vcpu_get_fd(CPUArchState *env);
|
||||
int valid_hax_tunnel_size(uint16_t size);
|
||||
|
||||
/* Host specific functions */
|
||||
int hax_mod_version(struct hax_state *hax, struct hax_module_version *version);
|
||||
int hax_inject_interrupt(CPUArchState *env, int vector);
|
||||
struct hax_vm *hax_vm_create(struct hax_state *hax);
|
||||
int hax_vcpu_run(struct hax_vcpu_state *vcpu);
|
||||
int hax_vcpu_create(int id);
|
||||
int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state,
|
||||
int set);
|
||||
int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set);
|
||||
int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set);
|
||||
#endif
|
||||
|
||||
int hax_vm_destroy(struct hax_vm *vm);
|
||||
int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap);
|
||||
int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion);
|
||||
int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags);
|
||||
|
||||
/* Common host function */
|
||||
int hax_host_create_vm(struct hax_state *hax, int *vm_id);
|
||||
hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id);
|
||||
int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid);
|
||||
hax_fd hax_host_open_vcpu(int vmid, int vcpuid);
|
||||
int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu);
|
||||
hax_fd hax_mod_open(void);
|
||||
void hax_memory_init(void);
|
||||
|
||||
|
||||
#ifdef CONFIG_DARWIN
|
||||
#include "target/i386/hax-darwin.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WIN32
|
||||
#include "target/i386/hax-windows.h"
|
||||
#endif
|
||||
|
||||
#include "target/i386/hax-interface.h"
|
||||
|
||||
#endif
|
361
target/i386/hax-interface.h
Normal file
361
target/i386/hax-interface.h
Normal file
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* QEMU HAXM support
|
||||
*
|
||||
* Copyright (c) 2011 Intel Corporation
|
||||
* Written by:
|
||||
* Jiang Yunhong<yunhong.jiang@intel.com>
|
||||
* Xin Xiaohui<xiaohui.xin@intel.com>
|
||||
* Zhang Xiantao<xiantao.zhang@intel.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.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Interface with HAX kernel module */
|
||||
|
||||
#ifndef _HAX_INTERFACE_H
|
||||
#define _HAX_INTERFACE_H
|
||||
|
||||
/* fx_layout has 3 formats table 3-56, 512bytes */
|
||||
struct fx_layout {
|
||||
uint16_t fcw;
|
||||
uint16_t fsw;
|
||||
uint8_t ftw;
|
||||
uint8_t res1;
|
||||
uint16_t fop;
|
||||
union {
|
||||
struct {
|
||||
uint32_t fip;
|
||||
uint16_t fcs;
|
||||
uint16_t res2;
|
||||
};
|
||||
uint64_t fpu_ip;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint32_t fdp;
|
||||
uint16_t fds;
|
||||
uint16_t res3;
|
||||
};
|
||||
uint64_t fpu_dp;
|
||||
};
|
||||
uint32_t mxcsr;
|
||||
uint32_t mxcsr_mask;
|
||||
uint8_t st_mm[8][16];
|
||||
uint8_t mmx_1[8][16];
|
||||
uint8_t mmx_2[8][16];
|
||||
uint8_t pad[96];
|
||||
} __attribute__ ((aligned(8)));
|
||||
|
||||
struct vmx_msr {
|
||||
uint64_t entry;
|
||||
uint64_t value;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/*
|
||||
* Fixed array is not good, but it makes Mac support a bit easier by avoiding
|
||||
* memory map or copyin staff.
|
||||
*/
|
||||
#define HAX_MAX_MSR_ARRAY 0x20
|
||||
struct hax_msr_data {
|
||||
uint16_t nr_msr;
|
||||
uint16_t done;
|
||||
uint16_t pad[2];
|
||||
struct vmx_msr entries[HAX_MAX_MSR_ARRAY];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
union interruptibility_state_t {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint32_t sti_blocking:1;
|
||||
uint32_t movss_blocking:1;
|
||||
uint32_t smi_blocking:1;
|
||||
uint32_t nmi_blocking:1;
|
||||
uint32_t reserved:28;
|
||||
};
|
||||
uint64_t pad;
|
||||
};
|
||||
|
||||
typedef union interruptibility_state_t interruptibility_state_t;
|
||||
|
||||
/* Segment descriptor */
|
||||
struct segment_desc_t {
|
||||
uint16_t selector;
|
||||
uint16_t _dummy;
|
||||
uint32_t limit;
|
||||
uint64_t base;
|
||||
union {
|
||||
struct {
|
||||
uint32_t type:4;
|
||||
uint32_t desc:1;
|
||||
uint32_t dpl:2;
|
||||
uint32_t present:1;
|
||||
uint32_t:4;
|
||||
uint32_t available:1;
|
||||
uint32_t long_mode:1;
|
||||
uint32_t operand_size:1;
|
||||
uint32_t granularity:1;
|
||||
uint32_t null:1;
|
||||
uint32_t:15;
|
||||
};
|
||||
uint32_t ar;
|
||||
};
|
||||
uint32_t ipad;
|
||||
};
|
||||
|
||||
typedef struct segment_desc_t segment_desc_t;
|
||||
|
||||
struct vcpu_state_t {
|
||||
union {
|
||||
uint64_t _regs[16];
|
||||
struct {
|
||||
union {
|
||||
struct {
|
||||
uint8_t _al, _ah;
|
||||
};
|
||||
uint16_t _ax;
|
||||
uint32_t _eax;
|
||||
uint64_t _rax;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint8_t _cl, _ch;
|
||||
};
|
||||
uint16_t _cx;
|
||||
uint32_t _ecx;
|
||||
uint64_t _rcx;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint8_t _dl, _dh;
|
||||
};
|
||||
uint16_t _dx;
|
||||
uint32_t _edx;
|
||||
uint64_t _rdx;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint8_t _bl, _bh;
|
||||
};
|
||||
uint16_t _bx;
|
||||
uint32_t _ebx;
|
||||
uint64_t _rbx;
|
||||
};
|
||||
union {
|
||||
uint16_t _sp;
|
||||
uint32_t _esp;
|
||||
uint64_t _rsp;
|
||||
};
|
||||
union {
|
||||
uint16_t _bp;
|
||||
uint32_t _ebp;
|
||||
uint64_t _rbp;
|
||||
};
|
||||
union {
|
||||
uint16_t _si;
|
||||
uint32_t _esi;
|
||||
uint64_t _rsi;
|
||||
};
|
||||
union {
|
||||
uint16_t _di;
|
||||
uint32_t _edi;
|
||||
uint64_t _rdi;
|
||||
};
|
||||
|
||||
uint64_t _r8;
|
||||
uint64_t _r9;
|
||||
uint64_t _r10;
|
||||
uint64_t _r11;
|
||||
uint64_t _r12;
|
||||
uint64_t _r13;
|
||||
uint64_t _r14;
|
||||
uint64_t _r15;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
uint32_t _eip;
|
||||
uint64_t _rip;
|
||||
};
|
||||
|
||||
union {
|
||||
uint32_t _eflags;
|
||||
uint64_t _rflags;
|
||||
};
|
||||
|
||||
segment_desc_t _cs;
|
||||
segment_desc_t _ss;
|
||||
segment_desc_t _ds;
|
||||
segment_desc_t _es;
|
||||
segment_desc_t _fs;
|
||||
segment_desc_t _gs;
|
||||
segment_desc_t _ldt;
|
||||
segment_desc_t _tr;
|
||||
|
||||
segment_desc_t _gdt;
|
||||
segment_desc_t _idt;
|
||||
|
||||
uint64_t _cr0;
|
||||
uint64_t _cr2;
|
||||
uint64_t _cr3;
|
||||
uint64_t _cr4;
|
||||
|
||||
uint64_t _dr0;
|
||||
uint64_t _dr1;
|
||||
uint64_t _dr2;
|
||||
uint64_t _dr3;
|
||||
uint64_t _dr6;
|
||||
uint64_t _dr7;
|
||||
uint64_t _pde;
|
||||
|
||||
uint32_t _efer;
|
||||
|
||||
uint32_t _sysenter_cs;
|
||||
uint64_t _sysenter_eip;
|
||||
uint64_t _sysenter_esp;
|
||||
|
||||
uint32_t _activity_state;
|
||||
uint32_t pad;
|
||||
interruptibility_state_t _interruptibility_state;
|
||||
};
|
||||
|
||||
/* HAX exit status */
|
||||
enum exit_status {
|
||||
/* IO port request */
|
||||
HAX_EXIT_IO = 1,
|
||||
/* MMIO instruction emulation */
|
||||
HAX_EXIT_MMIO,
|
||||
/* QEMU emulation mode request, currently means guest enter non-PG mode */
|
||||
HAX_EXIT_REAL,
|
||||
/*
|
||||
* Interrupt window open, qemu can inject interrupt now
|
||||
* Also used when signal pending since at that time qemu usually need
|
||||
* check interrupt
|
||||
*/
|
||||
HAX_EXIT_INTERRUPT,
|
||||
/* Unknown vmexit, mostly trigger reboot */
|
||||
HAX_EXIT_UNKNOWN_VMEXIT,
|
||||
/* HALT from guest */
|
||||
HAX_EXIT_HLT,
|
||||
/* Reboot request, like because of tripple fault in guest */
|
||||
HAX_EXIT_STATECHANGE,
|
||||
/* the vcpu is now only paused when destroy, so simply return to hax */
|
||||
HAX_EXIT_PAUSED,
|
||||
HAX_EXIT_FAST_MMIO,
|
||||
};
|
||||
|
||||
/*
|
||||
* The interface definition:
|
||||
* 1. vcpu_run execute will return 0 on success, otherwise mean failed
|
||||
* 2. exit_status return the exit reason, as stated in enum exit_status
|
||||
* 3. exit_reason is the vmx exit reason
|
||||
*/
|
||||
struct hax_tunnel {
|
||||
uint32_t _exit_reason;
|
||||
uint32_t _exit_flag;
|
||||
uint32_t _exit_status;
|
||||
uint32_t user_event_pending;
|
||||
int ready_for_interrupt_injection;
|
||||
int request_interrupt_window;
|
||||
union {
|
||||
struct {
|
||||
/* 0: read, 1: write */
|
||||
#define HAX_EXIT_IO_IN 1
|
||||
#define HAX_EXIT_IO_OUT 0
|
||||
uint8_t _direction;
|
||||
uint8_t _df;
|
||||
uint16_t _size;
|
||||
uint16_t _port;
|
||||
uint16_t _count;
|
||||
uint8_t _flags;
|
||||
uint8_t _pad0;
|
||||
uint16_t _pad1;
|
||||
uint32_t _pad2;
|
||||
uint64_t _vaddr;
|
||||
} pio;
|
||||
struct {
|
||||
uint64_t gla;
|
||||
} mmio;
|
||||
struct {
|
||||
} state;
|
||||
};
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct hax_module_version {
|
||||
uint32_t compat_version;
|
||||
uint32_t cur_version;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* This interface is support only after API version 2 */
|
||||
struct hax_qemu_version {
|
||||
/* Current API version in QEMU */
|
||||
uint32_t cur_version;
|
||||
/* The minimum API version supported by QEMU */
|
||||
uint32_t min_version;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* The mac specfic interface to qemu, mostly is ioctl related */
|
||||
struct hax_tunnel_info {
|
||||
uint64_t va;
|
||||
uint64_t io_va;
|
||||
uint16_t size;
|
||||
uint16_t pad[3];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct hax_alloc_ram_info {
|
||||
uint32_t size;
|
||||
uint32_t pad;
|
||||
uint64_t va;
|
||||
} __attribute__ ((__packed__));
|
||||
#define HAX_RAM_INFO_ROM 0x01 /* Read-Only */
|
||||
#define HAX_RAM_INFO_INVALID 0x80 /* Unmapped, usually used for MMIO */
|
||||
struct hax_set_ram_info {
|
||||
uint64_t pa_start;
|
||||
uint32_t size;
|
||||
uint8_t flags;
|
||||
uint8_t pad[3];
|
||||
uint64_t va;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
#define HAX_CAP_STATUS_WORKING 0x1
|
||||
#define HAX_CAP_STATUS_NOTWORKING 0x0
|
||||
#define HAX_CAP_WORKSTATUS_MASK 0x1
|
||||
|
||||
#define HAX_CAP_FAILREASON_VT 0x1
|
||||
#define HAX_CAP_FAILREASON_NX 0x2
|
||||
|
||||
#define HAX_CAP_MEMQUOTA 0x2
|
||||
#define HAX_CAP_UG 0x4
|
||||
|
||||
struct hax_capabilityinfo {
|
||||
/* bit 0: 1 - working
|
||||
* 0 - not working, possibly because NT/NX disabled
|
||||
* bit 1: 1 - memory limitation working
|
||||
* 0 - no memory limitation
|
||||
*/
|
||||
uint16_t wstatus;
|
||||
/* valid when not working
|
||||
* bit 0: VT not enabeld
|
||||
* bit 1: NX not enabled*/
|
||||
uint16_t winfo;
|
||||
uint32_t pad;
|
||||
uint64_t mem_quota;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct hax_fastmmio {
|
||||
uint64_t gpa;
|
||||
union {
|
||||
uint64_t value;
|
||||
uint64_t gpa2; /* since HAX API v4 */
|
||||
};
|
||||
uint8_t size;
|
||||
uint8_t direction;
|
||||
uint16_t reg_index;
|
||||
uint32_t pad0;
|
||||
uint64_t _cr0;
|
||||
uint64_t _cr2;
|
||||
uint64_t _cr3;
|
||||
uint64_t _cr4;
|
||||
} __attribute__ ((__packed__));
|
||||
#endif
|
289
target/i386/hax-mem.c
Normal file
289
target/i386/hax-mem.c
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* HAX memory mapping operations
|
||||
*
|
||||
* Copyright (c) 2015-16 Intel Corporation
|
||||
* Copyright 2016 Google, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
#include "target/i386/hax-i386.h"
|
||||
#include "qemu/queue.h"
|
||||
|
||||
#define DEBUG_HAX_MEM 0
|
||||
|
||||
#define DPRINTF(fmt, ...) \
|
||||
do { \
|
||||
if (DEBUG_HAX_MEM) { \
|
||||
fprintf(stdout, fmt, ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* HAXMapping: describes a pending guest physical memory mapping
|
||||
*
|
||||
* @start_pa: a guest physical address marking the start of the region; must be
|
||||
* page-aligned
|
||||
* @size: a guest physical address marking the end of the region; must be
|
||||
* page-aligned
|
||||
* @host_va: the host virtual address of the start of the mapping
|
||||
* @flags: mapping parameters e.g. HAX_RAM_INFO_ROM or HAX_RAM_INFO_INVALID
|
||||
* @entry: additional fields for linking #HAXMapping instances together
|
||||
*/
|
||||
typedef struct HAXMapping {
|
||||
uint64_t start_pa;
|
||||
uint32_t size;
|
||||
uint64_t host_va;
|
||||
int flags;
|
||||
QTAILQ_ENTRY(HAXMapping) entry;
|
||||
} HAXMapping;
|
||||
|
||||
/*
|
||||
* A doubly-linked list (actually a tail queue) of the pending page mappings
|
||||
* for the ongoing memory transaction.
|
||||
*
|
||||
* It is used to optimize the number of page mapping updates done through the
|
||||
* kernel module. For example, it's effective when a driver is digging an MMIO
|
||||
* hole inside an existing memory mapping. It will get a deletion of the whole
|
||||
* region, then the addition of the 2 remaining RAM areas around the hole and
|
||||
* finally the memory transaction commit. During the commit, it will effectively
|
||||
* send to the kernel only the removal of the pages from the MMIO hole after
|
||||
* having computed locally the result of the deletion and additions.
|
||||
*/
|
||||
static QTAILQ_HEAD(HAXMappingListHead, HAXMapping) mappings =
|
||||
QTAILQ_HEAD_INITIALIZER(mappings);
|
||||
|
||||
/**
|
||||
* hax_mapping_dump_list: dumps @mappings to stdout (for debugging)
|
||||
*/
|
||||
static void hax_mapping_dump_list(void)
|
||||
{
|
||||
HAXMapping *entry;
|
||||
|
||||
DPRINTF("%s updates:\n", __func__);
|
||||
QTAILQ_FOREACH(entry, &mappings, entry) {
|
||||
DPRINTF("\t%c 0x%016" PRIx64 "->0x%016" PRIx64 " VA 0x%016" PRIx64
|
||||
"%s\n", entry->flags & HAX_RAM_INFO_INVALID ? '-' : '+',
|
||||
entry->start_pa, entry->start_pa + entry->size, entry->host_va,
|
||||
entry->flags & HAX_RAM_INFO_ROM ? " ROM" : "");
|
||||
}
|
||||
}
|
||||
|
||||
static void hax_insert_mapping_before(HAXMapping *next, uint64_t start_pa,
|
||||
uint32_t size, uint64_t host_va,
|
||||
uint8_t flags)
|
||||
{
|
||||
HAXMapping *entry;
|
||||
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->start_pa = start_pa;
|
||||
entry->size = size;
|
||||
entry->host_va = host_va;
|
||||
entry->flags = flags;
|
||||
if (!next) {
|
||||
QTAILQ_INSERT_TAIL(&mappings, entry, entry);
|
||||
} else {
|
||||
QTAILQ_INSERT_BEFORE(next, entry, entry);
|
||||
}
|
||||
}
|
||||
|
||||
static bool hax_mapping_is_opposite(HAXMapping *entry, uint64_t host_va,
|
||||
uint8_t flags)
|
||||
{
|
||||
/* removed then added without change for the read-only flag */
|
||||
bool nop_flags = (entry->flags ^ flags) == HAX_RAM_INFO_INVALID;
|
||||
|
||||
return (entry->host_va == host_va) && nop_flags;
|
||||
}
|
||||
|
||||
static void hax_update_mapping(uint64_t start_pa, uint32_t size,
|
||||
uint64_t host_va, uint8_t flags)
|
||||
{
|
||||
uint64_t end_pa = start_pa + size;
|
||||
uint32_t chunk_sz;
|
||||
HAXMapping *entry, *next;
|
||||
|
||||
QTAILQ_FOREACH_SAFE(entry, &mappings, entry, next) {
|
||||
if (start_pa >= entry->start_pa + entry->size) {
|
||||
continue;
|
||||
}
|
||||
if (start_pa < entry->start_pa) {
|
||||
chunk_sz = end_pa <= entry->start_pa ? size
|
||||
: entry->start_pa - start_pa;
|
||||
hax_insert_mapping_before(entry, start_pa, chunk_sz,
|
||||
host_va, flags);
|
||||
start_pa += chunk_sz;
|
||||
host_va += chunk_sz;
|
||||
size -= chunk_sz;
|
||||
}
|
||||
chunk_sz = MIN(size, entry->size);
|
||||
if (chunk_sz) {
|
||||
bool nop = hax_mapping_is_opposite(entry, host_va, flags);
|
||||
bool partial = chunk_sz < entry->size;
|
||||
if (partial) {
|
||||
/* remove the beginning of the existing chunk */
|
||||
entry->start_pa += chunk_sz;
|
||||
entry->host_va += chunk_sz;
|
||||
entry->size -= chunk_sz;
|
||||
if (!nop) {
|
||||
hax_insert_mapping_before(entry, start_pa, chunk_sz,
|
||||
host_va, flags);
|
||||
}
|
||||
} else { /* affects the full mapping entry */
|
||||
if (nop) { /* no change to this mapping, remove it */
|
||||
QTAILQ_REMOVE(&mappings, entry, entry);
|
||||
g_free(entry);
|
||||
} else { /* update mapping properties */
|
||||
entry->host_va = host_va;
|
||||
entry->flags = flags;
|
||||
}
|
||||
}
|
||||
start_pa += chunk_sz;
|
||||
host_va += chunk_sz;
|
||||
size -= chunk_sz;
|
||||
}
|
||||
if (!size) { /* we are done */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (size) { /* add the leftover */
|
||||
hax_insert_mapping_before(NULL, start_pa, size, host_va, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void hax_process_section(MemoryRegionSection *section, uint8_t flags)
|
||||
{
|
||||
MemoryRegion *mr = section->mr;
|
||||
hwaddr start_pa = section->offset_within_address_space;
|
||||
ram_addr_t size = int128_get64(section->size);
|
||||
unsigned int delta;
|
||||
uint64_t host_va;
|
||||
|
||||
/* We only care about RAM pages */
|
||||
if (!memory_region_is_ram(mr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Adjust start_pa and size so that they are page-aligned. (Cf
|
||||
* kvm_set_phys_mem() in kvm-all.c).
|
||||
*/
|
||||
delta = qemu_real_host_page_size - (start_pa & ~qemu_real_host_page_mask);
|
||||
delta &= ~qemu_real_host_page_mask;
|
||||
if (delta > size) {
|
||||
return;
|
||||
}
|
||||
start_pa += delta;
|
||||
size -= delta;
|
||||
size &= qemu_real_host_page_mask;
|
||||
if (!size || (start_pa & ~qemu_real_host_page_mask)) {
|
||||
return;
|
||||
}
|
||||
|
||||
host_va = (uintptr_t)memory_region_get_ram_ptr(mr)
|
||||
+ section->offset_within_region + delta;
|
||||
if (memory_region_is_rom(section->mr)) {
|
||||
flags |= HAX_RAM_INFO_ROM;
|
||||
}
|
||||
|
||||
/* the kernel module interface uses 32-bit sizes (but we could split...) */
|
||||
g_assert(size <= UINT32_MAX);
|
||||
|
||||
hax_update_mapping(start_pa, size, host_va, flags);
|
||||
}
|
||||
|
||||
static void hax_region_add(MemoryListener *listener,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
memory_region_ref(section->mr);
|
||||
hax_process_section(section, 0);
|
||||
}
|
||||
|
||||
static void hax_region_del(MemoryListener *listener,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
hax_process_section(section, HAX_RAM_INFO_INVALID);
|
||||
memory_region_unref(section->mr);
|
||||
}
|
||||
|
||||
static void hax_transaction_begin(MemoryListener *listener)
|
||||
{
|
||||
g_assert(QTAILQ_EMPTY(&mappings));
|
||||
}
|
||||
|
||||
static void hax_transaction_commit(MemoryListener *listener)
|
||||
{
|
||||
if (!QTAILQ_EMPTY(&mappings)) {
|
||||
HAXMapping *entry, *next;
|
||||
|
||||
if (DEBUG_HAX_MEM) {
|
||||
hax_mapping_dump_list();
|
||||
}
|
||||
QTAILQ_FOREACH_SAFE(entry, &mappings, entry, next) {
|
||||
if (entry->flags & HAX_RAM_INFO_INVALID) {
|
||||
/* for unmapping, put the values expected by the kernel */
|
||||
entry->flags = HAX_RAM_INFO_INVALID;
|
||||
entry->host_va = 0;
|
||||
}
|
||||
if (hax_set_ram(entry->start_pa, entry->size,
|
||||
entry->host_va, entry->flags)) {
|
||||
fprintf(stderr, "%s: Failed mapping @0x%016" PRIx64 "+0x%"
|
||||
PRIx32 " flags %02x\n", __func__, entry->start_pa,
|
||||
entry->size, entry->flags);
|
||||
}
|
||||
QTAILQ_REMOVE(&mappings, entry, entry);
|
||||
g_free(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* currently we fake the dirty bitmap sync, always dirty */
|
||||
static void hax_log_sync(MemoryListener *listener,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
MemoryRegion *mr = section->mr;
|
||||
|
||||
if (!memory_region_is_ram(mr)) {
|
||||
/* Skip MMIO regions */
|
||||
return;
|
||||
}
|
||||
|
||||
memory_region_set_dirty(mr, 0, int128_get64(section->size));
|
||||
}
|
||||
|
||||
static MemoryListener hax_memory_listener = {
|
||||
.begin = hax_transaction_begin,
|
||||
.commit = hax_transaction_commit,
|
||||
.region_add = hax_region_add,
|
||||
.region_del = hax_region_del,
|
||||
.log_sync = hax_log_sync,
|
||||
.priority = 10,
|
||||
};
|
||||
|
||||
static void hax_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
|
||||
{
|
||||
/*
|
||||
* In HAX, QEMU allocates the virtual address, and HAX kernel
|
||||
* populates the memory with physical memory. Currently we have no
|
||||
* paging, so user should make sure enough free memory in advance.
|
||||
*/
|
||||
if (hax_populate_ram((uint64_t)(uintptr_t)host, size) < 0) {
|
||||
fprintf(stderr, "HAX failed to populate RAM");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static struct RAMBlockNotifier hax_ram_notifier = {
|
||||
.ram_block_added = hax_ram_block_added,
|
||||
};
|
||||
|
||||
void hax_memory_init(void)
|
||||
{
|
||||
ram_block_notifier_add(&hax_ram_notifier);
|
||||
memory_listener_register(&hax_memory_listener, &address_space_memory);
|
||||
}
|
479
target/i386/hax-windows.c
Normal file
479
target/i386/hax-windows.c
Normal file
@ -0,0 +1,479 @@
|
||||
/*
|
||||
* QEMU HAXM support
|
||||
*
|
||||
* Copyright (c) 2011 Intel Corporation
|
||||
* Written by:
|
||||
* Jiang Yunhong<yunhong.jiang@intel.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 "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "hax-i386.h"
|
||||
|
||||
/*
|
||||
* return 0 when success, -1 when driver not loaded,
|
||||
* other negative value for other failure
|
||||
*/
|
||||
static int hax_open_device(hax_fd *fd)
|
||||
{
|
||||
uint32_t errNum = 0;
|
||||
HANDLE hDevice;
|
||||
|
||||
if (!fd) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
hDevice = CreateFile("\\\\.\\HAX",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "Failed to open the HAX device!\n");
|
||||
errNum = GetLastError();
|
||||
if (errNum == ERROR_FILE_NOT_FOUND) {
|
||||
return -1;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
*fd = hDevice;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hax_fd hax_mod_open */
|
||||
hax_fd hax_mod_open(void)
|
||||
{
|
||||
int ret;
|
||||
hax_fd fd = NULL;
|
||||
|
||||
ret = hax_open_device(&fd);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Open HAX device failed\n");
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int hax_populate_ram(uint64_t va, uint32_t size)
|
||||
{
|
||||
int ret;
|
||||
struct hax_alloc_ram_info info;
|
||||
HANDLE hDeviceVM;
|
||||
DWORD dSize = 0;
|
||||
|
||||
if (!hax_global.vm || !hax_global.vm->fd) {
|
||||
fprintf(stderr, "Allocate memory before vm create?\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info.size = size;
|
||||
info.va = va;
|
||||
|
||||
hDeviceVM = hax_global.vm->fd;
|
||||
|
||||
ret = DeviceIoControl(hDeviceVM,
|
||||
HAX_VM_IOCTL_ALLOC_RAM,
|
||||
&info, sizeof(info), NULL, 0, &dSize,
|
||||
(LPOVERLAPPED) NULL);
|
||||
|
||||
if (!ret) {
|
||||
fprintf(stderr, "Failed to allocate %x memory\n", size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags)
|
||||
{
|
||||
struct hax_set_ram_info info;
|
||||
HANDLE hDeviceVM = hax_global.vm->fd;
|
||||
DWORD dSize = 0;
|
||||
int ret;
|
||||
|
||||
info.pa_start = start_pa;
|
||||
info.size = size;
|
||||
info.va = host_va;
|
||||
info.flags = (uint8_t) flags;
|
||||
|
||||
ret = DeviceIoControl(hDeviceVM, HAX_VM_IOCTL_SET_RAM,
|
||||
&info, sizeof(info), NULL, 0, &dSize,
|
||||
(LPOVERLAPPED) NULL);
|
||||
|
||||
if (!ret) {
|
||||
return -EFAULT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap)
|
||||
{
|
||||
int ret;
|
||||
HANDLE hDevice = hax->fd; /* handle to hax module */
|
||||
DWORD dSize = 0;
|
||||
DWORD err = 0;
|
||||
|
||||
if (hax_invalid_fd(hDevice)) {
|
||||
fprintf(stderr, "Invalid fd for hax device!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = DeviceIoControl(hDevice, HAX_IOCTL_CAPABILITY, NULL, 0, cap,
|
||||
sizeof(*cap), &dSize, (LPOVERLAPPED) NULL);
|
||||
|
||||
if (!ret) {
|
||||
err = GetLastError();
|
||||
if (err == ERROR_INSUFFICIENT_BUFFER || err == ERROR_MORE_DATA) {
|
||||
fprintf(stderr, "hax capability is too long to hold.\n");
|
||||
}
|
||||
fprintf(stderr, "Failed to get Hax capability:%luu\n", err);
|
||||
return -EFAULT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
|
||||
{
|
||||
int ret;
|
||||
HANDLE hDevice = hax->fd; /* handle to hax module */
|
||||
DWORD dSize = 0;
|
||||
DWORD err = 0;
|
||||
|
||||
if (hax_invalid_fd(hDevice)) {
|
||||
fprintf(stderr, "Invalid fd for hax device!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = DeviceIoControl(hDevice,
|
||||
HAX_IOCTL_VERSION,
|
||||
NULL, 0,
|
||||
version, sizeof(*version), &dSize,
|
||||
(LPOVERLAPPED) NULL);
|
||||
|
||||
if (!ret) {
|
||||
err = GetLastError();
|
||||
if (err == ERROR_INSUFFICIENT_BUFFER || err == ERROR_MORE_DATA) {
|
||||
fprintf(stderr, "hax module verion is too long to hold.\n");
|
||||
}
|
||||
fprintf(stderr, "Failed to get Hax module version:%lu\n", err);
|
||||
return -EFAULT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static char *hax_vm_devfs_string(int vm_id)
|
||||
{
|
||||
char *name;
|
||||
|
||||
if (vm_id > MAX_VM_ID) {
|
||||
fprintf(stderr, "Too big VM id\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define HAX_VM_DEVFS "\\\\.\\hax_vmxx"
|
||||
name = g_strdup(HAX_VM_DEVFS);
|
||||
if (!name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(name, sizeof HAX_VM_DEVFS, "\\\\.\\hax_vm%02d", vm_id);
|
||||
return name;
|
||||
}
|
||||
|
||||
static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
|
||||
{
|
||||
char *name;
|
||||
|
||||
if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID) {
|
||||
fprintf(stderr, "Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define HAX_VCPU_DEVFS "\\\\.\\hax_vmxx_vcpuxx"
|
||||
name = g_strdup(HAX_VCPU_DEVFS);
|
||||
if (!name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(name, sizeof HAX_VCPU_DEVFS, "\\\\.\\hax_vm%02d_vcpu%02d",
|
||||
vm_id, vcpu_id);
|
||||
return name;
|
||||
}
|
||||
|
||||
int hax_host_create_vm(struct hax_state *hax, int *vmid)
|
||||
{
|
||||
int ret;
|
||||
int vm_id = 0;
|
||||
DWORD dSize = 0;
|
||||
|
||||
if (hax_invalid_fd(hax->fd)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (hax->vm) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = DeviceIoControl(hax->fd,
|
||||
HAX_IOCTL_CREATE_VM,
|
||||
NULL, 0, &vm_id, sizeof(vm_id), &dSize,
|
||||
(LPOVERLAPPED) NULL);
|
||||
if (!ret) {
|
||||
fprintf(stderr, "Failed to create VM. Error code: %lu\n",
|
||||
GetLastError());
|
||||
return -1;
|
||||
}
|
||||
*vmid = vm_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
hax_fd hax_host_open_vm(struct hax_state *hax, int vm_id)
|
||||
{
|
||||
char *vm_name = NULL;
|
||||
hax_fd hDeviceVM;
|
||||
|
||||
vm_name = hax_vm_devfs_string(vm_id);
|
||||
if (!vm_name) {
|
||||
fprintf(stderr, "Failed to open VM. VM name is null\n");
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
hDeviceVM = CreateFile(vm_name,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hDeviceVM == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "Open the vm device error:%s, ec:%lu\n",
|
||||
vm_name, GetLastError());
|
||||
}
|
||||
|
||||
g_free(vm_name);
|
||||
return hDeviceVM;
|
||||
}
|
||||
|
||||
int hax_notify_qemu_version(hax_fd vm_fd, struct hax_qemu_version *qversion)
|
||||
{
|
||||
int ret;
|
||||
DWORD dSize = 0;
|
||||
if (hax_invalid_fd(vm_fd)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = DeviceIoControl(vm_fd,
|
||||
HAX_VM_IOCTL_NOTIFY_QEMU_VERSION,
|
||||
qversion, sizeof(struct hax_qemu_version),
|
||||
NULL, 0, &dSize, (LPOVERLAPPED) NULL);
|
||||
if (!ret) {
|
||||
fprintf(stderr, "Failed to notify qemu API version\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hax_host_create_vcpu(hax_fd vm_fd, int vcpuid)
|
||||
{
|
||||
int ret;
|
||||
DWORD dSize = 0;
|
||||
|
||||
ret = DeviceIoControl(vm_fd,
|
||||
HAX_VM_IOCTL_VCPU_CREATE,
|
||||
&vcpuid, sizeof(vcpuid), NULL, 0, &dSize,
|
||||
(LPOVERLAPPED) NULL);
|
||||
if (!ret) {
|
||||
fprintf(stderr, "Failed to create vcpu %x\n", vcpuid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
hax_fd hax_host_open_vcpu(int vmid, int vcpuid)
|
||||
{
|
||||
char *devfs_path = NULL;
|
||||
hax_fd hDeviceVCPU;
|
||||
|
||||
devfs_path = hax_vcpu_devfs_string(vmid, vcpuid);
|
||||
if (!devfs_path) {
|
||||
fprintf(stderr, "Failed to get the devfs\n");
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
hDeviceVCPU = CreateFile(devfs_path,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
if (hDeviceVCPU == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "Failed to open the vcpu devfs\n");
|
||||
}
|
||||
g_free(devfs_path);
|
||||
return hDeviceVCPU;
|
||||
}
|
||||
|
||||
int hax_host_setup_vcpu_channel(struct hax_vcpu_state *vcpu)
|
||||
{
|
||||
hax_fd hDeviceVCPU = vcpu->fd;
|
||||
int ret;
|
||||
struct hax_tunnel_info info;
|
||||
DWORD dSize = 0;
|
||||
|
||||
ret = DeviceIoControl(hDeviceVCPU,
|
||||
HAX_VCPU_IOCTL_SETUP_TUNNEL,
|
||||
NULL, 0, &info, sizeof(info), &dSize,
|
||||
(LPOVERLAPPED) NULL);
|
||||
if (!ret) {
|
||||
fprintf(stderr, "Failed to setup the hax tunnel\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!valid_hax_tunnel_size(info.size)) {
|
||||
fprintf(stderr, "Invalid hax tunnel size %x\n", info.size);
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
vcpu->tunnel = (struct hax_tunnel *) (intptr_t) (info.va);
|
||||
vcpu->iobuf = (unsigned char *) (intptr_t) (info.io_va);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hax_vcpu_run(struct hax_vcpu_state *vcpu)
|
||||
{
|
||||
int ret;
|
||||
HANDLE hDeviceVCPU = vcpu->fd;
|
||||
DWORD dSize = 0;
|
||||
|
||||
ret = DeviceIoControl(hDeviceVCPU,
|
||||
HAX_VCPU_IOCTL_RUN,
|
||||
NULL, 0, NULL, 0, &dSize, (LPOVERLAPPED) NULL);
|
||||
if (!ret) {
|
||||
return -EFAULT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int hax_sync_fpu(CPUArchState *env, struct fx_layout *fl, int set)
|
||||
{
|
||||
int ret;
|
||||
hax_fd fd;
|
||||
HANDLE hDeviceVCPU;
|
||||
DWORD dSize = 0;
|
||||
|
||||
fd = hax_vcpu_get_fd(env);
|
||||
if (hax_invalid_fd(fd)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
hDeviceVCPU = fd;
|
||||
|
||||
if (set) {
|
||||
ret = DeviceIoControl(hDeviceVCPU,
|
||||
HAX_VCPU_IOCTL_SET_FPU,
|
||||
fl, sizeof(*fl), NULL, 0, &dSize,
|
||||
(LPOVERLAPPED) NULL);
|
||||
} else {
|
||||
ret = DeviceIoControl(hDeviceVCPU,
|
||||
HAX_VCPU_IOCTL_GET_FPU,
|
||||
NULL, 0, fl, sizeof(*fl), &dSize,
|
||||
(LPOVERLAPPED) NULL);
|
||||
}
|
||||
if (!ret) {
|
||||
return -EFAULT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int hax_sync_msr(CPUArchState *env, struct hax_msr_data *msrs, int set)
|
||||
{
|
||||
int ret;
|
||||
hax_fd fd;
|
||||
HANDLE hDeviceVCPU;
|
||||
DWORD dSize = 0;
|
||||
|
||||
fd = hax_vcpu_get_fd(env);
|
||||
if (hax_invalid_fd(fd)) {
|
||||
return -1;
|
||||
}
|
||||
hDeviceVCPU = fd;
|
||||
|
||||
if (set) {
|
||||
ret = DeviceIoControl(hDeviceVCPU,
|
||||
HAX_VCPU_IOCTL_SET_MSRS,
|
||||
msrs, sizeof(*msrs),
|
||||
msrs, sizeof(*msrs), &dSize, (LPOVERLAPPED) NULL);
|
||||
} else {
|
||||
ret = DeviceIoControl(hDeviceVCPU,
|
||||
HAX_VCPU_IOCTL_GET_MSRS,
|
||||
msrs, sizeof(*msrs),
|
||||
msrs, sizeof(*msrs), &dSize, (LPOVERLAPPED) NULL);
|
||||
}
|
||||
if (!ret) {
|
||||
return -EFAULT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, int set)
|
||||
{
|
||||
int ret;
|
||||
hax_fd fd;
|
||||
HANDLE hDeviceVCPU;
|
||||
DWORD dSize;
|
||||
|
||||
fd = hax_vcpu_get_fd(env);
|
||||
if (hax_invalid_fd(fd)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
hDeviceVCPU = fd;
|
||||
|
||||
if (set) {
|
||||
ret = DeviceIoControl(hDeviceVCPU,
|
||||
HAX_VCPU_SET_REGS,
|
||||
state, sizeof(*state),
|
||||
NULL, 0, &dSize, (LPOVERLAPPED) NULL);
|
||||
} else {
|
||||
ret = DeviceIoControl(hDeviceVCPU,
|
||||
HAX_VCPU_GET_REGS,
|
||||
NULL, 0,
|
||||
state, sizeof(*state), &dSize,
|
||||
(LPOVERLAPPED) NULL);
|
||||
}
|
||||
if (!ret) {
|
||||
return -EFAULT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int hax_inject_interrupt(CPUArchState *env, int vector)
|
||||
{
|
||||
int ret;
|
||||
hax_fd fd;
|
||||
HANDLE hDeviceVCPU;
|
||||
DWORD dSize;
|
||||
|
||||
fd = hax_vcpu_get_fd(env);
|
||||
if (hax_invalid_fd(fd)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
hDeviceVCPU = fd;
|
||||
|
||||
ret = DeviceIoControl(hDeviceVCPU,
|
||||
HAX_VCPU_IOCTL_INTERRUPT,
|
||||
&vector, sizeof(vector), NULL, 0, &dSize,
|
||||
(LPOVERLAPPED) NULL);
|
||||
if (!ret) {
|
||||
return -EFAULT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
89
target/i386/hax-windows.h
Normal file
89
target/i386/hax-windows.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* QEMU HAXM support
|
||||
*
|
||||
* Copyright IBM, Corp. 2008
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* Copyright (c) 2011 Intel Corporation
|
||||
* Written by:
|
||||
* Jiang Yunhong<yunhong.jiang@intel.com>
|
||||
* Xin Xiaohui<xiaohui.xin@intel.com>
|
||||
* Zhang Xiantao<xiantao.zhang@intel.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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TARGET_I386_HAX_WINDOWS_H
|
||||
#define TARGET_I386_HAX_WINDOWS_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <memory.h>
|
||||
#include <malloc.h>
|
||||
#include <winioctl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <windef.h>
|
||||
|
||||
#define HAX_INVALID_FD INVALID_HANDLE_VALUE
|
||||
|
||||
static inline void hax_mod_close(struct hax_state *hax)
|
||||
{
|
||||
CloseHandle(hax->fd);
|
||||
}
|
||||
|
||||
static inline void hax_close_fd(hax_fd fd)
|
||||
{
|
||||
CloseHandle(fd);
|
||||
}
|
||||
|
||||
static inline int hax_invalid_fd(hax_fd fd)
|
||||
{
|
||||
return (fd == INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
#define HAX_DEVICE_TYPE 0x4000
|
||||
|
||||
#define HAX_IOCTL_VERSION CTL_CODE(HAX_DEVICE_TYPE, 0x900, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_IOCTL_CREATE_VM CTL_CODE(HAX_DEVICE_TYPE, 0x901, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_IOCTL_CAPABILITY CTL_CODE(HAX_DEVICE_TYPE, 0x910, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define HAX_VM_IOCTL_VCPU_CREATE CTL_CODE(HAX_DEVICE_TYPE, 0x902, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_VM_IOCTL_ALLOC_RAM CTL_CODE(HAX_DEVICE_TYPE, 0x903, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_VM_IOCTL_SET_RAM CTL_CODE(HAX_DEVICE_TYPE, 0x904, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_VM_IOCTL_VCPU_DESTROY CTL_CODE(HAX_DEVICE_TYPE, 0x905, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define HAX_VCPU_IOCTL_RUN CTL_CODE(HAX_DEVICE_TYPE, 0x906, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_VCPU_IOCTL_SET_MSRS CTL_CODE(HAX_DEVICE_TYPE, 0x907, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_VCPU_IOCTL_GET_MSRS CTL_CODE(HAX_DEVICE_TYPE, 0x908, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_VCPU_IOCTL_SET_FPU CTL_CODE(HAX_DEVICE_TYPE, 0x909, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_VCPU_IOCTL_GET_FPU CTL_CODE(HAX_DEVICE_TYPE, 0x90a, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define HAX_VCPU_IOCTL_SETUP_TUNNEL CTL_CODE(HAX_DEVICE_TYPE, 0x90b, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_VCPU_IOCTL_INTERRUPT CTL_CODE(HAX_DEVICE_TYPE, 0x90c, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_VCPU_SET_REGS CTL_CODE(HAX_DEVICE_TYPE, 0x90d, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define HAX_VCPU_GET_REGS CTL_CODE(HAX_DEVICE_TYPE, 0x90e, \
|
||||
METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION CTL_CODE(HAX_DEVICE_TYPE, 0x910, \
|
||||
METHOD_BUFFERED, \
|
||||
FILE_ANY_ACCESS)
|
||||
#endif /* TARGET_I386_HAX_WINDOWS_H */
|
@ -24,6 +24,7 @@
|
||||
#include "kvm_i386.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "hw/i386/apic_internal.h"
|
||||
#endif
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hyperv.h"
|
||||
#include "standard-headers/asm-x86/hyperv.h"
|
||||
|
||||
@ -88,7 +89,7 @@ HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
|
||||
goto err_sint_set_notifier;
|
||||
}
|
||||
|
||||
event_notifier_set_handler(&sint_route->sint_ack_notifier, false,
|
||||
event_notifier_set_handler(&sint_route->sint_ack_notifier,
|
||||
kvm_hv_sint_ack_handler);
|
||||
|
||||
gsi = kvm_irqchip_add_hv_sint_route(kvm_state, vcpu_id, sint);
|
||||
@ -112,7 +113,7 @@ HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
|
||||
err_irqfd:
|
||||
kvm_irqchip_release_virq(kvm_state, gsi);
|
||||
err_gsi:
|
||||
event_notifier_set_handler(&sint_route->sint_ack_notifier, false, NULL);
|
||||
event_notifier_set_handler(&sint_route->sint_ack_notifier, NULL);
|
||||
event_notifier_cleanup(&sint_route->sint_ack_notifier);
|
||||
err_sint_set_notifier:
|
||||
event_notifier_cleanup(&sint_route->sint_set_notifier);
|
||||
@ -128,7 +129,7 @@ void kvm_hv_sint_route_destroy(HvSintRoute *sint_route)
|
||||
&sint_route->sint_set_notifier,
|
||||
sint_route->gsi);
|
||||
kvm_irqchip_release_virq(kvm_state, sint_route->gsi);
|
||||
event_notifier_set_handler(&sint_route->sint_ack_notifier, false, NULL);
|
||||
event_notifier_set_handler(&sint_route->sint_ack_notifier, NULL);
|
||||
event_notifier_cleanup(&sint_route->sint_ack_notifier);
|
||||
event_notifier_cleanup(&sint_route->sint_set_notifier);
|
||||
g_free(sint_route);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "kvm_i386.h"
|
||||
#include "hyperv.h"
|
||||
|
@ -55,6 +55,11 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_irqchip_create(MachineState *ms, KVMState *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_init_vcpu(CPUState *cs)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(cs);
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "cpu.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "sysemu/numa.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "sysemu/cpus.h"
|
||||
@ -145,6 +145,11 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_irqchip_create(MachineState *ms, KVMState *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_arch_sync_sregs(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *cenv = &cpu->env;
|
||||
|
@ -315,16 +315,4 @@ static inline void kvmppc_icbi_range(PowerPCCPU *cpu, uint8_t *addr, int len)
|
||||
|
||||
#endif /* CONFIG_KVM */
|
||||
|
||||
#ifndef KVM_INTERRUPT_SET
|
||||
#define KVM_INTERRUPT_SET -1
|
||||
#endif
|
||||
|
||||
#ifndef KVM_INTERRUPT_UNSET
|
||||
#define KVM_INTERRUPT_UNSET -2
|
||||
#endif
|
||||
|
||||
#ifndef KVM_INTERRUPT_SET_LEVEL
|
||||
#define KVM_INTERRUPT_SET_LEVEL -3
|
||||
#endif
|
||||
|
||||
#endif /* KVM_PPC_H */
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "mmu-hash64.h"
|
||||
#include "exec/log.h"
|
||||
|
@ -21,10 +21,10 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "disas/bfd.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "cpu-models.h"
|
||||
#include "mmu-hash32.h"
|
||||
#include "mmu-hash64.h"
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
|
||||
int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
{
|
||||
|
@ -294,6 +294,11 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_irqchip_create(MachineState *ms, KVMState *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long kvm_arch_vcpu_id(CPUState *cpu)
|
||||
{
|
||||
return cpu->cpu_index;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user