* socket option parsing fix (Daniel)

* SCSI fixes (Fam)
 * Readline double-free fix (Greg)
 * More HVF attribution fixes (Izik)
 * WHPX (Windows Hypervisor Platform Extensions) support (Justin)
 * POLLHUP handler (Klim)
 * ivshmem fixes (Ladi)
 * memfd memory backend (Marc-André)
 * improved error message (Marcelo)
 * Memory fixes (Peter Xu, Zhecheng)
 * Remove obsolete code and comments (Peter M.)
 * qdev API improvements (Philippe)
 * Add CONFIG_I2C switch (Thomas)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQEcBAABAgAGBQJaexoYAAoJEL/70l94x66DVL0IAJC//aZCwwgyN9CRNDcOo10/
 UPtzprfezERkur77r1KvEYVNIfslRF6iTBou2+suOWkzoNL2LJ0XZ+wi+2u2sFIF
 ikvbQVk4dOWqJJQj7e1cmv5A2EZy2dcxjAoD1IG6CRy76+HzYqwjHVw+HkYY5CUS
 qwnUWjQddP6WtH9MsUHpX7p7atWo7T1tzkx4v8H+CIHBO3uUJQSZLkGYflvcstpj
 Fo04bZzSkDj2rnlqqBo/6UgJQXD8++Rs64vmiX2xwcK47TWO31Vbuwu+r8V9osWm
 LHFmRpL8ZkZfL0yqf0bpjmd688dirjVpHIJ5KE043Lo6AdI+K5xBfoBjXxtPiKE=
 =o90D
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* socket option parsing fix (Daniel)
* SCSI fixes (Fam)
* Readline double-free fix (Greg)
* More HVF attribution fixes (Izik)
* WHPX (Windows Hypervisor Platform Extensions) support (Justin)
* POLLHUP handler (Klim)
* ivshmem fixes (Ladi)
* memfd memory backend (Marc-André)
* improved error message (Marcelo)
* Memory fixes (Peter Xu, Zhecheng)
* Remove obsolete code and comments (Peter M.)
* qdev API improvements (Philippe)
* Add CONFIG_I2C switch (Thomas)

# gpg: Signature made Wed 07 Feb 2018 15:24:08 GMT
# gpg:                using RSA key BFFBD25F78C7AE83
# 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: (47 commits)
  Add the WHPX acceleration enlightenments
  Introduce the WHPX impl
  Add the WHPX vcpu API
  Add the Windows Hypervisor Platform accelerator.
  tests/test-filter-redirector: move close()
  tests: use memfd in vhost-user-test
  vhost-user-test: make read-guest-mem setup its own qemu
  tests: keep compiling failing vhost-user tests
  Add memfd based hostmem
  memfd: add hugetlbsize argument
  memfd: add hugetlb support
  memfd: add error argument, instead of perror()
  cpus: join thread when removing a vCPU
  cpus: hvf: unregister thread with RCU
  cpus: tcg: unregister thread with RCU, fix exiting of loop on unplug
  cpus: dummy: unregister thread with RCU, exit loop on unplug
  cpus: kvm: unregister thread with RCU
  cpus: hax: register/unregister thread with RCU, exit loop on unplug
  ivshmem: Disable irqfd on device reset
  ivshmem: Improve MSI irqfd error handling
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

# Conflicts:
#	cpus.c
master
Peter Maydell 2018-02-07 20:40:36 +00:00
commit 7b213bb475
90 changed files with 2464 additions and 347 deletions

View File

@ -13,12 +13,13 @@ addons:
- libattr1-dev
- libbrlapi-dev
- libcap-ng-dev
- libgcc-6-dev
- libgnutls-dev
- libgtk-3-dev
- libiscsi-dev
- liblttng-ust-dev
- libnfs-dev
- libncurses5-dev
- libnfs-dev
- libnss3-dev
- libpixman-1-dev
- libpng12-dev

View File

@ -235,6 +235,7 @@ static int kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot)
{
KVMState *s = kvm_state;
struct kvm_userspace_memory_region mem;
int ret;
mem.slot = slot->slot | (kml->as_id << 16);
mem.guest_phys_addr = slot->start_addr;
@ -248,7 +249,10 @@ static int kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot)
kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
}
mem.memory_size = slot->memory_size;
return kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
trace_kvm_set_user_memory(mem.slot, mem.flags, mem.guest_phys_addr,
mem.memory_size, mem.userspace_addr, ret);
return ret;
}
int kvm_destroy_vcpu(CPUState *cpu)

View File

@ -12,4 +12,5 @@ kvm_irqchip_commit_routes(void) ""
kvm_irqchip_add_msi_route(char *name, int vector, int virq) "dev %s vector %d virq %d"
kvm_irqchip_update_msi_route(int virq) "Updating MSI route virq=%d"
kvm_irqchip_release_virq(int virq) "virq %d"
kvm_set_user_memory(uint32_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, int ret) "Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " ret=%d"

View File

@ -1,4 +1,5 @@
obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o
obj-$(call lnot,$(CONFIG_HVF)) += hvf-stub.o
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o
obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o
obj-$(call lnot,$(CONFIG_HVF)) += hvf-stub.o
obj-$(call lnot,$(CONFIG_WHPX)) += whpx-stub.o
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o

48
accel/stubs/whpx-stub.c Normal file
View File

@ -0,0 +1,48 @@
/*
* QEMU Windows Hypervisor Platform accelerator (WHPX) stub
*
* Copyright Microsoft Corp. 2017
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "cpu.h"
#include "sysemu/whpx.h"
int whpx_init_vcpu(CPUState *cpu)
{
return -1;
}
int whpx_vcpu_exec(CPUState *cpu)
{
return -1;
}
void whpx_destroy_vcpu(CPUState *cpu)
{
}
void whpx_vcpu_kick(CPUState *cpu)
{
}
void whpx_cpu_synchronize_state(CPUState *cpu)
{
}
void whpx_cpu_synchronize_post_reset(CPUState *cpu)
{
}
void whpx_cpu_synchronize_post_init(CPUState *cpu)
{
}
void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu)
{
}

View File

@ -503,39 +503,6 @@ int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
}
#elif defined(__ia64)
#ifndef __ISR_VALID
/* This ought to be in <bits/siginfo.h>... */
# define __ISR_VALID 1
#endif
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
{
siginfo_t *info = pinfo;
ucontext_t *uc = puc;
unsigned long ip;
int is_write = 0;
ip = uc->uc_mcontext.sc_ip;
switch (host_signum) {
case SIGILL:
case SIGFPE:
case SIGSEGV:
case SIGBUS:
case SIGTRAP:
if (info->si_code && (info->si_segvflags & __ISR_VALID)) {
/* ISR.W (write-access) is bit 33: */
is_write = (info->si_isr >> 33) & 1;
}
break;
default:
break;
}
return handle_cpu_signal(ip, info, is_write, (sigset_t *)&uc->uc_sigmask);
}
#elif defined(__s390__)
int cpu_signal_handler(int host_signum, void *pinfo,

View File

@ -8,3 +8,5 @@ common-obj-$(CONFIG_LINUX) += hostmem-file.o
common-obj-y += cryptodev.o
common-obj-y += cryptodev-builtin.o
common-obj-$(CONFIG_LINUX) += hostmem-memfd.o

170
backends/hostmem-memfd.c Normal file
View File

@ -0,0 +1,170 @@
/*
* QEMU host memfd memory backend
*
* Copyright (C) 2018 Red Hat Inc
*
* Authors:
* Marc-André Lureau <marcandre.lureau@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "sysemu/hostmem.h"
#include "sysemu/sysemu.h"
#include "qom/object_interfaces.h"
#include "qemu/memfd.h"
#include "qapi/error.h"
#define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd"
#define MEMORY_BACKEND_MEMFD(obj) \
OBJECT_CHECK(HostMemoryBackendMemfd, (obj), TYPE_MEMORY_BACKEND_MEMFD)
typedef struct HostMemoryBackendMemfd HostMemoryBackendMemfd;
struct HostMemoryBackendMemfd {
HostMemoryBackend parent_obj;
bool hugetlb;
uint64_t hugetlbsize;
bool seal;
};
static void
memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
{
HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(backend);
char *name;
int fd;
if (!backend->size) {
error_setg(errp, "can't create backend with size 0");
return;
}
if (host_memory_backend_mr_inited(backend)) {
return;
}
backend->force_prealloc = mem_prealloc;
fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD, backend->size,
m->hugetlb, m->hugetlbsize, m->seal ?
F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL : 0,
errp);
if (fd == -1) {
return;
}
name = object_get_canonical_path(OBJECT(backend));
memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
name, backend->size, true, fd, errp);
g_free(name);
}
static bool
memfd_backend_get_hugetlb(Object *o, Error **errp)
{
return MEMORY_BACKEND_MEMFD(o)->hugetlb;
}
static void
memfd_backend_set_hugetlb(Object *o, bool value, Error **errp)
{
MEMORY_BACKEND_MEMFD(o)->hugetlb = value;
}
static void
memfd_backend_set_hugetlbsize(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
Error *local_err = NULL;
uint64_t value;
if (host_memory_backend_mr_inited(MEMORY_BACKEND(obj))) {
error_setg(&local_err, "cannot change property value");
goto out;
}
visit_type_size(v, name, &value, &local_err);
if (local_err) {
goto out;
}
if (!value) {
error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
PRIu64 "'", object_get_typename(obj), name, value);
goto out;
}
m->hugetlbsize = value;
out:
error_propagate(errp, local_err);
}
static void
memfd_backend_get_hugetlbsize(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
uint64_t value = m->hugetlbsize;
visit_type_size(v, name, &value, errp);
}
static bool
memfd_backend_get_seal(Object *o, Error **errp)
{
return MEMORY_BACKEND_MEMFD(o)->seal;
}
static void
memfd_backend_set_seal(Object *o, bool value, Error **errp)
{
MEMORY_BACKEND_MEMFD(o)->seal = value;
}
static void
memfd_backend_instance_init(Object *obj)
{
HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
/* default to sealed file */
m->seal = true;
}
static void
memfd_backend_class_init(ObjectClass *oc, void *data)
{
HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
bc->alloc = memfd_backend_memory_alloc;
object_class_property_add_bool(oc, "hugetlb",
memfd_backend_get_hugetlb,
memfd_backend_set_hugetlb,
&error_abort);
object_class_property_add(oc, "hugetlbsize", "int",
memfd_backend_get_hugetlbsize,
memfd_backend_set_hugetlbsize,
NULL, NULL, &error_abort);
object_class_property_add_bool(oc, "seal",
memfd_backend_get_seal,
memfd_backend_set_seal,
&error_abort);
}
static const TypeInfo memfd_backend_info = {
.name = TYPE_MEMORY_BACKEND_MEMFD,
.parent = TYPE_MEMORY_BACKEND,
.instance_init = memfd_backend_instance_init,
.class_init = memfd_backend_class_init,
.instance_size = sizeof(HostMemoryBackendMemfd),
};
static void register_types(void)
{
type_register_static(&memfd_backend_info);
}
type_init(register_types);

View File

