mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 11:23:43 +08:00
* 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
This commit is contained in:
commit
7b213bb475
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
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
48
accel/stubs/whpx-stub.c
Normal 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)
|
||||
{
|
||||
}
|
@ -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,
|
||||
|
@ -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
170
backends/hostmem-memfd.c
Normal 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);
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
111
configure
vendored
111
configure
vendored
@ -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"
|
||||
@ -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
113
cpus.c
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -62,3 +62,4 @@ CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM)
|
||||
CONFIG_PXB=y
|
||||
CONFIG_ACPI_VMGENID=y
|
||||
CONFIG_FW_CFG_DMA=y
|
||||
CONFIG_I2C=y
|
||||
|
@ -34,3 +34,4 @@ CONFIG_ISA_TESTDEV=y
|
||||
CONFIG_EMPTY_SLOT=y
|
||||
CONFIG_MIPS_CPS=y
|
||||
CONFIG_MIPS_ITU=y
|
||||
CONFIG_I2C=y
|
||||
|
@ -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
|
||||
|
@ -17,3 +17,4 @@ CONFIG_XILINX=y
|
||||
CONFIG_XILINX_ETHLITE=y
|
||||
CONFIG_SM501=y
|
||||
CONFIG_IDE_SII3112=y
|
||||
CONFIG_I2C=y
|
||||
|
@ -62,3 +62,4 @@ CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM)
|
||||
CONFIG_PXB=y
|
||||
CONFIG_ACPI_VMGENID=y
|
||||
CONFIG_FW_CFG_DMA=y
|
||||
CONFIG_I2C=y
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
if (!blkconf_apply_backend_options(&s->conf,
|
||||
blk_is_read_only(s->conf.blk),
|
||||
true, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
true, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
|
@ -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"
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
40
include/sysemu/whpx.h
Normal 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 */
|
@ -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
|
||||
|
||||
|
28
memory.c
28
memory.c
@ -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, §ion, fr->dirty_log_mask, 0);
|
||||
}
|
||||
if (listener->region_del) {
|
||||
listener->region_del(listener, §ion);
|
||||
}
|
||||
}
|
||||
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
1
numa.c
@ -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.
|
||||
|
@ -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
|
||||
|
@ -1,4 +1,5 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# GDB debugging support
|
||||
#
|
||||
# Copyright 2017 Linaro Ltd
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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
1366
target/i386/whpx-all.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
@ -43,13 +42,12 @@
|
||||
|
||||
#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 "
|
||||
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,11 +985,19 @@ 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)
|
||||
#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);
|
||||
@ -966,6 +1007,7 @@ int main(int argc, char **argv)
|
||||
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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
78
util/memfd.c
78
util/memfd.c
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
if (strstr(optstr, ",ipv6")) {
|
||||
addr->ipv6 = addr->has_ipv6 = true;
|
||||
addr->has_ipv4 = 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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user