* Atomic memslot updates for KVM (Emanuele, David)
* libvhost-user/libvduse warnings fixes (Marcel) * i386 TCG fixes (Joe, myself) * Remove compilation errors when -Werror=maybe-uninitialized (Eric) * fix GLIB_VERSION for cross-compilation (Paolo) -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmO+hUYUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroM5+Qf9HIy2QDdGZJ1fA3AUhp7bCJgotlRF 2NMFwo3P/Vwe4qMzzRGkMpsDLFhJx6j1V+sSyeLNxCPtidHccFcmKJOlTqmGeT0k HccK07cgAXSZUtvog2xid7PeNpi8OQjKih2Gn/FnN9Tjtad7yMYfXO3O5ttkRV+7 F8qXBkm4J74l5zs+UMOXUj9y4PudjRFPS0q/lti82eg8mUZ33BZtBkP18Qjq45GM wLcemfId0Z6e4s4fmVeTobZ31ltz/B6HDkoD59pQSK6QW2VBIAoO64Hw6FdZnu5W PltBsDy5cboKHibkb/ySZQUMhb7UemKFyf7eRWkdlnSSHHFdL/K4x7x7DA== =0b+g -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging * Atomic memslot updates for KVM (Emanuele, David) * libvhost-user/libvduse warnings fixes (Marcel) * i386 TCG fixes (Joe, myself) * Remove compilation errors when -Werror=maybe-uninitialized (Eric) * fix GLIB_VERSION for cross-compilation (Paolo) # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmO+hUYUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroM5+Qf9HIy2QDdGZJ1fA3AUhp7bCJgotlRF # 2NMFwo3P/Vwe4qMzzRGkMpsDLFhJx6j1V+sSyeLNxCPtidHccFcmKJOlTqmGeT0k # HccK07cgAXSZUtvog2xid7PeNpi8OQjKih2Gn/FnN9Tjtad7yMYfXO3O5ttkRV+7 # F8qXBkm4J74l5zs+UMOXUj9y4PudjRFPS0q/lti82eg8mUZ33BZtBkP18Qjq45GM # wLcemfId0Z6e4s4fmVeTobZ31ltz/B6HDkoD59pQSK6QW2VBIAoO64Hw6FdZnu5W # PltBsDy5cboKHibkb/ySZQUMhb7UemKFyf7eRWkdlnSSHHFdL/K4x7x7DA== # =0b+g # -----END PGP SIGNATURE----- # gpg: Signature made Wed 11 Jan 2023 09:45:42 GMT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # 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 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (29 commits) configure: remove backwards-compatibility code target/i386: fix operand size of unary SSE operations libvduse: Add extra compiler warnings libvhost-user: Add extra compiler warnings libvhost-user: Fix assignment in vring_set_avail_event libvduse: Fix assignment in vring_set_avail_event libvduse: Switch to unsigned int for inuse field in struct VduseVirtq libvduse: Provide _GNU_SOURCE when compiling outside of QEMU libvhost-user: Change dev->postcopy_ufd assignment to make it C90 compliant libvhost-user: Declare uffdio_register early to make it C90 compliant libvhost-user: Use unsigned int i for some for-loop iterations libvhost-user: Cast rc variable to avoid compiler warning libvhost-user: Replace typeof with __typeof__ libvhost-user: Provide _GNU_SOURCE when compiling outside of QEMU hw/display: avoid creating empty loadable modules enforce use of G_GNUC_PRINTF attributes tests: add G_GNUC_PRINTF for various functions util/error: add G_GNUC_PRINTF for various functions tools/virtiofsd: add G_GNUC_PRINTF for logging functions hw/xen: use G_GNUC_PRINTF/SCANF for various functions ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3db29dcac2
@ -6,8 +6,7 @@
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||
../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
--disable-user --target-list-exclude="arm-softmmu cris-softmmu
|
||||
i386-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu
|
||||
mips64-softmmu ppc-softmmu riscv32-softmmu sh4-softmmu
|
||||
@ -32,8 +31,7 @@
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||
../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
--disable-tools --enable-${ACCEL:-kvm} $EXTRA_CONFIGURE_OPTS
|
||||
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
||||
|
||||
@ -44,8 +42,7 @@
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||
../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
--disable-system --target-list-exclude="aarch64_be-linux-user
|
||||
alpha-linux-user cris-linux-user m68k-linux-user microblazeel-linux-user
|
||||
nios2-linux-user or1k-linux-user ppc-linux-user sparc-linux-user
|
||||
|
154
accel/accel-blocker.c
Normal file
154
accel/accel-blocker.c
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Lock to inhibit accelerator ioctls
|
||||
*
|
||||
* Copyright (c) 2022 Red Hat Inc.
|
||||
*
|
||||
* Author: Emanuele Giuseppe Esposito <eesposit@redhat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hw/core/cpu.h"
|
||||
#include "sysemu/accel-blocker.h"
|
||||
|
||||
static QemuLockCnt accel_in_ioctl_lock;
|
||||
static QemuEvent accel_in_ioctl_event;
|
||||
|
||||
void accel_blocker_init(void)
|
||||
{
|
||||
qemu_lockcnt_init(&accel_in_ioctl_lock);
|
||||
qemu_event_init(&accel_in_ioctl_event, false);
|
||||
}
|
||||
|
||||
void accel_ioctl_begin(void)
|
||||
{
|
||||
if (likely(qemu_mutex_iothread_locked())) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* block if lock is taken in kvm_ioctl_inhibit_begin() */
|
||||
qemu_lockcnt_inc(&accel_in_ioctl_lock);
|
||||
}
|
||||
|
||||
void accel_ioctl_end(void)
|
||||
{
|
||||
if (likely(qemu_mutex_iothread_locked())) {
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_lockcnt_dec(&accel_in_ioctl_lock);
|
||||
/* change event to SET. If event was BUSY, wake up all waiters */
|
||||
qemu_event_set(&accel_in_ioctl_event);
|
||||
}
|
||||
|
||||
void accel_cpu_ioctl_begin(CPUState *cpu)
|
||||
{
|
||||
if (unlikely(qemu_mutex_iothread_locked())) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* block if lock is taken in kvm_ioctl_inhibit_begin() */
|
||||
qemu_lockcnt_inc(&cpu->in_ioctl_lock);
|
||||
}
|
||||
|
||||
void accel_cpu_ioctl_end(CPUState *cpu)
|
||||
{
|
||||
if (unlikely(qemu_mutex_iothread_locked())) {
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_lockcnt_dec(&cpu->in_ioctl_lock);
|
||||
/* change event to SET. If event was BUSY, wake up all waiters */
|
||||
qemu_event_set(&accel_in_ioctl_event);
|
||||
}
|
||||
|
||||
static bool accel_has_to_wait(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
bool needs_to_wait = false;
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
if (qemu_lockcnt_count(&cpu->in_ioctl_lock)) {
|
||||
/* exit the ioctl, if vcpu is running it */
|
||||
qemu_cpu_kick(cpu);
|
||||
needs_to_wait = true;
|
||||
}
|
||||
}
|
||||
|
||||
return needs_to_wait || qemu_lockcnt_count(&accel_in_ioctl_lock);
|
||||
}
|
||||
|
||||
void accel_ioctl_inhibit_begin(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
|
||||
/*
|
||||
* We allow to inhibit only when holding the BQL, so we can identify
|
||||
* when an inhibitor wants to issue an ioctl easily.
|
||||
*/
|
||||
g_assert(qemu_mutex_iothread_locked());
|
||||
|
||||
/* Block further invocations of the ioctls outside the BQL. */
|
||||
CPU_FOREACH(cpu) {
|
||||
qemu_lockcnt_lock(&cpu->in_ioctl_lock);
|
||||
}
|
||||
qemu_lockcnt_lock(&accel_in_ioctl_lock);
|
||||
|
||||
/* Keep waiting until there are running ioctls */
|
||||
while (true) {
|
||||
|
||||
/* Reset event to FREE. */
|
||||
qemu_event_reset(&accel_in_ioctl_event);
|
||||
|
||||
if (accel_has_to_wait()) {
|
||||
/*
|
||||
* If event is still FREE, and there are ioctls still in progress,
|
||||
* wait.
|
||||
*
|
||||
* If an ioctl finishes before qemu_event_wait(), it will change
|
||||
* the event state to SET. This will prevent qemu_event_wait() from
|
||||
* blocking, but it's not a problem because if other ioctls are
|
||||
* still running the loop will iterate once more and reset the event
|
||||
* status to FREE so that it can wait properly.
|
||||
*
|
||||
* If an ioctls finishes while qemu_event_wait() is blocking, then
|
||||
* it will be waken up, but also here the while loop makes sure
|
||||
* to re-enter the wait if there are other running ioctls.
|
||||
*/
|
||||
qemu_event_wait(&accel_in_ioctl_event);
|
||||
} else {
|
||||
/* No ioctl is running */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void accel_ioctl_inhibit_end(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
|
||||
qemu_lockcnt_unlock(&accel_in_ioctl_lock);
|
||||
CPU_FOREACH(cpu) {
|
||||
qemu_lockcnt_unlock(&cpu->in_ioctl_lock);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/accel-blocker.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "exec/memory.h"
|
||||
#include "exec/ram_addr.h"
|
||||
@ -46,6 +47,7 @@
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "kvm-cpus.h"
|
||||
#include "sysemu/dirtylimit.h"
|
||||
#include "qemu/range.h"
|
||||
|
||||
#include "hw/boards.h"
|
||||
#include "monitor/stats.h"
|
||||
@ -1292,6 +1294,7 @@ void kvm_set_max_memslot_size(hwaddr max_slot_size)
|
||||
kvm_max_slot_size = max_slot_size;
|
||||
}
|
||||
|
||||
/* Called with KVMMemoryListener.slots_lock held */
|
||||
static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
MemoryRegionSection *section, bool add)
|
||||
{
|
||||
@ -1326,14 +1329,12 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
ram = memory_region_get_ram_ptr(mr) + mr_offset;
|
||||
ram_start_offset = memory_region_get_ram_addr(mr) + mr_offset;
|
||||
|
||||
kvm_slots_lock();
|
||||
|
||||
if (!add) {
|
||||
do {
|
||||
slot_size = MIN(kvm_max_slot_size, size);
|
||||
mem = kvm_lookup_matching_slot(kml, start_addr, slot_size);
|
||||
if (!mem) {
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
|
||||
/*
|
||||
@ -1371,7 +1372,7 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
start_addr += slot_size;
|
||||
size -= slot_size;
|
||||
} while (size);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
/* register the new slot */
|
||||
@ -1396,9 +1397,6 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
ram += slot_size;
|
||||
size -= slot_size;
|
||||
} while (size);
|
||||
|
||||
out:
|
||||
kvm_slots_unlock();
|
||||
}
|
||||
|
||||
static void *kvm_dirty_ring_reaper_thread(void *data)
|
||||
@ -1455,18 +1453,95 @@ static void kvm_region_add(MemoryListener *listener,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
KVMMemoryListener *kml = container_of(listener, KVMMemoryListener, listener);
|
||||
KVMMemoryUpdate *update;
|
||||
|
||||
memory_region_ref(section->mr);
|
||||
kvm_set_phys_mem(kml, section, true);
|
||||
update = g_new0(KVMMemoryUpdate, 1);
|
||||
update->section = *section;
|
||||
|
||||
QSIMPLEQ_INSERT_TAIL(&kml->transaction_add, update, next);
|
||||
}
|
||||
|
||||
static void kvm_region_del(MemoryListener *listener,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
KVMMemoryListener *kml = container_of(listener, KVMMemoryListener, listener);
|
||||
KVMMemoryUpdate *update;
|
||||
|
||||
kvm_set_phys_mem(kml, section, false);
|
||||
memory_region_unref(section->mr);
|
||||
update = g_new0(KVMMemoryUpdate, 1);
|
||||
update->section = *section;
|
||||
|
||||
QSIMPLEQ_INSERT_TAIL(&kml->transaction_del, update, next);
|
||||
}
|
||||
|
||||
static void kvm_region_commit(MemoryListener *listener)
|
||||
{
|
||||
KVMMemoryListener *kml = container_of(listener, KVMMemoryListener,
|
||||
listener);
|
||||
KVMMemoryUpdate *u1, *u2;
|
||||
bool need_inhibit = false;
|
||||
|
||||
if (QSIMPLEQ_EMPTY(&kml->transaction_add) &&
|
||||
QSIMPLEQ_EMPTY(&kml->transaction_del)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have to be careful when regions to add overlap with ranges to remove.
|
||||
* We have to simulate atomic KVM memslot updates by making sure no ioctl()
|
||||
* is currently active.
|
||||
*
|
||||
* The lists are order by addresses, so it's easy to find overlaps.
|
||||
*/
|
||||
u1 = QSIMPLEQ_FIRST(&kml->transaction_del);
|
||||
u2 = QSIMPLEQ_FIRST(&kml->transaction_add);
|
||||
while (u1 && u2) {
|
||||
Range r1, r2;
|
||||
|
||||
range_init_nofail(&r1, u1->section.offset_within_address_space,
|
||||
int128_get64(u1->section.size));
|
||||
range_init_nofail(&r2, u2->section.offset_within_address_space,
|
||||
int128_get64(u2->section.size));
|
||||
|
||||
if (range_overlaps_range(&r1, &r2)) {
|
||||
need_inhibit = true;
|
||||
break;
|
||||
}
|
||||
if (range_lob(&r1) < range_lob(&r2)) {
|
||||
u1 = QSIMPLEQ_NEXT(u1, next);
|
||||
} else {
|
||||
u2 = QSIMPLEQ_NEXT(u2, next);
|
||||
}
|
||||
}
|
||||
|
||||
kvm_slots_lock();
|
||||
if (need_inhibit) {
|
||||
accel_ioctl_inhibit_begin();
|
||||
}
|
||||
|
||||
/* Remove all memslots before adding the new ones. */
|
||||
while (!QSIMPLEQ_EMPTY(&kml->transaction_del)) {
|
||||
u1 = QSIMPLEQ_FIRST(&kml->transaction_del);
|
||||
QSIMPLEQ_REMOVE_HEAD(&kml->transaction_del, next);
|
||||
|
||||
kvm_set_phys_mem(kml, &u1->section, false);
|
||||
memory_region_unref(u1->section.mr);
|
||||
|
||||
g_free(u1);
|
||||
}
|
||||
while (!QSIMPLEQ_EMPTY(&kml->transaction_add)) {
|
||||
u1 = QSIMPLEQ_FIRST(&kml->transaction_add);
|
||||
QSIMPLEQ_REMOVE_HEAD(&kml->transaction_add, next);
|
||||
|
||||
memory_region_ref(u1->section.mr);
|
||||
kvm_set_phys_mem(kml, &u1->section, true);
|
||||
|
||||
g_free(u1);
|
||||
}
|
||||
|
||||
if (need_inhibit) {
|
||||
accel_ioctl_inhibit_end();
|
||||
}
|
||||
kvm_slots_unlock();
|
||||
}
|
||||
|
||||
static void kvm_log_sync(MemoryListener *listener,
|
||||
@ -1610,8 +1685,12 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
|
||||
kml->slots[i].slot = i;
|
||||
}
|
||||
|
||||
QSIMPLEQ_INIT(&kml->transaction_add);
|
||||
QSIMPLEQ_INIT(&kml->transaction_del);
|
||||
|
||||
kml->listener.region_add = kvm_region_add;
|
||||
kml->listener.region_del = kvm_region_del;
|
||||
kml->listener.commit = kvm_region_commit;
|
||||
kml->listener.log_start = kvm_log_start;
|
||||
kml->listener.log_stop = kvm_log_stop;
|
||||
kml->listener.priority = 10;
|
||||
@ -2310,6 +2389,7 @@ static int kvm_init(MachineState *ms)
|
||||
assert(TARGET_PAGE_SIZE <= qemu_real_host_page_size());
|
||||
|
||||
s->sigmask_len = 8;
|
||||
accel_blocker_init();
|
||||
|
||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||
QTAILQ_INIT(&s->kvm_sw_breakpoints);
|
||||
@ -3014,7 +3094,9 @@ int kvm_vm_ioctl(KVMState *s, int type, ...)
|
||||
va_end(ap);
|
||||
|
||||
trace_kvm_vm_ioctl(type, arg);
|
||||
accel_ioctl_begin();
|
||||
ret = ioctl(s->vmfd, type, arg);
|
||||
accel_ioctl_end();
|
||||
if (ret == -1) {
|
||||
ret = -errno;
|
||||
}
|
||||
@ -3032,7 +3114,9 @@ int kvm_vcpu_ioctl(CPUState *cpu, int type, ...)
|
||||
va_end(ap);
|
||||
|
||||
trace_kvm_vcpu_ioctl(cpu->cpu_index, type, arg);
|
||||
accel_cpu_ioctl_begin(cpu);
|
||||
ret = ioctl(cpu->kvm_fd, type, arg);
|
||||
accel_cpu_ioctl_end(cpu);
|
||||
if (ret == -1) {
|
||||
ret = -errno;
|
||||
}
|
||||
@ -3050,7 +3134,9 @@ int kvm_device_ioctl(int fd, int type, ...)
|
||||
va_end(ap);
|
||||
|
||||
trace_kvm_device_ioctl(fd, type, arg);
|
||||
accel_ioctl_begin();
|
||||
ret = ioctl(fd, type, arg);
|
||||
accel_ioctl_end();
|
||||
if (ret == -1) {
|
||||
ret = -errno;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
specific_ss.add(files('accel-common.c'))
|
||||
specific_ss.add(files('accel-common.c', 'accel-blocker.c'))
|
||||
softmmu_ss.add(files('accel-softmmu.c'))
|
||||
user_ss.add(files('accel-user.c'))
|
||||
|
||||
|
@ -238,7 +238,6 @@ static void qemu_chr_open_pp_fd(Chardev *chr,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHARDEV_PARPORT
|
||||
static void qmp_chardev_open_parallel(Chardev *chr,
|
||||
ChardevBackend *backend,
|
||||
bool *be_opened,
|
||||
@ -276,29 +275,21 @@ static void char_parallel_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
cc->parse = qemu_chr_parse_parallel;
|
||||
cc->open = qmp_chardev_open_parallel;
|
||||
#if defined(__linux__)
|
||||
cc->chr_ioctl = pp_ioctl;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
|
||||
defined(__DragonFly__)
|
||||
cc->chr_ioctl = pp_ioctl;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void char_parallel_finalize(Object *obj)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
Chardev *chr = CHARDEV(obj);
|
||||
ParallelChardev *drv = PARALLEL_CHARDEV(chr);
|
||||
int fd = drv->fd;
|
||||
|
||||
#if defined(__linux__)
|
||||
pp_hw_mode(drv, IEEE1284_MODE_COMPAT);
|
||||
ioctl(fd, PPRELEASE);
|
||||
#endif
|
||||
close(fd);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
|
||||
defined(__DragonFly__)
|
||||
/* FIXME: close fd? */
|
||||
#endif
|
||||
}
|
||||
|
||||
static const TypeInfo char_parallel_type_info = {
|
||||
@ -315,5 +306,3 @@ static void register_types(void)
|
||||
}
|
||||
|
||||
type_init(register_types);
|
||||
|
||||
#endif
|
||||
|
@ -14,9 +14,12 @@ chardev_ss.add(files(
|
||||
))
|
||||
chardev_ss.add(when: 'CONFIG_POSIX', if_true: [files(
|
||||
'char-fd.c',
|
||||
'char-parallel.c',
|
||||
'char-pty.c',
|
||||
), util])
|
||||
if targetos in ['linux', 'gnu/kfreebsd', 'freebsd', 'dragonfly']
|
||||
chardev_ss.add(files('char-parallel.c'))
|
||||
endif
|
||||
|
||||
chardev_ss.add(when: 'CONFIG_WIN32', if_true: files(
|
||||
'char-console.c',
|
||||
'char-win-stdio.c',
|
||||
|
13
configure
vendored
13
configure
vendored
@ -1183,6 +1183,7 @@ add_to warn_flags -Wnested-externs
|
||||
add_to warn_flags -Wendif-labels
|
||||
add_to warn_flags -Wexpansion-to-defined
|
||||
add_to warn_flags -Wimplicit-fallthrough=2
|
||||
add_to warn_flags -Wmissing-format-attribute
|
||||
|
||||
nowarn_flags=
|
||||
add_to nowarn_flags -Wno-initializer-overrides
|
||||
@ -2375,7 +2376,7 @@ echo "QEMU_OBJCFLAGS=$QEMU_OBJCFLAGS" >> $config_host_mak
|
||||
echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
|
||||
echo "GLIB_LIBS=$glib_libs" >> $config_host_mak
|
||||
echo "GLIB_BINDIR=$glib_bindir" >> $config_host_mak
|
||||
echo "GLIB_VERSION=$(pkg-config --modversion glib-2.0)" >> $config_host_mak
|
||||
echo "GLIB_VERSION=$($pkg_config --modversion glib-2.0)" >> $config_host_mak
|
||||
echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak
|
||||
echo "EXESUF=$EXESUF" >> $config_host_mak
|
||||
|
||||
@ -2567,16 +2568,6 @@ if test "$skip_meson" = no; then
|
||||
if test "$?" -ne 0 ; then
|
||||
error_exit "meson setup failed"
|
||||
fi
|
||||
else
|
||||
if test -f meson-private/cmd_line.txt; then
|
||||
# Adjust old command line options whose type was changed
|
||||
# Avoids having to use "setup --wipe" when Meson is upgraded
|
||||
perl -i -ne '
|
||||
s/^gettext = true$/gettext = auto/;
|
||||
s/^gettext = false$/gettext = disabled/;
|
||||
/^b_staticpic/ && next;
|
||||
print;' meson-private/cmd_line.txt
|
||||
fi
|
||||
fi
|
||||
|
||||
# Save the configure command line for later reuse.
|
||||
|
3
disas.c
3
disas.c
@ -239,7 +239,8 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code,
|
||||
}
|
||||
}
|
||||
|
||||
static int gstring_printf(FILE *stream, const char *fmt, ...)
|
||||
static int G_GNUC_PRINTF(2, 3)
|
||||
gstring_printf(FILE *stream, const char *fmt, ...)
|
||||
{
|
||||
/* We abuse the FILE parameter to pass a GString. */
|
||||
GString *s = (GString *)stream;
|
||||
|
@ -238,6 +238,7 @@ static void cpu_common_initfn(Object *obj)
|
||||
cpu->cflags_next_tb = -1;
|
||||
|
||||
qemu_mutex_init(&cpu->work_mutex);
|
||||
qemu_lockcnt_init(&cpu->in_ioctl_lock);
|
||||
QSIMPLEQ_INIT(&cpu->work_list);
|
||||
QTAILQ_INIT(&cpu->breakpoints);
|
||||
QTAILQ_INIT(&cpu->watchpoints);
|
||||
@ -249,6 +250,7 @@ static void cpu_common_finalize(Object *obj)
|
||||
{
|
||||
CPUState *cpu = CPU(obj);
|
||||
|
||||
qemu_lockcnt_destroy(&cpu->in_ioctl_lock);
|
||||
qemu_mutex_destroy(&cpu->work_mutex);
|
||||
}
|
||||
|
||||
|
@ -73,10 +73,12 @@ if config_all_devices.has_key('CONFIG_VIRTIO_GPU')
|
||||
virtio_gpu_ss.add(when: 'CONFIG_VHOST_USER_GPU', if_true: files('vhost-user-gpu.c'))
|
||||
hw_display_modules += {'virtio-gpu': virtio_gpu_ss}
|
||||
|
||||
virtio_gpu_gl_ss = ss.source_set()
|
||||
virtio_gpu_gl_ss.add(when: ['CONFIG_VIRTIO_GPU', virgl, opengl],
|
||||
if_true: [files('virtio-gpu-gl.c', 'virtio-gpu-virgl.c'), pixman, virgl])
|
||||
hw_display_modules += {'virtio-gpu-gl': virtio_gpu_gl_ss}
|
||||
if virgl.found() and opengl.found()
|
||||
virtio_gpu_gl_ss = ss.source_set()
|
||||
virtio_gpu_gl_ss.add(when: ['CONFIG_VIRTIO_GPU', virgl, opengl],
|
||||
if_true: [files('virtio-gpu-gl.c', 'virtio-gpu-virgl.c'), pixman, virgl])
|
||||
hw_display_modules += {'virtio-gpu-gl': virtio_gpu_gl_ss}
|
||||
endif
|
||||
endif
|
||||
|
||||
if config_all_devices.has_key('CONFIG_VIRTIO_PCI')
|
||||
@ -87,10 +89,12 @@ if config_all_devices.has_key('CONFIG_VIRTIO_PCI')
|
||||
if_true: files('vhost-user-gpu-pci.c'))
|
||||
hw_display_modules += {'virtio-gpu-pci': virtio_gpu_pci_ss}
|
||||
|
||||
virtio_gpu_pci_gl_ss = ss.source_set()
|
||||
virtio_gpu_pci_gl_ss.add(when: ['CONFIG_VIRTIO_GPU', 'CONFIG_VIRTIO_PCI', virgl, opengl],
|
||||
if_true: [files('virtio-gpu-pci-gl.c'), pixman])
|
||||
hw_display_modules += {'virtio-gpu-pci-gl': virtio_gpu_pci_gl_ss}
|
||||
if virgl.found() and opengl.found()
|
||||
virtio_gpu_pci_gl_ss = ss.source_set()
|
||||
virtio_gpu_pci_gl_ss.add(when: ['CONFIG_VIRTIO_GPU', 'CONFIG_VIRTIO_PCI', virgl, opengl],
|
||||
if_true: [files('virtio-gpu-pci-gl.c'), pixman])
|
||||
hw_display_modules += {'virtio-gpu-pci-gl': virtio_gpu_pci_gl_ss}
|
||||
endif
|
||||
endif
|
||||
|
||||
if config_all_devices.has_key('CONFIG_VIRTIO_VGA')
|
||||
|
@ -561,6 +561,7 @@ void xen_device_backend_printf(XenDevice *xendev, const char *key,
|
||||
}
|
||||
}
|
||||
|
||||
G_GNUC_SCANF(3, 4)
|
||||
static int xen_device_backend_scanf(XenDevice *xendev, const char *key,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
|
@ -196,6 +196,7 @@ const char *xenbus_strstate(enum xenbus_state state)
|
||||
* 2 == noisy debug messages (logfile only).
|
||||
* 3 == will flood your log (logfile only).
|
||||
*/
|
||||
G_GNUC_PRINTF(3, 0)
|
||||
static void xen_pv_output_msg(struct XenLegacyDevice *xendev,
|
||||
FILE *f, const char *fmt, va_list args)
|
||||
{
|
||||
|
@ -398,6 +398,9 @@ struct CPUState {
|
||||
uint32_t kvm_fetch_index;
|
||||
uint64_t dirty_pages;
|
||||
|
||||
/* Use by accel-block: CPU is executing an ioctl() */
|
||||
QemuLockCnt in_ioctl_lock;
|
||||
|
||||
/* Used for events with 'vcpu' and *without* the 'disabled' properties */
|
||||
DECLARE_BITMAP(trace_dstate_delayed, CPU_TRACE_DSTATE_MAX_EVENTS);
|
||||
DECLARE_BITMAP(trace_dstate, CPU_TRACE_DSTATE_MAX_EVENTS);
|
||||
|
@ -31,10 +31,12 @@ void xs_node_printf(struct xs_handle *xsh, xs_transaction_t tid,
|
||||
/* Read from node/key unless node is empty, in which case read from key */
|
||||
int xs_node_vscanf(struct xs_handle *xsh, xs_transaction_t tid,
|
||||
const char *node, const char *key, Error **errp,
|
||||
const char *fmt, va_list ap);
|
||||
const char *fmt, va_list ap)
|
||||
G_GNUC_SCANF(6, 0);
|
||||
int xs_node_scanf(struct xs_handle *xsh, xs_transaction_t tid,
|
||||
const char *node, const char *key, Error **errp,
|
||||
const char *fmt, ...);
|
||||
const char *fmt, ...)
|
||||
G_GNUC_SCANF(6, 7);
|
||||
|
||||
/* Watch node/key unless node is empty, in which case watch key */
|
||||
void xs_node_watch(struct xs_handle *xsh, const char *node, const char *key,
|
||||
|
@ -94,7 +94,8 @@ void xen_device_frontend_printf(XenDevice *xendev, const char *key,
|
||||
G_GNUC_PRINTF(3, 4);
|
||||
|
||||
int xen_device_frontend_scanf(XenDevice *xendev, const char *key,
|
||||
const char *fmt, ...);
|
||||
const char *fmt, ...)
|
||||
G_GNUC_SCANF(3, 4);
|
||||
|
||||
void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs,
|
||||
Error **errp);
|
||||
|
@ -427,11 +427,6 @@ void qemu_anon_ram_free(void *ptr, size_t size);
|
||||
#define HAVE_CHARDEV_SERIAL 1
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
#define HAVE_CHARDEV_PARPORT 1
|
||||
#endif
|
||||
|
||||
#if defined(__HAIKU__)
|
||||
#define SIGIO SIGPOLL
|
||||
#endif
|
||||
|
56
include/sysemu/accel-blocker.h
Normal file
56
include/sysemu/accel-blocker.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Accelerator blocking API, to prevent new ioctls from starting and wait the
|
||||
* running ones finish.
|
||||
* This mechanism differs from pause/resume_all_vcpus() in that it does not
|
||||
* release the BQL.
|
||||
*
|
||||
* Copyright (c) 2022 Red Hat Inc.
|
||||
*
|
||||
* Author: Emanuele Giuseppe Esposito <eesposit@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.
|
||||
*/
|
||||
#ifndef ACCEL_BLOCKER_H
|
||||
#define ACCEL_BLOCKER_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
extern void accel_blocker_init(void);
|
||||
|
||||
/*
|
||||
* accel_{cpu_}ioctl_begin/end:
|
||||
* Mark when ioctl is about to run or just finished.
|
||||
*
|
||||
* accel_{cpu_}ioctl_begin will block after accel_ioctl_inhibit_begin() is
|
||||
* called, preventing new ioctls to run. They will continue only after
|
||||
* accel_ioctl_inibith_end().
|
||||
*/
|
||||
extern void accel_ioctl_begin(void);
|
||||
extern void accel_ioctl_end(void);
|
||||
extern void accel_cpu_ioctl_begin(CPUState *cpu);
|
||||
extern void accel_cpu_ioctl_end(CPUState *cpu);
|
||||
|
||||
/*
|
||||
* accel_ioctl_inhibit_begin: start critical section
|
||||
*
|
||||
* This function makes sure that:
|
||||
* 1) incoming accel_{cpu_}ioctl_begin() calls block
|
||||
* 2) wait that all ioctls that were already running reach
|
||||
* accel_{cpu_}ioctl_end(), kicking vcpus if necessary.
|
||||
*
|
||||
* This allows the caller to access shared data or perform operations without
|
||||
* worrying of concurrent vcpus accesses.
|
||||
*/
|
||||
extern void accel_ioctl_inhibit_begin(void);
|
||||
|
||||
/*
|
||||
* accel_ioctl_inhibit_end: end critical section started by
|
||||
* accel_ioctl_inhibit_begin()
|
||||
*
|
||||
* This function allows blocked accel_{cpu_}ioctl_begin() to continue.
|
||||
*/
|
||||
extern void accel_ioctl_inhibit_end(void);
|
||||
|
||||
#endif /* ACCEL_BLOCKER_H */
|
@ -12,6 +12,7 @@
|
||||
#include "exec/memory.h"
|
||||
#include "qapi/qapi-types-common.h"
|
||||
#include "qemu/accel.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
typedef struct KVMSlot
|
||||
@ -31,10 +32,17 @@ typedef struct KVMSlot
|
||||
ram_addr_t ram_start_offset;
|
||||
} KVMSlot;
|
||||
|
||||
typedef struct KVMMemoryUpdate {
|
||||
QSIMPLEQ_ENTRY(KVMMemoryUpdate) next;
|
||||
MemoryRegionSection section;
|
||||
} KVMMemoryUpdate;
|
||||
|
||||
typedef struct KVMMemoryListener {
|
||||
MemoryListener listener;
|
||||
KVMSlot *slots;
|
||||
int as_id;
|
||||
QSIMPLEQ_HEAD(, KVMMemoryUpdate) transaction_add;
|
||||
QSIMPLEQ_HEAD(, KVMMemoryUpdate) transaction_del;
|
||||
} KVMMemoryListener;
|
||||
|
||||
#define KVM_MSI_HASHTAB_SIZE 256
|
||||
|
@ -16,6 +16,10 @@
|
||||
* later. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
@ -97,7 +101,7 @@ struct VduseVirtq {
|
||||
uint16_t signalled_used;
|
||||
bool signalled_used_valid;
|
||||
int index;
|
||||
int inuse;
|
||||
unsigned int inuse;
|
||||
bool ready;
|
||||
int fd;
|
||||
VduseDev *dev;
|
||||
@ -578,7 +582,8 @@ void vduse_queue_notify(VduseVirtq *vq)
|
||||
|
||||
static inline void vring_set_avail_event(VduseVirtq *vq, uint16_t val)
|
||||
{
|
||||
*((uint16_t *)&vq->vring.used->ring[vq->vring.num]) = htole16(val);
|
||||
uint16_t val_le = htole16(val);
|
||||
memcpy(&vq->vring.used->ring[vq->vring.num], &val_le, sizeof(uint16_t));
|
||||
}
|
||||
|
||||
static bool vduse_queue_map_single_desc(VduseVirtq *vq, unsigned int *p_num_sg,
|
||||
|
@ -1,6 +1,12 @@
|
||||
project('libvduse', 'c',
|
||||
license: 'GPL-2.0-or-later',
|
||||
default_options: ['c_std=gnu99'])
|
||||
default_options: ['warning_level=1', 'c_std=gnu99'])
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
add_project_arguments(cc.get_supported_arguments('-Wsign-compare',
|
||||
'-Wdeclaration-after-statement',
|
||||
'-Wstrict-aliasing'),
|
||||
native: false, language: 'c')
|
||||
|
||||
libvduse = static_library('vduse',
|
||||
files('libvduse.c'),
|
||||
|
@ -13,6 +13,10 @@
|
||||
* later. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
/* this code avoids GLib dependency */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -58,8 +62,8 @@
|
||||
#endif /* !__GNUC__ */
|
||||
#ifndef MIN
|
||||
#define MIN(x, y) ({ \
|
||||
typeof(x) _min1 = (x); \
|
||||
typeof(y) _min2 = (y); \
|
||||
__typeof__(x) _min1 = (x); \
|
||||
__typeof__(y) _min2 = (y); \
|
||||
(void) (&_min1 == &_min2); \
|
||||
_min1 < _min2 ? _min1 : _min2; })
|
||||
#endif
|
||||
@ -188,7 +192,7 @@ vu_panic(VuDev *dev, const char *msg, ...)
|
||||
void *
|
||||
vu_gpa_to_va(VuDev *dev, uint64_t *plen, uint64_t guest_addr)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
if (*plen == 0) {
|
||||
return NULL;
|
||||
@ -214,7 +218,7 @@ vu_gpa_to_va(VuDev *dev, uint64_t *plen, uint64_t guest_addr)
|
||||
static void *
|
||||
qva_to_va(VuDev *dev, uint64_t qemu_addr)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
/* Find matching memory region. */
|
||||
for (i = 0; i < dev->nregions; i++) {
|
||||
@ -335,7 +339,7 @@ vu_message_read_default(VuDev *dev, int conn_fd, VhostUserMsg *vmsg)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
assert(rc == vmsg->size);
|
||||
assert((uint32_t)rc == vmsg->size);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -617,11 +621,13 @@ map_ring(VuDev *dev, VuVirtq *vq)
|
||||
|
||||
static bool
|
||||
generate_faults(VuDev *dev) {
|
||||
int i;
|
||||
unsigned int i;
|
||||
for (i = 0; i < dev->nregions; i++) {
|
||||
VuDevRegion *dev_region = &dev->regions[i];
|
||||
int ret;
|
||||
#ifdef UFFDIO_REGISTER
|
||||
struct uffdio_register reg_struct;
|
||||
|
||||
/*
|
||||
* We should already have an open ufd. Mark each memory
|
||||
* range as ufd.
|
||||
@ -655,7 +661,7 @@ generate_faults(VuDev *dev) {
|
||||
"%s: Failed to madvise(NOHUGEPAGE) region %d: %s\n",
|
||||
__func__, i, strerror(errno));
|
||||
}
|
||||
struct uffdio_register reg_struct;
|
||||
|
||||
reg_struct.range.start = (uintptr_t)dev_region->mmap_addr;
|
||||
reg_struct.range.len = dev_region->size + dev_region->mmap_offset;
|
||||
reg_struct.mode = UFFDIO_REGISTER_MODE_MISSING;
|
||||
@ -825,7 +831,7 @@ static inline bool reg_equal(VuDevRegion *vudev_reg,
|
||||
static bool
|
||||
vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
|
||||
VhostUserMemoryRegion m = vmsg->payload.memreg.region, *msg_region = &m;
|
||||
int i;
|
||||
unsigned int i;
|
||||
bool found = false;
|
||||
|
||||
if (vmsg->fd_num > 1) {
|
||||
@ -891,7 +897,7 @@ vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
|
||||
static bool
|
||||
vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
VhostUserMemory m = vmsg->payload.memory, *memory = &m;
|
||||
dev->nregions = memory->nregions;
|
||||
|
||||
@ -968,7 +974,7 @@ vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg)
|
||||
static bool
|
||||
vu_set_mem_table_exec(VuDev *dev, VhostUserMsg *vmsg)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
VhostUserMemory m = vmsg->payload.memory, *memory = &m;
|
||||
|
||||
for (i = 0; i < dev->nregions; i++) {
|
||||
@ -1593,12 +1599,13 @@ vu_set_config(VuDev *dev, VhostUserMsg *vmsg)
|
||||
static bool
|
||||
vu_set_postcopy_advise(VuDev *dev, VhostUserMsg *vmsg)
|
||||
{
|
||||
dev->postcopy_ufd = -1;
|
||||
#ifdef UFFDIO_API
|
||||
struct uffdio_api api_struct;
|
||||
|
||||
dev->postcopy_ufd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
|
||||
vmsg->size = 0;
|
||||
#else
|
||||
dev->postcopy_ufd = -1;
|
||||
#endif
|
||||
|
||||
if (dev->postcopy_ufd == -1) {
|
||||
@ -1976,7 +1983,7 @@ end:
|
||||
void
|
||||
vu_deinit(VuDev *dev)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < dev->nregions; i++) {
|
||||
VuDevRegion *r = &dev->regions[i];
|
||||
@ -2471,14 +2478,13 @@ vring_used_flags_unset_bit(VuVirtq *vq, int mask)
|
||||
static inline void
|
||||
vring_set_avail_event(VuVirtq *vq, uint16_t val)
|
||||
{
|
||||
uint16_t *avail;
|
||||
uint16_t val_le = htole16(val);
|
||||
|
||||
if (!vq->notification) {
|
||||
return;
|
||||
}
|
||||
|
||||
avail = (uint16_t *)&vq->vring.used->ring[vq->vring.num];
|
||||
*avail = htole16(val);
|
||||
memcpy(&vq->vring.used->ring[vq->vring.num], &val_le, sizeof(uint16_t));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,6 +1,12 @@
|
||||
project('libvhost-user', 'c',
|
||||
license: 'GPL-2.0-or-later',
|
||||
default_options: ['c_std=gnu99'])
|
||||
default_options: ['warning_level=1', 'c_std=gnu99'])
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
add_project_arguments(cc.get_supported_arguments('-Wsign-compare',
|
||||
'-Wdeclaration-after-statement',
|
||||
'-Wstrict-aliasing'),
|
||||
native: false, language: 'c')
|
||||
|
||||
threads = dependency('threads')
|
||||
glib = dependency('glib-2.0')
|
||||
|
@ -2470,6 +2470,8 @@ void helper_vpermdq_ymm(Reg *d, Reg *v, Reg *s, uint32_t order)
|
||||
r0 = s->Q(2);
|
||||
r1 = s->Q(3);
|
||||
break;
|
||||
default: /* default case added to help the compiler to avoid warnings */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
switch ((order >> 4) & 3) {
|
||||
case 0:
|
||||
@ -2488,6 +2490,8 @@ void helper_vpermdq_ymm(Reg *d, Reg *v, Reg *s, uint32_t order)
|
||||
r2 = s->Q(2);
|
||||
r3 = s->Q(3);
|
||||
break;
|
||||
default: /* default case added to help the compiler to avoid warnings */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
d->Q(0) = r0;
|
||||
d->Q(1) = r1;
|
||||
|
@ -105,6 +105,7 @@
|
||||
#define vex3 .vex_class = 3,
|
||||
#define vex4 .vex_class = 4,
|
||||
#define vex4_unal .vex_class = 4, .vex_special = X86_VEX_SSEUnaligned,
|
||||
#define vex4_rep5 .vex_class = 4, .vex_special = X86_VEX_REPScalar,
|
||||
#define vex5 .vex_class = 5,
|
||||
#define vex6 .vex_class = 6,
|
||||
#define vex7 .vex_class = 7,
|
||||
@ -839,8 +840,8 @@ static const X86OpEntry opcodes_0F[256] = {
|
||||
|
||||
[0x50] = X86_OP_ENTRY3(MOVMSK, G,y, None,None, U,x, vex7 p_00_66),
|
||||
[0x51] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
|
||||
[0x52] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex5 p_00_f3),
|
||||
[0x53] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex5 p_00_f3),
|
||||
[0x52] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex4_rep5 p_00_f3),
|
||||
[0x53] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex4_rep5 p_00_f3),
|
||||
[0x54] = X86_OP_ENTRY3(PAND, V,x, H,x, W,x, vex4 p_00_66), /* vand */
|
||||
[0x55] = X86_OP_ENTRY3(PANDN, V,x, H,x, W,x, vex4 p_00_66), /* vandn */
|
||||
[0x56] = X86_OP_ENTRY3(POR, V,x, H,x, W,x, vex4 p_00_66), /* vor */
|
||||
@ -878,7 +879,7 @@ static const X86OpEntry opcodes_0F[256] = {
|
||||
|
||||
[0x58] = X86_OP_ENTRY3(VADD, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
|
||||
[0x59] = X86_OP_ENTRY3(VMUL, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
|
||||
[0x5a] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex3 p_00_66_f3_f2),
|
||||
[0x5a] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
|
||||
[0x5b] = X86_OP_GROUP0(0F5B),
|
||||
[0x5c] = X86_OP_ENTRY3(VSUB, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
|
||||
[0x5d] = X86_OP_ENTRY3(VMIN, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
|
||||
@ -1447,9 +1448,9 @@ static bool validate_vex(DisasContext *s, X86DecodedInsn *decode)
|
||||
* Instructions which differ between 00/66 and F2/F3 in the
|
||||
* exception classification and the size of the memory operand.
|
||||
*/
|
||||
assert(e->vex_class == 1 || e->vex_class == 2);
|
||||
assert(e->vex_class == 1 || e->vex_class == 2 || e->vex_class == 4);
|
||||
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
|
||||
e->vex_class = 3;
|
||||
e->vex_class = e->vex_class < 4 ? 3 : 5;
|
||||
if (s->vex_l) {
|
||||
goto illegal;
|
||||
}
|
||||
|
@ -882,7 +882,7 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
|
||||
|
||||
dt = &env->idt;
|
||||
if (intno * 16 + 15 > dt->limit) {
|
||||
raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);
|
||||
raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
|
||||
}
|
||||
ptr = dt->base + intno * 16;
|
||||
e1 = cpu_ldl_kernel(env, ptr);
|
||||
@ -895,18 +895,18 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
|
||||
case 15: /* 386 trap gate */
|
||||
break;
|
||||
default:
|
||||
raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);
|
||||
raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
|
||||
break;
|
||||
}
|
||||
dpl = (e2 >> DESC_DPL_SHIFT) & 3;
|
||||
cpl = env->hflags & HF_CPL_MASK;
|
||||
/* check privilege if software int */
|
||||
if (is_int && dpl < cpl) {
|
||||
raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);
|
||||
raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
|
||||
}
|
||||
/* check valid bit */
|
||||
if (!(e2 & DESC_P_MASK)) {
|
||||
raise_exception_err(env, EXCP0B_NOSEG, intno * 16 + 2);
|
||||
raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2);
|
||||
}
|
||||
selector = e1 >> 16;
|
||||
offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
|
||||
|
@ -37,6 +37,7 @@ tfcflags = [
|
||||
'-Wno-missing-prototypes',
|
||||
'-Wno-return-type',
|
||||
'-Wno-unused-function',
|
||||
'-Wno-missing-format-attribute',
|
||||
'-Wno-error',
|
||||
]
|
||||
|
||||
|
@ -154,6 +154,7 @@ static void ahci_migrate(AHCIQState *from, AHCIQState *to, const char *uri)
|
||||
/**
|
||||
* Start a Q35 machine and bookmark a handle to the AHCI device.
|
||||
*/
|
||||
G_GNUC_PRINTF(1, 0)
|
||||
static AHCIQState *ahci_vboot(const char *cli, va_list ap)
|
||||
{
|
||||
AHCIQState *s;
|
||||
@ -171,6 +172,7 @@ static AHCIQState *ahci_vboot(const char *cli, va_list ap)
|
||||
/**
|
||||
* Start a Q35 machine and bookmark a handle to the AHCI device.
|
||||
*/
|
||||
G_GNUC_PRINTF(1, 2)
|
||||
static AHCIQState *ahci_boot(const char *cli, ...)
|
||||
{
|
||||
AHCIQState *s;
|
||||
@ -209,6 +211,7 @@ static void ahci_shutdown(AHCIQState *ahci)
|
||||
* Boot and fully enable the HBA device.
|
||||
* @see ahci_boot, ahci_pci_enable and ahci_hba_enable.
|
||||
*/
|
||||
G_GNUC_PRINTF(1, 2)
|
||||
static AHCIQState *ahci_boot_and_enable(const char *cli, ...)
|
||||
{
|
||||
AHCIQState *ahci;
|
||||
|
@ -32,6 +32,7 @@ static QDict *do_query_no_props(QTestState *qts, const char *cpu_type)
|
||||
QUERY_TAIL, cpu_type);
|
||||
}
|
||||
|
||||
G_GNUC_PRINTF(3, 4)
|
||||
static QDict *do_query(QTestState *qts, const char *cpu_type,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
|
@ -98,7 +98,7 @@ static void setup_vm_cmd(ERSTState *s, const char *cmd)
|
||||
const char *arch = qtest_get_arch();
|
||||
|
||||
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||
s->qs = qtest_pc_boot(cmd);
|
||||
s->qs = qtest_pc_boot("%s", cmd);
|
||||
} else {
|
||||
g_printerr("erst-test tests are only available on x86\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -125,6 +125,7 @@ static QGuestAllocator guest_malloc;
|
||||
static char *tmp_path[2];
|
||||
static char *debug_path;
|
||||
|
||||
G_GNUC_PRINTF(1, 2)
|
||||
static QTestState *ide_test_start(const char *cmdline_fmt, ...)
|
||||
{
|
||||
QTestState *qts;
|
||||
@ -788,7 +789,7 @@ static void test_flush_nodev(void)
|
||||
QPCIDevice *dev;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
|
||||
qts = ide_test_start("");
|
||||
qts = ide_test_start("%s", "");
|
||||
|
||||
dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
|
||||
|
||||
|
@ -109,9 +109,9 @@ static void setup_vm_cmd(IVState *s, const char *cmd, bool msix)
|
||||
const char *arch = qtest_get_arch();
|
||||
|
||||
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||
s->qs = qtest_pc_boot(cmd);
|
||||
s->qs = qtest_pc_boot("%s", cmd);
|
||||
} else if (strcmp(arch, "ppc64") == 0) {
|
||||
s->qs = qtest_spapr_boot(cmd);
|
||||
s->qs = qtest_spapr_boot("%s", cmd);
|
||||
} else {
|
||||
g_printerr("ivshmem-test tests are only available on x86 or ppc64\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -134,7 +134,7 @@ static void socket_send_fds(int socket_fd, int *fds, size_t fds_num,
|
||||
* in the case that they choose to discard all replies up until
|
||||
* a particular EVENT is received.
|
||||
*/
|
||||
static void
|
||||
static G_GNUC_PRINTF(4, 0) void
|
||||
_qmp_fd_vsend_fds(int fd, int *fds, size_t fds_num,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
#include "libqos.h"
|
||||
|
||||
QOSState *qtest_pc_vboot(const char *cmdline_fmt, va_list ap);
|
||||
QOSState *qtest_pc_boot(const char *cmdline_fmt, ...);
|
||||
QOSState *qtest_pc_vboot(const char *cmdline_fmt, va_list ap)
|
||||
G_GNUC_PRINTF(1, 0);
|
||||
QOSState *qtest_pc_boot(const char *cmdline_fmt, ...)
|
||||
G_GNUC_PRINTF(1, 2);
|
||||
void qtest_pc_shutdown(QOSState *qs);
|
||||
|
||||
#endif
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
#include "libqos.h"
|
||||
|
||||
QOSState *qtest_spapr_vboot(const char *cmdline_fmt, va_list ap);
|
||||
QOSState *qtest_spapr_boot(const char *cmdline_fmt, ...);
|
||||
QOSState *qtest_spapr_vboot(const char *cmdline_fmt, va_list ap)
|
||||
G_GNUC_PRINTF(1, 0);
|
||||
QOSState *qtest_spapr_boot(const char *cmdline_fmt, ...)
|
||||
G_GNUC_PRINTF(1, 2);
|
||||
void qtest_spapr_shutdown(QOSState *qs);
|
||||
|
||||
/* List of capabilities needed to silence warnings with TCG */
|
||||
|
@ -21,8 +21,10 @@ struct QOSState {
|
||||
QOSOps *ops;
|
||||
};
|
||||
|
||||
QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap);
|
||||
QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...);
|
||||
QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap)
|
||||
G_GNUC_PRINTF(2, 0);
|
||||
QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...)
|
||||
G_GNUC_PRINTF(2, 3);
|
||||
void qtest_common_shutdown(QOSState *qs);
|
||||
void qtest_shutdown(QOSState *qs);
|
||||
bool have_qemu_img(void);
|
||||
|
@ -211,6 +211,7 @@ static void *virtio_9p_pci_create(void *pci_bus, QGuestAllocator *t_alloc,
|
||||
* variable arguments of this function to this
|
||||
* replacement string
|
||||
*/
|
||||
G_GNUC_PRINTF(3, 4)
|
||||
static void regex_replace(GString *haystack, const char *pattern,
|
||||
const char *replace_fmt, ...)
|
||||
{
|
||||
|
@ -25,6 +25,7 @@ QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...);
|
||||
G_GNUC_PRINTF(2, 3)
|
||||
QDict *wait_command(QTestState *who, const char *command, ...);
|
||||
|
||||
G_GNUC_PRINTF(2, 3)
|
||||
QDict *qmp_command(QTestState *who, const char *command, ...);
|
||||
|
||||
G_GNUC_PRINTF(3, 4)
|
||||
|
@ -13,7 +13,7 @@ static void run_test_rtas_get_time_of_day(const char *machine)
|
||||
uint64_t ret;
|
||||
time_t t1, t2;
|
||||
|
||||
qs = qtest_spapr_boot(machine);
|
||||
qs = qtest_spapr_boot("%s", machine);
|
||||
|
||||
t1 = time(NULL);
|
||||
ret = qrtas_get_time_of_day(qs->qts, &qs->alloc, &tm, &ns);
|
||||
|
@ -72,9 +72,9 @@ int main(int argc, char **argv)
|
||||
qtest_add_func("/uhci/pci/hotplug/usb-storage", test_usb_storage_hotplug);
|
||||
|
||||
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||
qs = qtest_pc_boot(cmd);
|
||||
qs = qtest_pc_boot("%s", cmd);
|
||||
} else if (strcmp(arch, "ppc64") == 0) {
|
||||
qs = qtest_spapr_boot(cmd);
|
||||
qs = qtest_spapr_boot("%s", cmd);
|
||||
} else {
|
||||
g_printerr("usb-hcd-uhci-test tests are only "
|
||||
"available on x86 or ppc64\n");
|
||||
|
@ -138,6 +138,7 @@ void qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
|
||||
}
|
||||
|
||||
|
||||
G_GNUC_PRINTF(2, 3)
|
||||
static QObject *do_qmp_dispatch(bool allow_oob, const char *template, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@ -160,6 +161,7 @@ static QObject *do_qmp_dispatch(bool allow_oob, const char *template, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
G_GNUC_PRINTF(3, 4)
|
||||
static void do_qmp_dispatch_error(bool allow_oob, ErrorClass cls,
|
||||
const char *template, ...)
|
||||
{
|
||||
@ -269,7 +271,7 @@ static void test_dispatch_cmd_io(void)
|
||||
|
||||
static void test_dispatch_cmd_deprecated(void)
|
||||
{
|
||||
const char *cmd = "{ 'execute': 'test-command-features1' }";
|
||||
#define cmd "{ 'execute': 'test-command-features1' }"
|
||||
QDict *ret;
|
||||
|
||||
memset(&compat_policy, 0, sizeof(compat_policy));
|
||||
@ -287,12 +289,13 @@ static void test_dispatch_cmd_deprecated(void)
|
||||
|
||||
compat_policy.deprecated_input = COMPAT_POLICY_INPUT_REJECT;
|
||||
do_qmp_dispatch_error(false, ERROR_CLASS_COMMAND_NOT_FOUND, cmd);
|
||||
#undef cmd
|
||||
}
|
||||
|
||||
static void test_dispatch_cmd_arg_deprecated(void)
|
||||
{
|
||||
const char *cmd = "{ 'execute': 'test-features0',"
|
||||
" 'arguments': { 'fs1': { 'foo': 42 } } }";
|
||||
#define cmd "{ 'execute': 'test-features0'," \
|
||||
" 'arguments': { 'fs1': { 'foo': 42 } } }"
|
||||
QDict *ret;
|
||||
|
||||
memset(&compat_policy, 0, sizeof(compat_policy));
|
||||
@ -310,11 +313,12 @@ static void test_dispatch_cmd_arg_deprecated(void)
|
||||
|
||||
compat_policy.deprecated_input = COMPAT_POLICY_INPUT_REJECT;
|
||||
do_qmp_dispatch_error(false, ERROR_CLASS_GENERIC_ERROR, cmd);
|
||||
#undef cmd
|
||||
}
|
||||
|
||||
static void test_dispatch_cmd_ret_deprecated(void)
|
||||
{
|
||||
const char *cmd = "{ 'execute': 'test-features0' }";
|
||||
#define cmd "{ 'execute': 'test-features0' }"
|
||||
QDict *ret;
|
||||
|
||||
memset(&compat_policy, 0, sizeof(compat_policy));
|
||||
@ -334,6 +338,7 @@ static void test_dispatch_cmd_ret_deprecated(void)
|
||||
ret = qobject_to(QDict, do_qmp_dispatch(false, cmd));
|
||||
assert(ret && qdict_size(ret) == 0);
|
||||
qobject_unref(ret);
|
||||
#undef cmd
|
||||
}
|
||||
|
||||
/* test generated dealloc functions for generated types */
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "fuse_log.h"
|
||||
|
||||
|
||||
G_GNUC_PRINTF(2, 0)
|
||||
static void default_log_func(__attribute__((unused)) enum fuse_log_level level,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
|
@ -45,7 +45,8 @@ enum fuse_log_level {
|
||||
* @param ap format string arguments
|
||||
*/
|
||||
typedef void (*fuse_log_func_t)(enum fuse_log_level level, const char *fmt,
|
||||
va_list ap);
|
||||
va_list ap)
|
||||
G_GNUC_PRINTF(2, 0);
|
||||
|
||||
/**
|
||||
* Install a custom log handler function.
|
||||
@ -68,6 +69,7 @@ void fuse_set_log_func(fuse_log_func_t func);
|
||||
* @param level severity level (FUSE_LOG_ERR, FUSE_LOG_DEBUG, etc)
|
||||
* @param fmt sprintf-style format string including newline
|
||||
*/
|
||||
void fuse_log(enum fuse_log_level level, const char *fmt, ...);
|
||||
void fuse_log(enum fuse_log_level level, const char *fmt, ...)
|
||||
G_GNUC_PRINTF(2, 3);
|
||||
|
||||
#endif /* FUSE_LOG_H_ */
|
||||
|
@ -4182,6 +4182,7 @@ static void setup_nofile_rlimit(unsigned long rlimit_nofile)
|
||||
}
|
||||
}
|
||||
|
||||
G_GNUC_PRINTF(2, 0)
|
||||
static void log_func(enum fuse_log_level level, const char *fmt, va_list ap)
|
||||
{
|
||||
g_autofree char *localfmt = NULL;
|
||||
|
@ -193,6 +193,7 @@ real_time_iso8601(void)
|
||||
* a single phrase, with no newline or trailing punctuation.
|
||||
* Prepend the current location and append a newline.
|
||||
*/
|
||||
G_GNUC_PRINTF(2, 0)
|
||||
static void vreport(report_type type, const char *fmt, va_list ap)
|
||||
{
|
||||
gchar *timestr;
|
||||
|
@ -45,6 +45,7 @@ static void error_handle_fatal(Error **errp, Error *err)
|
||||
}
|
||||
}
|
||||
|
||||
G_GNUC_PRINTF(6, 0)
|
||||
static void error_setv(Error **errp,
|
||||
const char *src, int line, const char *func,
|
||||
ErrorClass err_class, const char *fmt, va_list ap,
|
||||
|
@ -58,6 +58,7 @@ util_ss.add(files('yank.c'))
|
||||
util_ss.add(files('int128.c'))
|
||||
util_ss.add(files('memalign.c'))
|
||||
util_ss.add(files('interval-tree.c'))
|
||||
util_ss.add(files('lockcnt.c'))
|
||||
|
||||
if have_user
|
||||
util_ss.add(files('selfmap.c'))
|
||||
@ -72,7 +73,6 @@ endif
|
||||
if have_block or have_ga
|
||||
util_ss.add(files('aiocb.c', 'async.c'))
|
||||
util_ss.add(files('base64.c'))
|
||||
util_ss.add(files('lockcnt.c'))
|
||||
util_ss.add(files('main-loop.c'))
|
||||
util_ss.add(files('qemu-coroutine.c', 'qemu-coroutine-lock.c', 'qemu-coroutine-io.c'))
|
||||
util_ss.add(files('coroutine-@0@.c'.format(config_host['CONFIG_COROUTINE_BACKEND'])))
|
||||
|
Loading…
Reference in New Issue
Block a user