* 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:
Peter Maydell 2017-01-20 16:42:07 +00:00
commit 598cf1c805
110 changed files with 3728 additions and 468 deletions

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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;
}
}

View File

@ -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
View 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;
}

View File

@ -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)

View File

@ -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
View 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);
}

View File

@ -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);
}

View File

@ -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
View 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);
}
}

View File

@ -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"

View File

@ -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"

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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
View 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);
}

View File

@ -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;

View File

@ -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() */

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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"

View File

@ -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
View 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 */

View File

@ -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);

View File

@ -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",\

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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
View 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
View 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 */

View File

@ -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
View 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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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"

View File

@ -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"

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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)
{
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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
View 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)
{
}

View File

@ -1,4 +0,0 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
CharDriverState *serial_hds[0];

View File

@ -1,8 +0,0 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/main-loop.h"
AioContext *iohandler_get_aio_context(void)
{
abort();
}

View File

@ -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;
}

View File

@ -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");
}

View File

@ -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;
}

View File

@ -1,7 +0,0 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "monitor/monitor.h"
void monitor_init(CharDriverState *chr, int flags)
{
}

View File

@ -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)
{
}

View File

@ -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;
}

View File

@ -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)
{
}

View File

@ -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)

View File

@ -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

File diff suppressed because it is too large Load Diff

316
target/i386/hax-darwin.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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 */

View File

@ -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

View File

@ -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);

View File

@ -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"

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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"

View File

@ -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"

View File

@ -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)
{

View File

@ -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