@ -51,23 +51,6 @@ typedef struct {
static void pty_chr_update_read_handler_locked(Chardev *chr);
static void pty_chr_state(Chardev *chr, int connected);
static gboolean pty_chr_timer(gpointer opaque)
{
struct Chardev *chr = CHARDEV(opaque);
PtyChardev *s = PTY_CHARDEV(opaque);
qemu_mutex_lock(&chr->chr_write_lock);
s->timer_src = NULL;
g_source_unref(s->open_source);
s->open_source = NULL;
if (!s->connected) {
/* Next poll ... */
pty_chr_update_read_handler_locked(chr);
}
qemu_mutex_unlock(&chr->chr_write_lock);
return FALSE;
}
static void pty_chr_timer_cancel(PtyChardev *s)
{
if (s->timer_src) {
@ -77,6 +60,31 @@ static void pty_chr_timer_cancel(PtyChardev *s)
}
}
static void pty_chr_open_src_cancel(PtyChardev *s)
{
if (s->open_source) {
g_source_destroy(s->open_source);
g_source_unref(s->open_source);
s->open_source = NULL;
}
}
static gboolean pty_chr_timer(gpointer opaque)
{
struct Chardev *chr = CHARDEV(opaque);
PtyChardev *s = PTY_CHARDEV(opaque);
qemu_mutex_lock(&chr->chr_write_lock);
pty_chr_timer_cancel(s);
pty_chr_open_src_cancel(s);
if (!s->connected) {
/* Next poll ... */
pty_chr_update_read_handler_locked(chr);
}
qemu_mutex_unlock(&chr->chr_write_lock);
return FALSE;
}
/* Called with chr_write_lock held. */
static void pty_chr_rearm_timer(Chardev *chr, int ms)
{
@ -195,11 +203,7 @@ static void pty_chr_state(Chardev *chr, int connected)
PtyChardev *s = PTY_CHARDEV(chr);
if (!connected) {
if (s->open_source) {
g_source_destroy(s->open_source);
g_source_unref(s->open_source);
s->open_source = NULL;
}
pty_chr_open_src_cancel(s);
remove_fd_in_watch(chr);
s->connected = 0;
/* (re-)connect poll interval for idle guests: once per second.

View File

@ -42,6 +42,7 @@ typedef struct {
QIOChannel *ioc; /* Client I/O channel */
QIOChannelSocket *sioc; /* Client master channel */
QIONetListener *listener;
GSource *hup_source;
QCryptoTLSCreds *tls_creds;
int connected;
int max_size;
@ -352,6 +353,12 @@ static void tcp_chr_free_connection(Chardev *chr)
s->read_msgfds_num = 0;
}
if (s->hup_source != NULL) {
g_source_destroy(s->hup_source);
g_source_unref(s->hup_source);
s->hup_source = NULL;
}
tcp_set_msgfds(chr, NULL, 0);
remove_fd_in_watch(chr);
object_unref(OBJECT(s->sioc));
@ -455,6 +462,15 @@ static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
return TRUE;
}
static gboolean tcp_chr_hup(QIOChannel *channel,
GIOCondition cond,
void *opaque)
{
Chardev *chr = CHARDEV(opaque);
tcp_chr_disconnect(chr);
return G_SOURCE_REMOVE;
}
static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
@ -528,6 +544,12 @@ static void tcp_chr_connect(void *opaque)
tcp_chr_read,
chr, chr->gcontext);
}
s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP);
g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup,
chr, NULL);
g_source_attach(s->hup_source, chr->gcontext);
qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}

113
configure vendored
View File

@ -222,6 +222,17 @@ supported_hvf_target() {
return 1
}
supported_whpx_target() {
test "$whpx" = "yes" || return 1
glob "$1" "*-softmmu" || return 1
case "${1%-softmmu}" in
i386|x86_64)
return 0
;;
esac
return 1
}
supported_target() {
case "$1" in
*-softmmu)
@ -248,6 +259,7 @@ supported_target() {
supported_xen_target "$1" && return 0
supported_hax_target "$1" && return 0
supported_hvf_target "$1" && return 0
supported_whpx_target "$1" && return 0
print_error "TCG disabled, but hardware accelerator not available for '$target'"
return 1
}
@ -338,10 +350,12 @@ vhost_user=""
kvm="no"
hax="no"
hvf="no"
whpx="no"
rdma=""
gprof="no"
debug_tcg="no"
debug="no"
sanitizers="no"
fortify_source=""
strip_opt="yes"
tcg_interpreter="no"
@ -636,8 +650,6 @@ elif check_define _ARCH_PPC ; then
fi
elif check_define __mips__ ; then
cpu="mips"
elif check_define __ia64__ ; then
cpu="ia64"
elif check_define __s390__ ; then
if check_define __s390x__ ; then
cpu="s390x"
@ -995,6 +1007,10 @@ for opt do
strip_opt="no"
fortify_source="no"
;;
--enable-sanitizers) sanitizers="yes"
;;
--disable-sanitizers) sanitizers="no"
;;
--enable-sparse) sparse="yes"
;;
--disable-sparse) sparse="no"
@ -1055,6 +1071,10 @@ for opt do
;;
--enable-hvf) hvf="yes"
;;
--disable-whpx) whpx="no"
;;
--enable-whpx) whpx="yes"
;;
--disable-tcg-interpreter) tcg_interpreter="no"
;;
--enable-tcg-interpreter) tcg_interpreter="yes"
@ -1476,6 +1496,7 @@ Advanced options (experts only):
--firmwarepath=PATH search PATH for firmware files
--with-confsuffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir [$confsuffix]
--enable-debug enable common debug build options
--enable-sanitizers enable default sanitizers
--disable-strip disable stripping binaries
--disable-werror disable compilation abort on warning
--disable-stack-protector disable compiler-provided stack protection
@ -1553,6 +1574,7 @@ disabled with --disable-FEATURE, default is enabled if available:
kvm KVM acceleration support
hax HAX acceleration support
hvf Hypervisor.framework acceleration support
whpx Windows Hypervisor Platform acceleration support
rdma RDMA-based migration support
vde support for vde network
netmap support for netmap network
@ -2450,6 +2472,30 @@ if test "$xen_pv_domain_build" = "yes" &&
"which requires Xen support."
fi
##########################################
# Windows Hypervisor Platform accelerator (WHPX) check
if test "$whpx" != "no" ; then
cat > $TMPC << EOF
#include <windows.h>
#include <winhvplatform.h>
#include <winhvemulation.h>
int main(void) {
WHV_CAPABILITY whpx_cap;
WHvGetCapability(WHvCapabilityCodeFeatures, &whpx_cap, sizeof(whpx_cap));
return 0;
}
EOF
if compile_prog "" "-lwinhvplatform -lwinhvemulation" ; then
libs_softmmu="$libs_softmmu -lwinhvplatform -lwinhvemulation"
whpx="yes"
else
if test "$whpx" = "yes"; then
feature_not_found "winhvplatform" "winhvemulation is not installed"
fi
whpx="no"
fi
fi
##########################################
# Sparse probe
if test "$sparse" != "no" ; then
@ -4743,9 +4789,6 @@ if test "$coroutine_pool" = ""; then
fi
if test "$debug_stack_usage" = "yes"; then
if test "$cpu" = "ia64" -o "$cpu" = "hppa"; then
error_exit "stack usage debugging is not supported for $cpu"
fi
if test "$coroutine_pool" = "yes"; then
echo "WARN: disabling coroutine pool for stack usage debugging"
coroutine_pool=no
@ -5204,10 +5247,46 @@ if compile_prog "" "" ; then
have_utmpx=yes
fi
##########################################
# checks for sanitizers
write_c_skeleton
have_asan=no
have_ubsan=no
have_asan_iface_h=no
have_asan_iface_fiber=no
if test "$sanitizers" = "yes" ; then
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address" ""; then
have_asan=yes
fi
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=undefined" ""; then
have_ubsan=yes
fi
if check_include "sanitizer/asan_interface.h" ; then
have_asan_iface_h=yes
fi
cat > $TMPC << EOF
#include <sanitizer/asan_interface.h>
int main(void) {
__sanitizer_start_switch_fiber(0, 0, 0);
return 0;
}
EOF
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address" "" ; then
have_asan_iface_fiber=yes
fi
fi
##########################################
# End of CC checks
# After here, no more $cc or $ld runs
write_c_skeleton
if test "$gcov" = "yes" ; then
CFLAGS="-fprofile-arcs -ftest-coverage -g $CFLAGS"
LDFLAGS="-fprofile-arcs -ftest-coverage $LDFLAGS"
@ -5228,6 +5307,20 @@ else
CFLAGS="-O2 $CFLAGS"
fi
if test "$have_asan" = "yes"; then
CFLAGS="-fsanitize=address $CFLAGS"
if test "$have_asan_iface_h" = "no" ; then
echo "ASAN build enabled, but ASAN header missing." \
"Without code annotation, the report may be inferior."
elif test "$have_asan_iface_fiber" = "no" ; then
echo "ASAN build enabled, but ASAN header is too old." \
"Without code annotation, the report may be inferior."
fi
fi
if test "$have_ubsan" = "yes"; then
CFLAGS="-fsanitize=undefined $CFLAGS"
fi
##########################################
# Do we have libnfs
if test "$libnfs" != "no" ; then
@ -5596,6 +5689,7 @@ echo "Install blobs $blobs"
echo "KVM support $kvm"
echo "HAX support $hax"
echo "HVF support $hvf"
echo "WHPX support $whpx"
echo "TCG support $tcg"
if test "$tcg" = "yes" ; then
echo "TCG debug enabled $debug_tcg"
@ -5763,7 +5857,7 @@ if test "$mingw32" = "yes" ; then
echo "CONFIG_QGA_NTDDDISK=y" >> $config_host_mak
fi
if test "$guest_agent_msi" = "yes"; then
echo "QEMU_GA_MSI_ENABLED=yes" >> $config_host_mak
echo "QEMU_GA_MSI_ENABLED=yes" >> $config_host_mak
echo "QEMU_GA_MSI_MINGW_DLL_PATH=${QEMU_GA_MSI_MINGW_DLL_PATH}" >> $config_host_mak
echo "QEMU_GA_MSI_WITH_VSS=${QEMU_GA_MSI_WITH_VSS}" >> $config_host_mak
echo "QEMU_GA_MSI_ARCH=${QEMU_GA_MSI_ARCH}" >> $config_host_mak
@ -6211,6 +6305,10 @@ if test "$valgrind_h" = "yes" ; then
echo "CONFIG_VALGRIND_H=y" >> $config_host_mak
fi
if test "$have_asan_iface_fiber" = "yes" ; then
echo "CONFIG_ASAN_IFACE_FIBER=y" >> $config_host_mak
fi
if test "$has_environ" = "yes" ; then
echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak
fi
@ -6692,6 +6790,9 @@ fi
if supported_hvf_target $target; then
echo "CONFIG_HVF=y" >> $config_target_mak
fi
if supported_whpx_target $target; then
echo "CONFIG_WHPX=y" >> $config_target_mak
fi
if test "$target_bigendian" = "yes" ; then
echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
fi

113
cpus.c
View File

@ -38,6 +38,7 @@
#include "sysemu/kvm.h"
#include "sysemu/hax.h"
#include "sysemu/hvf.h"
#include "sysemu/whpx.h"
#include "qmp-commands.h"
#include "exec/exec-all.h"
@ -1205,6 +1206,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
cpu->created = false;
qemu_cond_signal(&qemu_cpu_cond);
qemu_mutex_unlock_iothread();
rcu_unregister_thread();
return NULL;
}
@ -1233,7 +1235,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
cpu->created = true;
qemu_cond_signal(&qemu_cpu_cond);
while (1) {
do {
qemu_mutex_unlock_iothread();
do {
int sig;
@ -1245,8 +1247,9 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
}
qemu_mutex_lock_iothread();
qemu_wait_io_event(cpu);
}
} while (!cpu->unplug);
rcu_unregister_thread();
return NULL;
#endif
}
@ -1465,6 +1468,7 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
deal_with_unplugged_cpus();
}
rcu_unregister_thread();
return NULL;
}
@ -1473,6 +1477,7 @@ static void *qemu_hax_cpu_thread_fn(void *arg)
CPUState *cpu = arg;
int r;
rcu_register_thread();
qemu_mutex_lock_iothread();
qemu_thread_get_self(cpu->thread);
@ -1484,7 +1489,7 @@ static void *qemu_hax_cpu_thread_fn(void *arg)
hax_init_vcpu(cpu);
qemu_cond_signal(&qemu_cpu_cond);
while (1) {
do {
if (cpu_can_run(cpu)) {
r = hax_smp_cpu_exec(cpu);
if (r == EXCP_DEBUG) {
@ -1493,7 +1498,8 @@ static void *qemu_hax_cpu_thread_fn(void *arg)
}
qemu_wait_io_event(cpu);
}
} while (!cpu->unplug || cpu_can_run(cpu));
rcu_unregister_thread();
return NULL;
}
@ -1536,6 +1542,50 @@ static void *qemu_hvf_cpu_thread_fn(void *arg)
cpu->created = false;
qemu_cond_signal(&qemu_cpu_cond);
qemu_mutex_unlock_iothread();
rcu_unregister_thread();
return NULL;
}
static void *qemu_whpx_cpu_thread_fn(void *arg)
{
CPUState *cpu = arg;
int r;
rcu_register_thread();
qemu_mutex_lock_iothread();
qemu_thread_get_self(cpu->thread);
cpu->thread_id = qemu_get_thread_id();
current_cpu = cpu;
r = whpx_init_vcpu(cpu);
if (r < 0) {
fprintf(stderr, "whpx_init_vcpu failed: %s\n", strerror(-r));
exit(1);
}
/* signal CPU creation */
cpu->created = true;
qemu_cond_signal(&qemu_cpu_cond);
do {
if (cpu_can_run(cpu)) {
r = whpx_vcpu_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);
}
qemu_wait_io_event_common(cpu);
} while (!cpu->unplug || cpu_can_run(cpu));
whpx_destroy_vcpu(cpu);
cpu->created = false;
qemu_cond_signal(&qemu_cpu_cond);
qemu_mutex_unlock_iothread();
rcu_unregister_thread();
return NULL;
}
@ -1599,18 +1649,17 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
/* Ignore everything else? */
break;
}
} else if (cpu->unplug) {
qemu_tcg_destroy_vcpu(cpu);
cpu->created = false;
qemu_cond_signal(&qemu_cpu_cond);
qemu_mutex_unlock_iothread();
return NULL;
}
atomic_mb_set(&cpu->exit_request, 0);
qemu_wait_io_event(cpu);
}
} while (!cpu->unplug || cpu_can_run(cpu));
qemu_tcg_destroy_vcpu(cpu);
cpu->created = false;
qemu_cond_signal(&qemu_cpu_cond);
qemu_mutex_unlock_iothread();
rcu_unregister_thread();
return NULL;
}
@ -1630,9 +1679,11 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
}
#else /* _WIN32 */
if (!qemu_cpu_is_self(cpu)) {
if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) {
error_report("%s: QueueUserAPC failed with error %lu", __func__,
GetLastError());
if (whpx_enabled()) {
whpx_vcpu_kick(cpu);
} else if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) {
fprintf(stderr, "%s: QueueUserAPC failed with error %lu\n",
__func__, GetLastError());
exit(1);
}
}
@ -1747,19 +1798,14 @@ void resume_all_vcpus(void)
}
}
void cpu_remove(CPUState *cpu)
void cpu_remove_sync(CPUState *cpu)
{
cpu->stop = true;
cpu->unplug = true;
qemu_cpu_kick(cpu);
}
void cpu_remove_sync(CPUState *cpu)
{
cpu_remove(cpu);
while (cpu->created) {
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
}
qemu_mutex_unlock_iothread();
qemu_thread_join(cpu->thread);
qemu_mutex_lock_iothread();
}
/* For temporary buffers for forming a name */
@ -1877,6 +1923,25 @@ static void qemu_hvf_start_vcpu(CPUState *cpu)
}
}
static void qemu_whpx_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/WHPX",
cpu->cpu_index);
qemu_thread_create(cpu->thread, thread_name, qemu_whpx_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_dummy_start_vcpu(CPUState *cpu)
{
char thread_name[VCPU_THREAD_NAME_SIZE];
@ -1915,6 +1980,8 @@ void qemu_init_vcpu(CPUState *cpu)
qemu_hvf_start_vcpu(cpu);
} else if (tcg_enabled()) {
qemu_tcg_init_vcpu(cpu);
} else if (whpx_enabled()) {
qemu_whpx_start_vcpu(cpu);
} else {
qemu_dummy_start_vcpu(cpu);
}

View File

@ -67,6 +67,7 @@ CONFIG_CADENCE=y
CONFIG_XGMAC=y
CONFIG_EXYNOS4=y
CONFIG_PXA2XX=y
CONFIG_I2C=y
CONFIG_BITBANG_I2C=y
CONFIG_FRAMEBUFFER=y
CONFIG_XILINX_SPIPS=y

View File

@ -62,3 +62,4 @@ CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM)
CONFIG_PXB=y
CONFIG_ACPI_VMGENID=y
CONFIG_FW_CFG_DMA=y
CONFIG_I2C=y

View File

@ -34,3 +34,4 @@ CONFIG_ISA_TESTDEV=y
CONFIG_EMPTY_SLOT=y
CONFIG_MIPS_CPS=y
CONFIG_MIPS_ITU=y
CONFIG_I2C=y

View File

@ -23,6 +23,7 @@ CONFIG_PLATFORM_BUS=y
CONFIG_ETSEC=y
CONFIG_SM501=y
CONFIG_IDE_SII3112=y
CONFIG_I2C=y
# For Macs
CONFIG_MAC=y

View File

@ -17,3 +17,4 @@ CONFIG_XILINX=y
CONFIG_XILINX_ETHLITE=y
CONFIG_SM501=y
CONFIG_IDE_SII3112=y
CONFIG_I2C=y

View File

@ -62,3 +62,4 @@ CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM)
CONFIG_PXB=y
CONFIG_ACPI_VMGENID=y
CONFIG_FW_CFG_DMA=y
CONFIG_I2C=y

View File

@ -1075,6 +1075,30 @@ static void device_class_init(ObjectClass *class, void *data)
dc->user_creatable = true;
}
void device_class_set_parent_reset(DeviceClass *dc,
DeviceReset dev_reset,
DeviceReset *parent_reset)
{
*parent_reset = dc->reset;
dc->reset = dev_reset;
}
void device_class_set_parent_realize(DeviceClass *dc,
DeviceRealize dev_realize,
DeviceRealize *parent_realize)
{
*parent_realize = dc->realize;
dc->realize = dev_realize;
}
void device_class_set_parent_unrealize(DeviceClass *dc,
DeviceUnrealize dev_unrealize,
DeviceUnrealize *parent_unrealize)
{
*parent_unrealize = dc->unrealize;
dc->unrealize = dev_unrealize;
}
void device_reset(DeviceState *dev)
{
DeviceClass *klass = DEVICE_GET_CLASS(dev);

View File

@ -98,7 +98,7 @@
#define FIMD_WINCON_BUFSTATUS ((1 << 21) | (1 << 31))
#define FIMD_WINCON_BUF0_STAT ((0 << 21) | (0 << 31))
#define FIMD_WINCON_BUF1_STAT ((1 << 21) | (0 << 31))
#define FIMD_WINCON_BUF2_STAT ((0 << 21) | (1 << 31))
#define FIMD_WINCON_BUF2_STAT ((0 << 21) | (1U << 31))
#define FIMD_WINCON_BUFSELECT ((1 << 20) | (1 << 30))
#define FIMD_WINCON_BUF0_SEL ((0 << 20) | (0 << 30))
#define FIMD_WINCON_BUF1_SEL ((1 << 20) | (0 << 30))

View File

@ -1,4 +1,4 @@
common-obj-y += core.o smbus.o smbus_eeprom.o
common-obj-$(CONFIG_I2C) += core.o smbus.o smbus_eeprom.o
common-obj-$(CONFIG_DDC) += i2c-ddc.o
common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
common-obj-$(CONFIG_ACPI_X86) += smbus_ich9.o

View File

@ -315,8 +315,8 @@ static void kvm_pit_class_init(ObjectClass *klass, void *data)
PITCommonClass *k = PIT_COMMON_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
kpc->parent_realize = dc->realize;
dc->realize = kvm_pit_realizefn;
device_class_set_parent_realize(dc, kvm_pit_realizefn,
&kpc->parent_realize);
k->set_channel_gate = kvm_pit_set_gate;
k->get_channel_info = kvm_pit_get_channel_info;
dc->reset = kvm_pit_reset;

View File

@ -142,8 +142,7 @@ static void kvm_i8259_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = kvm_pic_reset;
kpc->parent_realize = dc->realize;
dc->realize = kvm_pic_realize;
device_class_set_parent_realize(dc, kvm_pic_realize, &kpc->parent_realize);
k->pre_save = kvm_pic_get;
k->post_load = kvm_pic_put;
}

View File

@ -374,8 +374,8 @@ static void adb_kbd_class_init(ObjectClass *oc, void *data)
ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
ADBKeyboardClass *akc = ADB_KEYBOARD_CLASS(oc);
akc->parent_realize = dc->realize;
dc->realize = adb_kbd_realizefn;
device_class_set_parent_realize(dc, adb_kbd_realizefn,
&akc->parent_realize);
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
adc->devreq = adb_kbd_request;

View File

@ -228,8 +228,8 @@ static void adb_mouse_class_init(ObjectClass *oc, void *data)
ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
amc->parent_realize = dc->realize;
dc->realize = adb_mouse_realizefn;
device_class_set_parent_realize(dc, adb_mouse_realizefn,
&amc->parent_realize);
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
adc->devreq = adb_mouse_request;

View File

@ -1461,8 +1461,7 @@ static void arm_gic_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
ARMGICClass *agc = ARM_GIC_CLASS(klass);
agc->parent_realize = dc->realize;
dc->realize = arm_gic_realize;
device_class_set_parent_realize(dc, arm_gic_realize, &agc->parent_realize);
}
static const TypeInfo arm_gic_info = {

View File

@ -591,10 +591,9 @@ static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
agcc->pre_save = kvm_arm_gic_get;
agcc->post_load = kvm_arm_gic_put;
kgc->parent_realize = dc->realize;
kgc->parent_reset = dc->reset;
dc->realize = kvm_arm_gic_realize;
dc->reset = kvm_arm_gic_reset;
device_class_set_parent_realize(dc, kvm_arm_gic_realize,
&kgc->parent_realize);
device_class_set_parent_reset(dc, kvm_arm_gic_reset, &kgc->parent_reset);
}
static const TypeInfo kvm_arm_gic_info = {

View File

@ -385,8 +385,7 @@ static void arm_gicv3_class_init(ObjectClass *klass, void *data)
ARMGICv3Class *agc = ARM_GICV3_CLASS(klass);
agcc->post_load = arm_gicv3_post_load;
agc->parent_realize = dc->realize;
dc->realize = arm_gic_realize;
device_class_set_parent_realize(dc, arm_gic_realize, &agc->parent_realize);
}
static const TypeInfo arm_gicv3_info = {

View File

@ -245,11 +245,10 @@ static void kvm_arm_its_class_init(ObjectClass *klass, void *data)
dc->realize = kvm_arm_its_realize;
dc->props = kvm_arm_its_props;
ic->parent_reset = dc->reset;
device_class_set_parent_reset(dc, kvm_arm_its_reset, &ic->parent_reset);
icc->send_msi = kvm_its_send_msi;
icc->pre_save = kvm_arm_its_pre_save;
icc->post_load = kvm_arm_its_post_load;
dc->reset = kvm_arm_its_reset;
}
static const TypeInfo kvm_arm_its_info = {

View File

@ -795,10 +795,9 @@ static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)
agcc->pre_save = kvm_arm_gicv3_get;
agcc->post_load = kvm_arm_gicv3_put;
kgc->parent_realize = dc->realize;
kgc->parent_reset = dc->reset;
dc->realize = kvm_arm_gicv3_realize;
dc->reset = kvm_arm_gicv3_reset;
device_class_set_parent_realize(dc, kvm_arm_gicv3_realize,
&kgc->parent_realize);
device_class_set_parent_reset(dc, kvm_arm_gicv3_reset, &kgc->parent_reset);
}
static const TypeInfo kvm_arm_gicv3_info = {

View File

@ -443,8 +443,7 @@ static void i8259_class_init(ObjectClass *klass, void *data)
PICClass *k = PIC_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
k->parent_realize = dc->realize;
dc->realize = pic_realize;
device_class_set_parent_realize(dc, pic_realize, &k->parent_realize);
dc->reset = pic_reset;
}

View File

@ -76,6 +76,7 @@ typedef struct Peer {
typedef struct MSIVector {
PCIDevice *pdev;
int virq;
bool unmasked;
} MSIVector;
typedef struct IVShmemState {
@ -316,6 +317,11 @@ static int ivshmem_vector_unmask(PCIDevice *dev, unsigned vector,
int ret;
IVSHMEM_DPRINTF("vector unmask %p %d\n", dev, vector);
if (!v->pdev) {
error_report("ivshmem: vector %d route does not exist", vector);
return -EINVAL;
}
assert(!v->unmasked);
ret = kvm_irqchip_update_msi_route(kvm_state, v->virq, msg, dev);
if (ret < 0) {
@ -323,22 +329,35 @@ static int ivshmem_vector_unmask(PCIDevice *dev, unsigned vector,
}
kvm_irqchip_commit_routes(kvm_state);
return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, v->virq);
ret = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, v->virq);
if (ret < 0) {
return ret;
}
v->unmasked = true;
return 0;
}
static void ivshmem_vector_mask(PCIDevice *dev, unsigned vector)
{
IVShmemState *s = IVSHMEM_COMMON(dev);
EventNotifier *n = &s->peers[s->vm_id].eventfds[vector];
MSIVector *v = &s->msi_vectors[vector];
int ret;
IVSHMEM_DPRINTF("vector mask %p %d\n", dev, vector);
ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n,
s->msi_vectors[vector].virq);
if (ret != 0) {
error_report("remove_irqfd_notifier_gsi failed");
if (!v->pdev) {
error_report("ivshmem: vector %d route does not exist", vector);
return;
}
assert(v->unmasked);
ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, v->virq);
if (ret < 0) {
error_report("remove_irqfd_notifier_gsi failed");
return;
}
v->unmasked = false;
}
static void ivshmem_vector_poll(PCIDevice *dev,
@ -738,10 +757,14 @@ static void ivshmem_msix_vector_use(IVShmemState *s)
}
}
static void ivshmem_disable_irqfd(IVShmemState *s);
static void ivshmem_reset(DeviceState *d)
{
IVShmemState *s = IVSHMEM_COMMON(d);
ivshmem_disable_irqfd(s);
s->intrstatus = 0;
s->intrmask = 0;
if (ivshmem_has_feature(s, IVSHMEM_MSI)) {
@ -766,29 +789,6 @@ static int ivshmem_setup_interrupts(IVShmemState *s, Error **errp)
return 0;
}
static void ivshmem_enable_irqfd(IVShmemState *s)
{
PCIDevice *pdev = PCI_DEVICE(s);
int i;
for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) {
Error *err = NULL;
ivshmem_add_kvm_msi_virq(s, i, &err);
if (err) {
error_report_err(err);
/* TODO do we need to handle the error? */
}
}
if (msix_set_vector_notifiers(pdev,
ivshmem_vector_unmask,
ivshmem_vector_mask,
ivshmem_vector_poll)) {
error_report("ivshmem: msix_set_vector_notifiers failed");
}
}
static void ivshmem_remove_kvm_msi_virq(IVShmemState *s, int vector)
{
IVSHMEM_DPRINTF("ivshmem_remove_kvm_msi_virq vector:%d\n", vector);
@ -803,16 +803,59 @@ static void ivshmem_remove_kvm_msi_virq(IVShmemState *s, int vector)
s->msi_vectors[vector].pdev = NULL;
}
static void ivshmem_disable_irqfd(IVShmemState *s)
static void ivshmem_enable_irqfd(IVShmemState *s)
{
PCIDevice *pdev = PCI_DEVICE(s);
int i;
for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) {
Error *err = NULL;
ivshmem_add_kvm_msi_virq(s, i, &err);
if (err) {
error_report_err(err);
goto undo;
}
}
if (msix_set_vector_notifiers(pdev,
ivshmem_vector_unmask,
ivshmem_vector_mask,
ivshmem_vector_poll)) {
error_report("ivshmem: msix_set_vector_notifiers failed");
goto undo;
}
return;
undo:
while (--i >= 0) {
ivshmem_remove_kvm_msi_virq(s, i);
}
}
static void ivshmem_disable_irqfd(IVShmemState *s)
{
PCIDevice *pdev = PCI_DEVICE(s);
int i;
if (!pdev->msix_vector_use_notifier) {
return;
}
msix_unset_vector_notifiers(pdev);
for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) {
/*
* MSI-X is already disabled here so msix_unset_vector_notifiers()
* didn't call our release notifier. Do it now to keep our masks and
* unmasks balanced.
*/
if (s->msi_vectors[i].unmasked) {
ivshmem_vector_mask(pdev, i);
}
ivshmem_remove_kvm_msi_virq(s, i);
}
}
static void ivshmem_write_config(PCIDevice *pdev, uint32_t address,

View File

@ -2664,8 +2664,8 @@ static void vmxnet3_class_init(ObjectClass *class, void *data)
c->class_id = PCI_CLASS_NETWORK_ETHERNET;
c->subsystem_vendor_id = PCI_VENDOR_ID_VMWARE;
c->subsystem_id = PCI_DEVICE_ID_VMWARE_VMXNET3;
vc->parent_dc_realize = dc->realize;
dc->realize = vmxnet3_realize;
device_class_set_parent_realize(dc, vmxnet3_realize,
&vc->parent_dc_realize);
dc->desc = "VMWare Paravirtualized Ethernet v3";
dc->reset = vmxnet3_qdev_reset;
dc->vmsd = &vmstate_vmxnet3;

View File

@ -1,6 +1,6 @@
common-obj-$(CONFIG_DS1225Y) += ds1225y.o
common-obj-y += eeprom93xx.o
common-obj-y += eeprom_at24c.o
common-obj-$(CONFIG_I2C) += eeprom_at24c.o
common-obj-y += fw_cfg.o
common-obj-y += chrp_nvram.o
common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o

View File

@ -137,8 +137,7 @@ static void gen_rp_dev_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_rp_dev;
dc->props = gen_rp_props;
rpc->parent_realize = dc->realize;
dc->realize = gen_rp_realize;
device_class_set_parent_realize(dc, gen_rp_realize, &rpc->parent_realize);
rpc->aer_vector = gen_rp_aer_vector;
rpc->interrupts_init = gen_rp_interrupts_init;

View File

@ -482,7 +482,6 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
int rc;
int sg_version;
struct sg_scsi_id scsiid;
Error *local_err = NULL;
if (!s->conf.blk) {
error_setg(errp, "drive property not set");
@ -516,11 +515,9 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
return;
}
blkconf_apply_backend_options(&s->conf,
blk_is_read_only(s->conf.blk),
true, &local_err);
if (local_err) {
error_propagate(errp, local_err);
if (!blkconf_apply_backend_options(&s->conf,
blk_is_read_only(s->conf.blk),
true, errp)) {
return;
}

View File

@ -1284,8 +1284,8 @@ static void pvscsi_class_init(ObjectClass *klass, void *data)
k->device_id = PCI_DEVICE_ID_VMWARE_PVSCSI;
k->class_id = PCI_CLASS_STORAGE_SCSI;
k->subsystem_id = 0x1000;
pvs_k->parent_dc_realize = dc->realize;
dc->realize = pvscsi_realize;
device_class_set_parent_realize(dc, pvscsi_realize,
&pvs_k->parent_dc_realize);
dc->reset = pvscsi_reset;
dc->vmsd = &vmstate_pvscsi;
dc->props = pvscsi_properties;

View File

@ -358,8 +358,7 @@ static void pit_class_initfn(ObjectClass *klass, void *data)
PITCommonClass *k = PIT_COMMON_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
pc->parent_realize = dc->realize;
dc->realize = pit_realizefn;
device_class_set_parent_realize(dc, pit_realizefn, &pc->parent_realize);
k->set_channel_gate = pit_set_channel_gate;
k->get_channel_info = pit_get_channel_info_common;
k->post_load = pit_post_load;

View File

@ -34,8 +34,8 @@ static void vfio_amd_xgbe_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
VFIOAmdXgbeDeviceClass *vcxc =
VFIO_AMD_XGBE_DEVICE_CLASS(klass);
vcxc->parent_realize = dc->realize;
dc->realize = amd_xgbe_realize;
device_class_set_parent_realize(dc, amd_xgbe_realize,
&vcxc->parent_realize);
dc->desc = "VFIO AMD XGBE";
dc->vmsd = &vfio_platform_amd_xgbe_vmstate;
/* Supported by TYPE_VIRT_MACHINE */

View File

@ -34,8 +34,8 @@ static void vfio_calxeda_xgmac_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
VFIOCalxedaXgmacDeviceClass *vcxc =
VFIO_CALXEDA_XGMAC_DEVICE_CLASS(klass);
vcxc->parent_realize = dc->realize;
dc->realize = calxeda_xgmac_realize;
device_class_set_parent_realize(dc, calxeda_xgmac_realize,
&vcxc->parent_realize);
dc->desc = "VFIO Calxeda XGMAC";
dc->vmsd = &vfio_platform_calxeda_xgmac_vmstate;
/* Supported by TYPE_VIRT_MACHINE */

View File

@ -1187,19 +1187,27 @@ static void vfio_disconnect_container(VFIOGroup *group)
{
VFIOContainer *container = group->container;
QLIST_REMOVE(group, container_next);
group->container = NULL;
/*
* Explicitly release the listener first before unset container,
* since unset may destroy the backend container if it's the last
* group.
*/
if (QLIST_EMPTY(&container->group_list)) {
vfio_listener_release(container);
}
if (ioctl(group->fd, VFIO_GROUP_UNSET_CONTAINER, &container->fd)) {
error_report("vfio: error disconnecting group %d from container",
group->groupid);
}
QLIST_REMOVE(group, container_next);
group->container = NULL;
if (QLIST_EMPTY(&container->group_list)) {
VFIOAddressSpace *space = container->space;
VFIOGuestIOMMU *giommu, *tmp;
vfio_listener_release(container);
QLIST_REMOVE(container, next);
QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {

View File

@ -25,3 +25,9 @@ virtio_balloon_handle_output(const char *name, uint64_t gpa) "section name: %s g
virtio_balloon_get_config(uint32_t num_pages, uint32_t actual) "num_pages: %d actual: %d"
virtio_balloon_set_config(uint32_t actual, uint32_t oldactual) "actual: %d oldactual: %d"
virtio_balloon_to_target(uint64_t target, uint32_t num_pages) "balloon target: 0x%"PRIx64" num_pages: %d"
# hw/virtio/vhost.c
vhost_region_add(void *p, const char *mr) "dev %p mr %s"
vhost_region_del(void *p, const char *mr) "dev %p mr %s"
vhost_iommu_region_add(void *p, const char *mr) "dev %p mr %s"
vhost_iommu_region_del(void *p, const char *mr) "dev %p mr %s"

View File

@ -27,6 +27,7 @@
#include "hw/virtio/virtio-access.h"
#include "migration/blocker.h"
#include "sysemu/dma.h"
#include "trace.h"
/* enabled until disconnected backend stabilizes */
#define _VHOST_DEBUG 1
@ -329,6 +330,7 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev)
static struct vhost_log *vhost_log_alloc(uint64_t size, bool share)
{
Error *err = NULL;
struct vhost_log *log;
uint64_t logsize = size * sizeof(*(log->log));
int fd = -1;
@ -337,7 +339,12 @@ static struct vhost_log *vhost_log_alloc(uint64_t size, bool share)
if (share) {
log->log = qemu_memfd_alloc("vhost-log", logsize,
F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL,
&fd);
&fd, &err);
if (err) {
error_report_err(err);
g_free(log);
return NULL;
}
memset(log->log, 0, logsize);
} else {
log->log = g_malloc0(logsize);
@ -687,6 +694,7 @@ static void vhost_region_add(MemoryListener *listener,
return;
}
trace_vhost_region_add(dev, section->mr->name ?: NULL);
++dev->n_mem_sections;
dev->mem_sections = g_renew(MemoryRegionSection, dev->mem_sections,
dev->n_mem_sections);
@ -706,6 +714,7 @@ static void vhost_region_del(MemoryListener *listener,
return;
}
trace_vhost_region_del(dev, section->mr->name ?: NULL);
vhost_set_memory(listener, section, false);
memory_region_unref(section->mr);
for (i = 0; i < dev->n_mem_sections; ++i) {
@ -743,6 +752,8 @@ static void vhost_iommu_region_add(MemoryListener *listener,
return;
}
trace_vhost_iommu_region_add(dev, section->mr->name ?: NULL);
iommu = g_malloc0(sizeof(*iommu));
end = int128_add(int128_make64(section->offset_within_region),
section->size);
@ -771,6 +782,8 @@ static void vhost_iommu_region_del(MemoryListener *listener,
return;
}
trace_vhost_iommu_region_del(dev, section->mr->name ?: NULL);
QLIST_FOREACH(iommu, &dev->iommu_list, iommu_next) {
if (iommu->mr == section->mr &&
iommu->n.start == section->offset_within_region) {
@ -1361,10 +1374,6 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
if (hdev->mem) {
/* those are only safe after successful init */
memory_listener_unregister(&hdev->memory_listener);
for (i = 0; i < hdev->n_mem_sections; ++i) {
MemoryRegionSection *section = &hdev->mem_sections[i];
memory_region_unref(section->mr);
}
QLIST_REMOVE(hdev, entry);
}
if (hdev->migration_blocker) {

View File

@ -1907,8 +1907,8 @@ static void virtio_pci_class_init(ObjectClass *klass, void *data)
k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
k->revision = VIRTIO_PCI_ABI_VERSION;
k->class_id = PCI_CLASS_OTHERS;
vpciklass->parent_dc_realize = dc->realize;
dc->realize = virtio_pci_dc_realize;
device_class_set_parent_realize(dc, virtio_pci_dc_realize,
&vpciklass->parent_dc_realize);
dc->reset = virtio_pci_reset;
}

View File

@ -1,5 +1,5 @@
/*
* Declarations for obsolete exec.c functions
* Declarations for functions which are internal to the memory subsystem.
*
* Copyright 2011 Red Hat, Inc. and/or its affiliates
*
@ -12,8 +12,9 @@
*/
/*
* This header is for use by exec.c and memory.c ONLY. Do not include it.
* The functions declared here will be removed soon.
* This header is for use by exec.c, memory.c and accel/tcg/cputlb.c ONLY,
* for declarations which are shared between the memory subsystem's
* internals and the TCG TLB code. Do not include it from elsewhere.
*/
#ifndef MEMORY_INTERNAL_H

View File

@ -332,7 +332,7 @@ FlatView *address_space_to_flatview(AddressSpace *as);
* MemoryRegionSection: describes a fragment of a #MemoryRegion
*
* @mr: the region, or %NULL if empty
* @address_space: the address space the region is mapped in
* @fv: the flat view of the address space the region is mapped in
* @offset_within_region: the beginning of the section, relative to @mr's start
* @size: the size of the section; will not exceed @mr's boundaries
* @offset_within_address_space: the address of the first byte of the section
@ -618,6 +618,7 @@ void memory_region_init_rom_nomigrate(MemoryRegion *mr,
* @mr: the #MemoryRegion to be initialized.
* @owner: the object that tracks the region's reference count
* @ops: callbacks for write access handling (must not be NULL).
* @opaque: passed to the read and write callbacks of the @ops structure.
* @name: Region name, becomes part of RAMBlock name used in migration stream
* must be unique within any device
* @size: size of the region.
@ -661,11 +662,10 @@ static inline void memory_region_init_reservation(MemoryRegion *mr,
* An IOMMU region translates addresses and forwards accesses to a target
* memory region.
*
* @typename: QOM class name
* @_iommu_mr: the #IOMMUMemoryRegion to be initialized
* @instance_size: the IOMMUMemoryRegion subclass instance size
* @mrtypename: the type name of the #IOMMUMemoryRegion
* @owner: the object that tracks the region's reference count
* @ops: a function that translates addresses into the @target region
* @name: used for debugging; not visible to the user or ABI
* @size: size of the region.
*/
@ -835,8 +835,8 @@ static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr)
* memory_region_get_iommu_class_nocheck: returns iommu memory region class
* if an iommu or NULL if not
*
* Returns pointer to IOMMUMemoryRegioniClass if a memory region is an iommu,
* otherwise NULL. This is fast path avoinding QOM checking, use with caution.
* Returns pointer to IOMMUMemoryRegionClass if a memory region is an iommu,
* otherwise NULL. This is fast path avoiding QOM checking, use with caution.
*
* @mr: the memory region being queried
*/
@ -1015,7 +1015,8 @@ int memory_region_get_fd(MemoryRegion *mr);
* protecting the pointer, such as a reference to the region that includes
* the incoming ram_addr_t.
*
* @mr: the memory region being queried.
* @ptr: the host pointer to be converted
* @offset: the offset within memory region
*/
MemoryRegion *memory_region_from_host(void *ptr, ram_addr_t *offset);
@ -1292,7 +1293,7 @@ void memory_region_clear_global_locking(MemoryRegion *mr);
* @size: the size of the access to trigger the eventfd
* @match_data: whether to match against @data, instead of just @addr
* @data: the data to match against the guest write
* @fd: the eventfd to be triggered when @addr, @size, and @data all match.
* @e: event notifier to be triggered when @addr, @size, and @data all match.
**/
void memory_region_add_eventfd(MemoryRegion *mr,
hwaddr addr,
@ -1312,7 +1313,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
* @size: the size of the access to trigger the eventfd
* @match_data: whether to match against @data, instead of just @addr
* @data: the data to match against the guest write
* @fd: the eventfd to be triggered when @addr, @size, and @data all match.
* @e: event notifier to be triggered when @addr, @size, and @data all match.
*/
void memory_region_del_eventfd(MemoryRegion *mr,
hwaddr addr,
@ -1548,7 +1549,7 @@ bool memory_region_request_mmio_ptr(MemoryRegion *mr, hwaddr addr);
* will need to request the pointer again.
*
* @mr: #MemoryRegion associated to the pointer.
* @addr: address within that region
* @offset: offset within the memory region
* @size: size of that area.
*/
void memory_region_invalidate_mmio_ptr(MemoryRegion *mr, hwaddr offset,
@ -1617,6 +1618,7 @@ void address_space_destroy(AddressSpace *as);
* @addr: address within that address space
* @attrs: memory transaction attributes
* @buf: buffer with the data transferred
* @len: the number of bytes to read or write
* @is_write: indicates the transfer direction
*/
MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
@ -1634,6 +1636,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
* @addr: address within that address space
* @attrs: memory transaction attributes
* @buf: buffer with the data transferred
* @len: the number of bytes to write
*/
MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs,
@ -1832,7 +1835,7 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
* called from an RCU critical section, to avoid that the last reference
* to the returned region disappears after address_space_translate returns.
*
* @as: #AddressSpace to be accessed
* @fv: #FlatView to be accessed
* @addr: address within that address space
* @xlat: pointer to address within the returned memory region section's
* #MemoryRegion.
@ -1890,7 +1893,7 @@ void *address_space_map(AddressSpace *as, hwaddr addr,
* the amount of memory that was actually read or written by the caller.
*
* @as: #AddressSpace used
* @addr: address within that address space
* @buffer: host pointer as returned by address_space_map()
* @len: buffer length as returned by address_space_map()
* @access_len: amount of data actually transferred
* @is_write: indicates the transfer direction
@ -1927,7 +1930,7 @@ static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
* or failed (eg unassigned memory, device rejected the transaction,
* IOMMU fault).
*
* @as: #AddressSpace to be accessed
* @fv: #FlatView to be accessed
* @addr: address within that address space
* @attrs: memory transaction attributes
* @buf: buffer with the data transferred

View File

@ -32,9 +32,9 @@ typedef enum DeviceCategory {
typedef int (*qdev_initfn)(DeviceState *dev);
typedef int (*qdev_event)(DeviceState *dev);
typedef void (*qdev_resetfn)(DeviceState *dev);
typedef void (*DeviceRealize)(DeviceState *dev, Error **errp);
typedef void (*DeviceUnrealize)(DeviceState *dev, Error **errp);
typedef void (*DeviceReset)(DeviceState *dev);
typedef void (*BusRealize)(BusState *bus, Error **errp);
typedef void (*BusUnrealize)(BusState *bus, Error **errp);
@ -117,7 +117,7 @@ typedef struct DeviceClass {
bool hotpluggable;
/* callbacks */
void (*reset)(DeviceState *dev);
DeviceReset reset;
DeviceRealize realize;
DeviceUnrealize unrealize;
@ -382,6 +382,16 @@ void qdev_machine_init(void);
*/
void device_reset(DeviceState *dev);
void device_class_set_parent_reset(DeviceClass *dc,
DeviceReset dev_reset,
DeviceReset *parent_reset);
void device_class_set_parent_realize(DeviceClass *dc,
DeviceRealize dev_realize,
DeviceRealize *parent_realize);
void device_class_set_parent_unrealize(DeviceClass *dc,
DeviceUnrealize dev_unrealize,
DeviceUnrealize *parent_unrealize);
const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
const char *qdev_fw_name(DeviceState *dev);

View File

@ -111,4 +111,8 @@
#define GCC_FMT_ATTR(n, m)
#endif
#ifndef __has_feature
#define __has_feature(x) 0 /* compatibility with non-clang compilers */
#endif
#endif /* COMPILER_H */

View File

@ -16,9 +16,10 @@
#define F_SEAL_WRITE 0x0008 /* prevent writes */
#endif
int qemu_memfd_create(const char *name, size_t size, unsigned int seals);
int qemu_memfd_create(const char *name, size_t size, bool hugetlb,
uint64_t hugetlbsize, unsigned int seals, Error **errp);
void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
int *fd);
int *fd, Error **errp);
void qemu_memfd_free(void *ptr, size_t size, int fd);
bool qemu_memfd_check(void);

View File

@ -12,9 +12,6 @@
#if defined(__i386__) || defined(__x86_64__)
# define cpu_relax() asm volatile("rep; nop" ::: "memory")
#elif defined(__ia64__)
# define cpu_relax() asm volatile("hint @pause" ::: "memory")
#elif defined(__aarch64__)
# define cpu_relax() asm volatile("yield" ::: "memory")

View File

@ -931,15 +931,6 @@ static inline int64_t cpu_get_host_ticks(void)
return val;
}
#elif defined(__ia64)
static inline int64_t cpu_get_host_ticks(void)
{
int64_t val;
asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
return val;
}
#elif defined(__s390__)
static inline int64_t cpu_get_host_ticks(void)

View File

@ -14,6 +14,7 @@
#include "qom/cpu.h"
#include "sysemu/hax.h"
#include "sysemu/kvm.h"
#include "sysemu/whpx.h"
static inline void cpu_synchronize_state(CPUState *cpu)
{
@ -23,6 +24,9 @@ static inline void cpu_synchronize_state(CPUState *cpu)
if (hax_enabled()) {
hax_cpu_synchronize_state(cpu);
}
if (whpx_enabled()) {
whpx_cpu_synchronize_state(cpu);
}
}
static inline void cpu_synchronize_post_reset(CPUState *cpu)
@ -33,6 +37,9 @@ static inline void cpu_synchronize_post_reset(CPUState *cpu)
if (hax_enabled()) {
hax_cpu_synchronize_post_reset(cpu);
}
if (whpx_enabled()) {
whpx_cpu_synchronize_post_reset(cpu);
}
}
static inline void cpu_synchronize_post_init(CPUState *cpu)
@ -43,6 +50,9 @@ static inline void cpu_synchronize_post_init(CPUState *cpu)
if (hax_enabled()) {
hax_cpu_synchronize_post_init(cpu);
}
if (whpx_enabled()) {
whpx_cpu_synchronize_post_init(cpu);
}
}
static inline void cpu_synchronize_pre_loadvm(CPUState *cpu)
@ -53,6 +63,9 @@ static inline void cpu_synchronize_pre_loadvm(CPUState *cpu)
if (hax_enabled()) {
hax_cpu_synchronize_pre_loadvm(cpu);
}
if (whpx_enabled()) {
whpx_cpu_synchronize_pre_loadvm(cpu);
}
}
#endif /* QEMU_HW_ACCEL_H */

40
include/sysemu/whpx.h Normal file
View File

@ -0,0 +1,40 @@
/*
* QEMU Windows Hypervisor Platform accelerator (WHPX) support
*
* Copyright Microsoft, Corp. 2017
*
* Authors:
*
* 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_WHPX_H
#define QEMU_WHPX_H
#include "config-host.h"
#include "qemu-common.h"
int whpx_init_vcpu(CPUState *cpu);
int whpx_vcpu_exec(CPUState *cpu);
void whpx_destroy_vcpu(CPUState *cpu);
void whpx_vcpu_kick(CPUState *cpu);
void whpx_cpu_synchronize_state(CPUState *cpu);
void whpx_cpu_synchronize_post_reset(CPUState *cpu);
void whpx_cpu_synchronize_post_init(CPUState *cpu);
void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu);
#ifdef CONFIG_WHPX
int whpx_enabled(void);
#else /* CONFIG_WHPX */
#define whpx_enabled() (0)
#endif /* CONFIG_WHPX */
#endif /* QEMU_WHPX_H */

View File

@ -36,10 +36,6 @@
#include <linux/capability.h>
#include <sched.h>
#include <sys/timex.h>
#ifdef __ia64__
int __clone2(int (*fn)(void *), void *child_stack_base,
size_t stack_size, int flags, void *arg, ...);
#endif
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
@ -246,8 +242,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || \
defined(__s390x__)
#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
#define __NR__llseek __NR_lseek
#endif

View File

@ -1091,6 +1091,7 @@ void memory_region_transaction_commit(void)
address_space_update_ioeventfds(as);
}
memory_region_update_pending = false;
ioeventfd_update_pending = false;
MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
} else if (ioeventfd_update_pending) {
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
@ -2624,6 +2625,32 @@ static void listener_add_address_space(MemoryListener *listener,
flatview_unref(view);
}
static void listener_del_address_space(MemoryListener *listener,
AddressSpace *as)
{
FlatView *view;
FlatRange *fr;
if (listener->begin) {
listener->begin(listener);
}
view = address_space_get_flatview(as);
FOR_EACH_FLAT_RANGE(fr, view) {
MemoryRegionSection section = section_from_flat_range(fr, view);
if (fr->dirty_log_mask && listener->log_stop) {
listener->log_stop(listener, &section, fr->dirty_log_mask, 0);
}
if (listener->region_del) {
listener->region_del(listener, &section);
}
}
if (listener->commit) {
listener->commit(listener);
}
flatview_unref(view);
}
void memory_listener_register(MemoryListener *listener, AddressSpace *as)
{
MemoryListener *other = NULL;
@ -2664,6 +2691,7 @@ void memory_listener_unregister(MemoryListener *listener)
return;
}
listener_del_address_space(listener, listener->address_space);
QTAILQ_REMOVE(&memory_listeners, listener, link);
QTAILQ_REMOVE(&listener->address_space->listeners, listener, link_as);
listener->address_space = NULL;

1
numa.c
View File

@ -463,6 +463,7 @@ static void allocate_system_memory_nonnuma(MemoryRegion *mr, Object *owner,
if (mem_prealloc) {
exit(1);
}
error_report("falling back to regular RAM allocation.");
/* Legacy behavior: if allocation failed, fall back to
* regular RAM allocation.

View File

@ -31,7 +31,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
"-machine [type=]name[,prop[=value][,...]]\n"
" selects emulated machine ('-machine help' for list)\n"
" property accel=accel1[:accel2[:...]] selects accelerator\n"
" supported accelerators are kvm, xen, hax, hvf or tcg (default: tcg)\n"
" supported accelerators are kvm, xen, hax, hvf, whpx or tcg (default: tcg)\n"
" kernel_irqchip=on|off|split controls accelerated irqchip support (default=off)\n"
" vmport=on|off|auto controls emulation of vmport (default: auto)\n"
" kvm_shadow_mem=size of KVM shadow MMU in bytes\n"
@ -66,7 +66,7 @@ Supported machine properties are:
@table @option
@item accel=@var{accels1}[:@var{accels2}[:...]]
This is used to enable an accelerator. Depending on the target architecture,
kvm, xen, hax, hvf or tcg can be available. By default, tcg is used. If there is
kvm, xen, hax, hvf, whpx or tcg can be available. By default, tcg is used. If there is
more than one accelerator specified, the next one is used if the previous one
fails to initialize.
@item kernel_irqchip=on|off
@ -126,13 +126,13 @@ ETEXI
DEF("accel", HAS_ARG, QEMU_OPTION_accel,
"-accel [accel=]accelerator[,thread=single|multi]\n"
" select accelerator (kvm, xen, hax, hvf or tcg; use 'help' for a list)\n"
" select accelerator (kvm, xen, hax, hvf, whpx or tcg; use 'help' for a list)\n"
" thread=single|multi (enable multi-threaded TCG)", QEMU_ARCH_ALL)
STEXI
@item -accel @var{name}[,prop=@var{value}[,...]]
@findex -accel
This is used to enable an accelerator. Depending on the target architecture,
kvm, xen, hax, hvf or tcg can be available. By default, tcg is used. If there is
kvm, xen, hax, hvf, whpx or tcg can be available. By default, tcg is used. If there is
more than one accelerator specified, the next one is used if the previous one
fails to initialize.
@table @option
@ -4024,6 +4024,28 @@ Memory backend objects offer more control than the @option{-m} option that is
traditionally used to define guest RAM. Please refer to
@option{memory-backend-file} for a description of the options.
@item -object memory-backend-memfd,id=@var{id},merge=@var{on|off},dump=@var{on|off},prealloc=@var{on|off},size=@var{size},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave},seal=@var{on|off},hugetlb=@var{on|off},hugetlbsize=@var{size}
Creates an anonymous memory file backend object, which allows QEMU to
share the memory with an external process (e.g. when using
vhost-user). The memory is allocated with memfd and optional
sealing. (Linux only)
The @option{seal} option creates a sealed-file, that will block
further resizing the memory ('on' by default).
The @option{hugetlb} option specify the file to be created resides in
the hugetlbfs filesystem (since Linux 4.14). Used in conjunction with
the @option{hugetlb} option, the @option{hugetlbsize} option specify
the hugetlb page size on systems that support multiple hugetlb page
sizes (it must be a power of 2 value supported by the system).
In some versions of Linux, the @option{hugetlb} option is incompatible
with the @option{seal} option (requires at least Linux 4.16).
Please refer to @option{memory-backend-file} for a description of the
other options.
@item -object rng-random,id=@var{id},filename=@var{/dev/random}
Creates a random number generator backend which obtains entropy from

View File

@ -1,4 +1,5 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# GDB debugging support
#
# Copyright 2017 Linaro Ltd

View File

@ -233,8 +233,8 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
AlphaCPUClass *acc = ALPHA_CPU_CLASS(oc);
acc->parent_realize = dc->realize;
dc->realize = alpha_cpu_realizefn;
device_class_set_parent_realize(dc, alpha_cpu_realizefn,
&acc->parent_realize);
cc->class_by_name = alpha_cpu_class_by_name;
cc->has_work = alpha_cpu_has_work;

View File

@ -1722,8 +1722,8 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(acc);
DeviceClass *dc = DEVICE_CLASS(oc);
acc->parent_realize = dc->realize;
dc->realize = arm_cpu_realizefn;
device_class_set_parent_realize(dc, arm_cpu_realizefn,
&acc->parent_realize);
dc->props = arm_cpu_properties;
acc->parent_reset = cc->reset;

View File

@ -266,7 +266,6 @@ static void kvm_arm_machine_init_done(Notifier *notifier, void *data)
{
KVMDevice *kd, *tkd;
memory_listener_unregister(&devlistener);
QSLIST_FOREACH_SAFE(kd, &kvm_devices_head, entries, tkd) {
if (kd->kda.addr != -1) {
kvm_arm_set_device_addr(kd);
@ -274,6 +273,7 @@ static void kvm_arm_machine_init_done(Notifier *notifier, void *data)
memory_region_unref(kd->mr);
g_free(kd);
}
memory_listener_unregister(&devlistener);
}
static Notifier notify = {

View File

@ -260,8 +260,8 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->parent_realize = dc->realize;
dc->realize = cris_cpu_realizefn;
device_class_set_parent_realize(dc, cris_cpu_realizefn,
&ccc->parent_realize);
ccc->parent_reset = cc->reset;
cc->reset = cris_cpu_reset;

View File

@ -168,8 +168,8 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
HPPACPUClass *acc = HPPA_CPU_CLASS(oc);
acc->parent_realize = dc->realize;
dc->realize = hppa_cpu_realizefn;
device_class_set_parent_realize(dc, hppa_cpu_realizefn,
&acc->parent_realize);
cc->class_by_name = hppa_cpu_class_by_name;
cc->has_work = hppa_cpu_has_work;

View File

@ -14,3 +14,4 @@ ifdef CONFIG_DARWIN
obj-$(CONFIG_HAX) += hax-all.o hax-mem.o hax-darwin.o
obj-$(CONFIG_HVF) += hvf/
endif
obj-$(CONFIG_WHPX) += whpx-all.o

View File

@ -4705,10 +4705,10 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
DeviceClass *dc = DEVICE_CLASS(oc);
xcc->parent_realize = dc->realize;
xcc->parent_unrealize = dc->unrealize;
dc->realize = x86_cpu_realizefn;
dc->unrealize = x86_cpu_unrealizefn;
device_class_set_parent_realize(dc, x86_cpu_realizefn,
&xcc->parent_realize);
device_class_set_parent_unrealize(dc, x86_cpu_unrealizefn,
&xcc->parent_unrealize);
dc->props = x86_cpu_properties;
xcc->parent_reset = cc->reset;

View File

@ -986,7 +986,7 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
X86CPU *cpu = x86_env_get_cpu(env);
CPUState *cs = CPU(cpu);
if (kvm_enabled()) {
if (kvm_enabled() || whpx_enabled()) {
env->tpr_access_type = access;
cpu_interrupt(cs, CPU_INTERRUPT_TPR);

View File

@ -17,6 +17,33 @@
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* This file contain code under public domain from the hvdos project:
* https://github.com/mist64/hvdos
*
* Parts Copyright (c) 2011 NetApp, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "qemu/osdep.h"
#include "qemu-common.h"

View File

@ -17,6 +17,9 @@
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* This file contain code under public domain from the hvdos project:
* https://github.com/mist64/hvdos
*/
#ifndef VMX_H

1366
target/i386/whpx-all.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -236,9 +236,8 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
DeviceClass *dc = DEVICE_CLASS(oc);
lcc->parent_realize = dc->realize;
dc->realize = lm32_cpu_realizefn;
device_class_set_parent_realize(dc, lm32_cpu_realizefn,
&lcc->parent_realize);
lcc->parent_reset = cc->reset;
cc->reset = lm32_cpu_reset;

View File

@ -255,9 +255,8 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
CPUClass *cc = CPU_CLASS(c);
DeviceClass *dc = DEVICE_CLASS(c);
mcc->parent_realize = dc->realize;
dc->realize = m68k_cpu_realizefn;
device_class_set_parent_realize(dc, m68k_cpu_realizefn,
&mcc->parent_realize);
mcc->parent_reset = cc->reset;
cc->reset = m68k_cpu_reset;

View File

@ -258,9 +258,8 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_CLASS(oc);
mcc->parent_realize = dc->realize;
dc->realize = mb_cpu_realizefn;
device_class_set_parent_realize(dc, mb_cpu_realizefn,
&mcc->parent_realize);
mcc->parent_reset = cc->reset;
cc->reset = mb_cpu_reset;

View File

@ -174,9 +174,8 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
CPUClass *cc = CPU_CLASS(c);
DeviceClass *dc = DEVICE_CLASS(c);
mcc->parent_realize = dc->realize;
dc->realize = mips_cpu_realizefn;
device_class_set_parent_realize(dc, mips_cpu_realizefn,
&mcc->parent_realize);
mcc->parent_reset = cc->reset;
cc->reset = mips_cpu_reset;

View File

@ -102,9 +102,8 @@ static void moxie_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
MoxieCPUClass *mcc = MOXIE_CPU_CLASS(oc);
mcc->parent_realize = dc->realize;
dc->realize = moxie_cpu_realizefn;
device_class_set_parent_realize(dc, moxie_cpu_realizefn,
&mcc->parent_realize);
mcc->parent_reset = cc->reset;
cc->reset = moxie_cpu_reset;

View File

@ -187,8 +187,8 @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
Nios2CPUClass *ncc = NIOS2_CPU_CLASS(oc);
ncc->parent_realize = dc->realize;
dc->realize = nios2_cpu_realizefn;
device_class_set_parent_realize(dc, nios2_cpu_realizefn,
&ncc->parent_realize);
dc->props = nios2_properties;
ncc->parent_reset = cc->reset;
cc->reset = nios2_cpu_reset;

View File

@ -132,9 +132,8 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(occ);
DeviceClass *dc = DEVICE_CLASS(oc);
occ->parent_realize = dc->realize;
dc->realize = openrisc_cpu_realizefn;
device_class_set_parent_realize(dc, openrisc_cpu_realizefn,
&occ->parent_realize);
occ->parent_reset = cc->reset;
cc->reset = openrisc_cpu_reset;

View File

@ -10556,12 +10556,12 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
DeviceClass *dc = DEVICE_CLASS(oc);
pcc->parent_realize = dc->realize;
pcc->parent_unrealize = dc->unrealize;
device_class_set_parent_realize(dc, ppc_cpu_realizefn,
&pcc->parent_realize);
device_class_set_parent_unrealize(dc, ppc_cpu_unrealizefn,
&pcc->parent_unrealize);
pcc->pvr_match = ppc_pvr_match_default;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
dc->realize = ppc_cpu_realizefn;
dc->unrealize = ppc_cpu_unrealizefn;
dc->props = ppc_cpu_properties;
pcc->parent_reset = cc->reset;

View File

@ -464,8 +464,8 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(scc);
DeviceClass *dc = DEVICE_CLASS(oc);
scc->parent_realize = dc->realize;
dc->realize = s390_cpu_realizefn;
device_class_set_parent_realize(dc, s390_cpu_realizefn,
&scc->parent_realize);
dc->props = s390x_cpu_properties;
dc->user_creatable = true;

View File

@ -236,8 +236,8 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
scc->parent_realize = dc->realize;
dc->realize = superh_cpu_realizefn;
device_class_set_parent_realize(dc, superh_cpu_realizefn,
&scc->parent_realize);
scc->parent_reset = cc->reset;
cc->reset = superh_cpu_reset;

View File

@ -858,8 +858,8 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
DeviceClass *dc = DEVICE_CLASS(oc);
scc->parent_realize = dc->realize;
dc->realize = sparc_cpu_realizefn;
device_class_set_parent_realize(dc, sparc_cpu_realizefn,
&scc->parent_realize);
dc->props = sparc_cpu_properties;
scc->parent_reset = cc->reset;

View File

@ -141,8 +141,8 @@ static void tilegx_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
TileGXCPUClass *tcc = TILEGX_CPU_CLASS(oc);
tcc->parent_realize = dc->realize;
dc->realize = tilegx_cpu_realizefn;
device_class_set_parent_realize(dc, tilegx_cpu_realizefn,
&tcc->parent_realize);
tcc->parent_reset = cc->reset;
cc->reset = tilegx_cpu_reset;

View File

@ -153,8 +153,8 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data)
CPUClass *cc = CPU_CLASS(c);
DeviceClass *dc = DEVICE_CLASS(c);
mcc->parent_realize = dc->realize;
dc->realize = tricore_cpu_realizefn;
device_class_set_parent_realize(dc, tricore_cpu_realizefn,
&mcc->parent_realize);
mcc->parent_reset = cc->reset;
cc->reset = tricore_cpu_reset;

View File

@ -132,8 +132,8 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
UniCore32CPUClass *ucc = UNICORE32_CPU_CLASS(oc);
ucc->parent_realize = dc->realize;
dc->realize = uc32_cpu_realizefn;
device_class_set_parent_realize(dc, uc32_cpu_realizefn,
&ucc->parent_realize);
cc->class_by_name = uc32_cpu_class_by_name;
cc->has_work = uc32_cpu_has_work;

View File

@ -151,8 +151,8 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
XtensaCPUClass *xcc = XTENSA_CPU_CLASS(cc);
xcc->parent_realize = dc->realize;
dc->realize = xtensa_cpu_realizefn;
device_class_set_parent_realize(dc, xtensa_cpu_realizefn,
&xcc->parent_realize);
xcc->parent_reset = cc->reset;
cc->reset = xtensa_cpu_reset;

View File

@ -186,7 +186,6 @@ static void test_redirector_rx(void)
ret = iov_send(send_sock, iov, 2, 0, sizeof(size) + sizeof(send_buf));
g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
close(send_sock);
ret = qemu_recv(backend_sock[0], &len, sizeof(len), 0);
g_assert_cmpint(ret, ==, sizeof(len));
@ -197,6 +196,7 @@ static void test_redirector_rx(void)
ret = qemu_recv(backend_sock[0], recv_buf, len, 0);
g_assert_cmpstr(recv_buf, ==, send_buf);
close(send_sock);
g_free(recv_buf);
unlink(sock_path0);
unlink(sock_path1);

View File

@ -17,6 +17,7 @@
#include "qemu/range.h"
#include "qemu/sockets.h"
#include "chardev/char-fe.h"
#include "qemu/memfd.h"
#include "sysemu/sysemu.h"
#include "libqos/libqos.h"
#include "libqos/pci-pc.h"
@ -30,8 +31,6 @@
#include <linux/virtio_net.h>
#include <sys/vfs.h>
#define VHOST_USER_NET_TESTS_WORKING 0 /* broken as of 2.10.0 */
/* GLIB version compatibility flags */
#if !GLIB_CHECK_VERSION(2, 26, 0)
#define G_TIME_SPAN_SECOND (G_GINT64_CONSTANT(1000000))
@ -41,15 +40,14 @@
#define HAVE_MONOTONIC_TIME
#endif
#define QEMU_CMD_MEM " -m %d -object memory-backend-file,id=mem,size=%dM,"\
#define QEMU_CMD_MEM " -m %d -object memory-backend-file,id=mem,size=%dM," \
"mem-path=%s,share=on -numa node,memdev=mem"
#define QEMU_CMD_MEMFD " -m %d -object memory-backend-memfd,id=mem,size=%dM," \
" -numa node,memdev=mem"
#define QEMU_CMD_CHR " -chardev socket,id=%s,path=%s%s"
#define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=%s,vhostforce"
#define QEMU_CMD_NET " -device virtio-net-pci,netdev=net0"
#define QEMU_CMD QEMU_CMD_MEM QEMU_CMD_CHR \
QEMU_CMD_NETDEV QEMU_CMD_NET
#define HUGETLBFS_MAGIC 0x958458f6
/*********** FROM hw/virtio/vhost-user.c *************************************/
@ -161,9 +159,40 @@ typedef struct TestServer {
QGuestAllocator *alloc;
} TestServer;
static TestServer *test_server_new(const gchar *name);
static void test_server_free(TestServer *server);
static void test_server_listen(TestServer *server);
static const char *tmpfs;
static const char *root;
enum test_memfd {
TEST_MEMFD_AUTO,
TEST_MEMFD_YES,
TEST_MEMFD_NO,
};
static char *get_qemu_cmd(TestServer *s,
int mem, enum test_memfd memfd, const char *mem_path,
const char *chr_opts, const char *extra)
{
if (memfd == TEST_MEMFD_AUTO && qemu_memfd_check()) {
memfd = TEST_MEMFD_YES;
}
if (memfd == TEST_MEMFD_YES) {
return g_strdup_printf(QEMU_CMD_MEMFD QEMU_CMD_CHR
QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem,
s->chr_name, s->socket_path,
chr_opts, s->chr_name, extra);
} else {
return g_strdup_printf(QEMU_CMD_MEM QEMU_CMD_CHR
QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem,
mem_path, s->chr_name, s->socket_path,
chr_opts, s->chr_name, extra);
}
}
static void init_virtio_dev(TestServer *s, uint32_t features_mask)
{
uint32_t features;
@ -227,9 +256,8 @@ static void wait_for_fds(TestServer *s)
g_mutex_unlock(&s->data_mutex);
}
static void read_guest_mem(const void *data)
static void read_guest_mem_server(TestServer *s)
{
TestServer *s = (void *)data;
uint32_t *guest_mem;
int i, j;
size_t size;
@ -494,14 +522,6 @@ static void test_server_listen(TestServer *server)
test_server_create_chr(server, ",server,nowait");
}
#define GET_QEMU_CMD(s) \
g_strdup_printf(QEMU_CMD, 512, 512, (root), (s)->chr_name, \
(s)->socket_path, "", (s)->chr_name)
#define GET_QEMU_CMDE(s, mem, chr_opts, extra, ...) \
g_strdup_printf(QEMU_CMD extra, (mem), (mem), (root), (s)->chr_name, \
(s)->socket_path, (chr_opts), (s)->chr_name, ##__VA_ARGS__)
static gboolean _test_server_free(TestServer *server)
{
int i;
@ -638,8 +658,9 @@ GSourceFuncs test_migrate_source_funcs = {
.check = test_migrate_source_check,
};
static void test_read_guest_mem(void)
static void test_read_guest_mem(const void *arg)
{
enum test_memfd memfd = GPOINTER_TO_INT(arg);
TestServer *server = NULL;
char *qemu_cmd = NULL;
QTestState *s = NULL;
@ -647,14 +668,14 @@ static void test_read_guest_mem(void)
server = test_server_new("test");
test_server_listen(server);
qemu_cmd = GET_QEMU_CMD(server);
qemu_cmd = get_qemu_cmd(server, 512, memfd, root, "", "");
s = qtest_start(qemu_cmd);
g_free(qemu_cmd);
init_virtio_dev(server, 1u << VIRTIO_NET_F_MAC);
read_guest_mem(server);
read_guest_mem_server(server);
uninit_virtio_dev(server);
@ -669,7 +690,7 @@ static void test_migrate(void)
char *uri = g_strdup_printf("%s%s", "unix:", dest->mig_path);
QTestState *global = global_qtest, *from, *to;
GSource *source;
gchar *cmd;
gchar *cmd, *tmp;
QDict *rsp;
guint8 *log;
guint64 size;
@ -677,7 +698,7 @@ static void test_migrate(void)
test_server_listen(s);
test_server_listen(dest);
cmd = GET_QEMU_CMDE(s, 2, "", "");
cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, "", "");
from = qtest_start(cmd);
g_free(cmd);
@ -686,7 +707,9 @@ static void test_migrate(void)
size = get_log_size(s);
g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
cmd = GET_QEMU_CMDE(dest, 2, "", " -incoming %s", uri);
tmp = g_strdup_printf(" -incoming %s", uri);
cmd = get_qemu_cmd(dest, 2, TEST_MEMFD_AUTO, root, "", tmp);
g_free(tmp);
to = qtest_init(cmd);
g_free(cmd);
@ -732,7 +755,7 @@ static void test_migrate(void)
global_qtest = to;
qmp_eventwait("RESUME");
read_guest_mem(dest);
read_guest_mem_server(dest);
uninit_virtio_dev(s);
@ -765,7 +788,7 @@ static void wait_for_rings_started(TestServer *s, size_t count)
g_mutex_unlock(&s->data_mutex);
}
#if VHOST_USER_NET_TESTS_WORKING && defined(CONFIG_HAS_GLIB_SUBPROCESS_TESTS)
#if defined(CONFIG_HAS_GLIB_SUBPROCESS_TESTS)
static inline void test_server_connect(TestServer *server)
{
test_server_create_chr(server, ",reconnect=1");
@ -799,7 +822,7 @@ static void test_reconnect_subprocess(void)
char *cmd;
g_thread_new("connect", connect_thread, s);
cmd = GET_QEMU_CMDE(s, 2, ",server", "");
cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
qtest_start(cmd);
g_free(cmd);
@ -837,7 +860,7 @@ static void test_connect_fail_subprocess(void)
s->test_fail = true;
g_thread_new("connect", connect_thread, s);
cmd = GET_QEMU_CMDE(s, 2, ",server", "");
cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
qtest_start(cmd);
g_free(cmd);
@ -867,7 +890,7 @@ static void test_flags_mismatch_subprocess(void)
s->test_flags = TEST_FLAGS_DISCONNECT;
g_thread_new("connect", connect_thread, s);
cmd = GET_QEMU_CMDE(s, 2, ",server", "");
cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
qtest_start(cmd);
g_free(cmd);
@ -902,11 +925,21 @@ static void test_multiqueue(void)
s->queues = 2;
test_server_listen(s);
cmd = g_strdup_printf(QEMU_CMD_MEM QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d "
"-device virtio-net-pci,netdev=net0,mq=on,vectors=%d",
512, 512, root, s->chr_name,
s->socket_path, "", s->chr_name,
s->queues, s->queues * 2 + 2);
if (qemu_memfd_check()) {
cmd = g_strdup_printf(
QEMU_CMD_MEMFD QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d "
"-device virtio-net-pci,netdev=net0,mq=on,vectors=%d",
512, 512, s->chr_name,
s->socket_path, "", s->chr_name,
s->queues, s->queues * 2 + 2);
} else {
cmd = g_strdup_printf(
QEMU_CMD_MEM QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d "
"-device virtio-net-pci,netdev=net0,mq=on,vectors=%d",
512, 512, root, s->chr_name,
s->socket_path, "", s->chr_name,
s->queues, s->queues * 2 + 2);
}
qtest_start(cmd);
g_free(cmd);
@ -952,20 +985,29 @@ int main(int argc, char **argv)
/* run the main loop thread so the chardev may operate */
thread = g_thread_new(NULL, thread_function, loop);
qtest_add_func("/vhost-user/read-guest-mem", test_read_guest_mem);
if (qemu_memfd_check()) {
qtest_add_data_func("/vhost-user/read-guest-mem/memfd",
GINT_TO_POINTER(TEST_MEMFD_YES),
test_read_guest_mem);
}
qtest_add_data_func("/vhost-user/read-guest-mem/memfile",
GINT_TO_POINTER(TEST_MEMFD_NO), test_read_guest_mem);
qtest_add_func("/vhost-user/migrate", test_migrate);
qtest_add_func("/vhost-user/multiqueue", test_multiqueue);
#if VHOST_USER_NET_TESTS_WORKING && defined(CONFIG_HAS_GLIB_SUBPROCESS_TESTS)
qtest_add_func("/vhost-user/reconnect/subprocess",
test_reconnect_subprocess);
qtest_add_func("/vhost-user/reconnect", test_reconnect);
qtest_add_func("/vhost-user/connect-fail/subprocess",
test_connect_fail_subprocess);
qtest_add_func("/vhost-user/connect-fail", test_connect_fail);
qtest_add_func("/vhost-user/flags-mismatch/subprocess",
test_flags_mismatch_subprocess);
qtest_add_func("/vhost-user/flags-mismatch", test_flags_mismatch);
#if defined(CONFIG_HAS_GLIB_SUBPROCESS_TESTS)
/* keeps failing on build-system since Aug 15 2017 */
if (getenv("QTEST_VHOST_USER_FIXME")) {
qtest_add_func("/vhost-user/reconnect/subprocess",
test_reconnect_subprocess);
qtest_add_func("/vhost-user/reconnect", test_reconnect);
qtest_add_func("/vhost-user/connect-fail/subprocess",
test_connect_fail_subprocess);
qtest_add_func("/vhost-user/connect-fail", test_connect_fail);
qtest_add_func("/vhost-user/flags-mismatch/subprocess",
test_flags_mismatch_subprocess);
qtest_add_func("/vhost-user/flags-mismatch", test_flags_mismatch);
}
#endif
ret = g_test_run();

View File

@ -31,6 +31,13 @@
#include <valgrind/valgrind.h>
#endif
#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
#ifdef CONFIG_ASAN_IFACE_FIBER
#define CONFIG_ASAN 1
#include <sanitizer/asan_interface.h>
#endif
#endif
typedef struct {
Coroutine base;
void *stack;
@ -59,11 +66,37 @@ union cc_arg {
int i[2];
};
static void finish_switch_fiber(void *fake_stack_save)
{
#ifdef CONFIG_ASAN
const void *bottom_old;
size_t size_old;
__sanitizer_finish_switch_fiber(fake_stack_save, &bottom_old, &size_old);
if (!leader.stack) {
leader.stack = (void *)bottom_old;
leader.stack_size = size_old;
}
#endif
}
static void start_switch_fiber(void **fake_stack_save,
const void *bottom, size_t size)
{
#ifdef CONFIG_ASAN
__sanitizer_start_switch_fiber(fake_stack_save, bottom, size);
#endif
}
static void coroutine_trampoline(int i0, int i1)
{
union cc_arg arg;
CoroutineUContext *self;
Coroutine *co;
void *fake_stack_save = NULL;
finish_switch_fiber(NULL);
arg.i[0] = i0;
arg.i[1] = i1;
@ -72,9 +105,13 @@ static void coroutine_trampoline(int i0, int i1)
/* Initialize longjmp environment and switch back the caller */
if (!sigsetjmp(self->env, 0)) {
start_switch_fiber(&fake_stack_save,
leader.stack, leader.stack_size);
siglongjmp(*(sigjmp_buf *)co->entry_arg, 1);
}
finish_switch_fiber(fake_stack_save);
while (true) {
co->entry(co->entry_arg);
qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
@ -87,6 +124,7 @@ Coroutine *qemu_coroutine_new(void)
ucontext_t old_uc, uc;
sigjmp_buf old_env;
union cc_arg arg = {0};
void *fake_stack_save = NULL;
/* The ucontext functions preserve signal masks which incurs a
* system call overhead. sigsetjmp(buf, 0)/siglongjmp() does not
@ -122,8 +160,12 @@ Coroutine *qemu_coroutine_new(void)
/* swapcontext() in, siglongjmp() back out */
if (!sigsetjmp(old_env, 0)) {
start_switch_fiber(&fake_stack_save, co->stack, co->stack_size);
swapcontext(&old_uc, &uc);
}
finish_switch_fiber(fake_stack_save);
return &co->base;
}
@ -169,13 +211,19 @@ qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
CoroutineUContext *from = DO_UPCAST(CoroutineUContext, base, from_);
CoroutineUContext *to = DO_UPCAST(CoroutineUContext, base, to_);
int ret;
void *fake_stack_save = NULL;
current = to_;
ret = sigsetjmp(from->env, 0);
if (ret == 0) {
start_switch_fiber(action == COROUTINE_TERMINATE ?
NULL : &fake_stack_save, to->stack, to->stack_size);
siglongjmp(to->env, action);
}
finish_switch_fiber(fake_stack_save);
return ret;
}

View File

@ -27,7 +27,9 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/memfd.h"
#include "qemu/host-utils.h"
#if defined CONFIG_LINUX && !defined CONFIG_MEMFD
#include <sys/syscall.h>
@ -51,36 +53,59 @@ static int memfd_create(const char *name, unsigned int flags)
#define MFD_ALLOW_SEALING 0x0002U
#endif
int qemu_memfd_create(const char *name, size_t size, unsigned int seals)
#ifndef MFD_HUGETLB
#define MFD_HUGETLB 0x0004U
#endif
#ifndef MFD_HUGE_SHIFT
#define MFD_HUGE_SHIFT 26
#endif
int qemu_memfd_create(const char *name, size_t size, bool hugetlb,
uint64_t hugetlbsize, unsigned int seals, Error **errp)
{
int mfd = -1;
int htsize = hugetlbsize ? ctz64(hugetlbsize) : 0;
if (htsize && 1 << htsize != hugetlbsize) {
error_setg(errp, "Hugepage size must be a power of 2");
return -1;
}
htsize = htsize << MFD_HUGE_SHIFT;
#ifdef CONFIG_LINUX
int mfd = -1;
unsigned int flags = MFD_CLOEXEC;
if (seals) {
flags |= MFD_ALLOW_SEALING;
}
if (hugetlb) {
flags |= MFD_HUGETLB;
flags |= htsize;
}
mfd = memfd_create(name, flags);
if (mfd < 0) {
return -1;
goto err;
}
if (ftruncate(mfd, size) == -1) {
perror("ftruncate");
close(mfd);
return -1;
goto err;
}
if (seals && fcntl(mfd, F_ADD_SEALS, seals) == -1) {
perror("fcntl");
close(mfd);
return -1;
goto err;
}
#endif
return mfd;
err:
if (mfd >= 0) {
close(mfd);
}
#endif
error_setg_errno(errp, errno, "failed to create memfd");
return -1;
}
/*
@ -90,14 +115,14 @@ int qemu_memfd_create(const char *name, size_t size, unsigned int seals)
* sealing.
*/
void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
int *fd)
int *fd, Error **errp)
{
void *ptr;
int mfd = qemu_memfd_create(name, size, seals);
int mfd = qemu_memfd_create(name, size, false, 0, seals, NULL);
/* some systems have memfd without sealing */
if (mfd == -1) {
mfd = qemu_memfd_create(name, size, 0);
mfd = qemu_memfd_create(name, size, false, 0, 0, NULL);
}
if (mfd == -1) {
@ -109,27 +134,26 @@ void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
unlink(fname);
g_free(fname);
if (mfd == -1) {
perror("mkstemp");
return NULL;
}
if (ftruncate(mfd, size) == -1) {
perror("ftruncate");
close(mfd);
return NULL;
if (mfd == -1 ||
ftruncate(mfd, size) == -1) {
goto err;
}
}
ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, mfd, 0);
if (ptr == MAP_FAILED) {
perror("mmap");
close(mfd);
return NULL;
goto err;
}
*fd = mfd;
return ptr;
err:
error_setg_errno(errp, errno, "failed to allocate shared memory");
if (mfd >= 0) {
close(mfd);
}
return NULL;
}
void qemu_memfd_free(void *ptr, size_t size, int fd)
@ -157,7 +181,7 @@ bool qemu_memfd_check(void)
int fd;
void *ptr;
ptr = qemu_memfd_alloc("test", 4096, 0, &fd);
ptr = qemu_memfd_alloc("test", 4096, 0, &fd, NULL);
memfd_check = ptr ? MEMFD_OK : MEMFD_KO;
qemu_memfd_free(ptr, 4096, fd);
}

View File

@ -554,6 +554,33 @@ err:
}
/* compatibility wrapper */
static int inet_parse_flag(const char *flagname, const char *optstr, bool *val,
Error **errp)
{
char *end;
size_t len;
end = strstr(optstr, ",");
if (end) {
if (end[1] == ',') { /* Reject 'ipv6=on,,foo' */
error_setg(errp, "error parsing '%s' flag '%s'", flagname, optstr);
return -1;
}
len = end - optstr;
} else {
len = strlen(optstr);
}
if (len == 0 || (len == 3 && strncmp(optstr, "=on", len) == 0)) {
*val = true;
} else if (len == 4 && strncmp(optstr, "=off", len) == 0) {
*val = false;
} else {
error_setg(errp, "error parsing '%s' flag '%s'", flagname, optstr);
return -1;
}
return 0;
}
int inet_parse(InetSocketAddress *addr, const char *str, Error **errp)
{
const char *optstr, *h;
@ -561,6 +588,7 @@ int inet_parse(InetSocketAddress *addr, const char *str, Error **errp)
char port[33];
int to;
int pos;
char *begin;
memset(addr, 0, sizeof(*addr));
@ -602,11 +630,19 @@ int inet_parse(InetSocketAddress *addr, const char *str, Error **errp)
addr->has_to = true;
addr->to = to;
}
if (strstr(optstr, ",ipv4")) {
addr->ipv4 = addr->has_ipv4 = true;
begin = strstr(optstr, ",ipv4");
if (begin) {
if (inet_parse_flag("ipv4", begin + 5, &addr->ipv4, errp) < 0) {
return -1;
}
addr->has_ipv4 = true;
}
if (strstr(optstr, ",ipv6")) {
addr->ipv6 = addr->has_ipv6 = true;
begin = strstr(optstr, ",ipv6");
if (begin) {
if (inet_parse_flag("ipv6", begin + 5, &addr->ipv6, errp) < 0) {
return -1;
}
addr->has_ipv6 = true;
}
return 0;
}

View File

@ -510,9 +510,6 @@ void readline_free(ReadLineState *rs)
for (i = 0; i < READLINE_MAX_CMDS; i++) {
g_free(rs->history[i]);
}
for (i = 0; i < READLINE_MAX_COMPLETIONS; i++) {
g_free(rs->completions[i]);
}
g_free(rs);
}