* Fuzzing improvements (Qiuhao, Alexander)
* i386: Fix BMI decoding for instructions with the 0x66 prefix (David) * initial attempt at fixing event_notifier emulation (Maxim) * i386: PKS emulation, fix for "qemu-system-i386 -cpu host" (myself) * meson: RBD test fixes (myself) * meson: TCI warnings (Philippe) * Leaner build for --disable-guest-agent, --disable-system and --disable-tools (Philippe, Stefan) * --enable-tcg-interpreter fix (Richard) * i386: SVM feature bits (Wei) * KVM bugfix (Thomas H.) * Add missing MemoryRegionOps callbacks (PJP) -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmAhR4cUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroOviAf/Ymk/KwHZKySVqHOjDZnvP5PXMAru p1zlMRLAorXK+CTbshkIliaQyD8ggzT4HCinJ2NisdfTWMmlWbgr8gahNqKyZ5UG HlL28va3dvGhelswh/CNso1ZhVb2Q+aAYn/c6LXQva2r0xi26ohJTkIkSCPP/bnI +73dGzwAilBOsBVbn4cCm/70XtwDpPkw41IZIDoy/4lhL8ZdpHMz8oOjNIlOdlcU aEDfM8vYE4C70OtUlRZ1OwVxzcjS1Bf6dQYcpg5gAKy/jAAqR+v2PStxXiUuj5D3 cAzd03Goh78Wcre+CbWxDKGcGtiooUT+J09wmvDPYVUHcpQMbumf4MufrQ== =INB5 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging * Fuzzing improvements (Qiuhao, Alexander) * i386: Fix BMI decoding for instructions with the 0x66 prefix (David) * initial attempt at fixing event_notifier emulation (Maxim) * i386: PKS emulation, fix for "qemu-system-i386 -cpu host" (myself) * meson: RBD test fixes (myself) * meson: TCI warnings (Philippe) * Leaner build for --disable-guest-agent, --disable-system and --disable-tools (Philippe, Stefan) * --enable-tcg-interpreter fix (Richard) * i386: SVM feature bits (Wei) * KVM bugfix (Thomas H.) * Add missing MemoryRegionOps callbacks (PJP) # gpg: Signature made Mon 08 Feb 2021 14:15:35 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 * remotes/bonzini-gitlab/tags/for-upstream: (46 commits) target/i386: Expose VMX entry/exit load pkrs control bits target/i386: Add support for save/load IA32_PKRS MSR imx7-ccm: add digprog mmio write method tz-ppc: add dummy read/write methods spapr_pci: add spapr msi read method nvram: add nrf51_soc flash read method prep: add ppc-parity write method vfio: add quirk device write method pci-host: designware: add pcie-msi read method hw/pci-host: add pci-intack write method cpu-throttle: Remove timer_mod() from cpu_throttle_set() replay: rng-builtin support pc-bios/descriptors: fix paths in json files replay: fix replay of the interrupts accel/kvm/kvm-all: Fix wrong return code handling in dirty log code qapi/meson: Restrict UI module to system emulation and tools qapi/meson: Restrict system-mode specific modules qapi/meson: Remove QMP from user-mode emulation qapi/meson: Restrict qdev code to system-mode emulation meson: Restrict emulation code ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
41d306ec7d
@ -2541,6 +2541,7 @@ F: qapi/qom.json
|
||||
F: qapi/qdev.json
|
||||
F: scripts/coccinelle/qom-parent-type.cocci
|
||||
F: softmmu/qdev-monitor.c
|
||||
F: stubs/qdev.c
|
||||
F: qom/
|
||||
F: tests/check-qom-interface.c
|
||||
F: tests/check-qom-proplist.c
|
||||
|
@ -644,16 +644,19 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
|
||||
|
||||
d.dirty_bitmap = mem->dirty_bmap;
|
||||
d.slot = mem->slot | (kml->as_id << 16);
|
||||
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
|
||||
DPRINTF("ioctl failed %d\n", errno);
|
||||
ret = -1;
|
||||
ret = kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d);
|
||||
if (ret == -ENOENT) {
|
||||
/* kernel does not have dirty bitmap in this slot */
|
||||
ret = 0;
|
||||
} else if (ret < 0) {
|
||||
error_report("ioctl KVM_GET_DIRTY_LOG failed: %d", errno);
|
||||
goto out;
|
||||
} else {
|
||||
subsection.offset_within_region += slot_offset;
|
||||
subsection.size = int128_make64(slot_size);
|
||||
kvm_get_dirty_pages_log_range(&subsection, d.dirty_bitmap);
|
||||
}
|
||||
|
||||
subsection.offset_within_region += slot_offset;
|
||||
subsection.size = int128_make64(slot_size);
|
||||
kvm_get_dirty_pages_log_range(&subsection, d.dirty_bitmap);
|
||||
|
||||
slot_offset += slot_size;
|
||||
start_addr += slot_size;
|
||||
size -= slot_size;
|
||||
@ -750,8 +753,8 @@ static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start,
|
||||
d.num_pages = bmap_npages;
|
||||
d.slot = mem->slot | (as_id << 16);
|
||||
|
||||
if (kvm_vm_ioctl(s, KVM_CLEAR_DIRTY_LOG, &d) == -1) {
|
||||
ret = -errno;
|
||||
ret = kvm_vm_ioctl(s, KVM_CLEAR_DIRTY_LOG, &d);
|
||||
if (ret < 0 && ret != -ENOENT) {
|
||||
error_report("%s: KVM_CLEAR_DIRTY_LOG failed, slot=%d, "
|
||||
"start=0x%"PRIx64", size=0x%"PRIx32", errno=%d",
|
||||
__func__, d.slot, (uint64_t)d.first_page,
|
||||
|
@ -81,7 +81,13 @@ void icount_handle_deadline(void)
|
||||
int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
|
||||
QEMU_TIMER_ATTR_ALL);
|
||||
|
||||
if (deadline == 0) {
|
||||
/*
|
||||
* Instructions, interrupts, and exceptions are processed in cpu-exec.
|
||||
* Don't interrupt cpu thread, when these events are waiting
|
||||
* (i.e., there is no checkpoint)
|
||||
*/
|
||||
if (deadline == 0
|
||||
&& (replay_mode != REPLAY_MODE_PLAY || replay_has_checkpoint())) {
|
||||
icount_notify_aio_contexts();
|
||||
}
|
||||
}
|
||||
|
@ -494,6 +494,16 @@ host_memory_backend_class_init(ObjectClass *oc, void *data)
|
||||
host_memory_backend_get_share, host_memory_backend_set_share);
|
||||
object_class_property_set_description(oc, "share",
|
||||
"Mark the memory as private to QEMU or shared");
|
||||
/*
|
||||
* Do not delete/rename option. This option must be considered stable
|
||||
* (as if it didn't have the 'x-' prefix including deprecation period) as
|
||||
* long as 4.0 and older machine types exists.
|
||||
* Option will be used by upper layers to override (disable) canonical path
|
||||
* for ramblock-id set by compat properties on old machine types ( <= 4.0),
|
||||
* to keep migration working when backend is used for main RAM with
|
||||
* -machine memory-backend= option (main RAM historically used prefix-less
|
||||
* ramblock-id).
|
||||
*/
|
||||
object_class_property_add_bool(oc, "x-use-canonical-path-for-ramblock-id",
|
||||
host_memory_backend_get_use_canonical_path,
|
||||
host_memory_backend_set_use_canonical_path);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "qom/object.h"
|
||||
#include "sysemu/replay.h"
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(RngBuiltin, RNG_BUILTIN)
|
||||
|
||||
@ -37,7 +38,7 @@ static void rng_builtin_request_entropy(RngBackend *b, RngRequest *req)
|
||||
{
|
||||
RngBuiltin *s = RNG_BUILTIN(b);
|
||||
|
||||
qemu_bh_schedule(s->bh);
|
||||
replay_bh_schedule_event(s->bh);
|
||||
}
|
||||
|
||||
static void rng_builtin_init(Object *obj)
|
||||
|
2
configure
vendored
2
configure
vendored
@ -1764,7 +1764,7 @@ Advanced options (experts only):
|
||||
--with-trace-file=NAME Full PATH,NAME of file to store traces
|
||||
Default:trace-<pid>
|
||||
--disable-slirp disable SLIRP userspace network connectivity
|
||||
--enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)
|
||||
--enable-tcg-interpreter enable TCI (TCG with bytecode interpreter, experimental and slow)
|
||||
--enable-malloc-trim enable libc malloc_trim() for memory optimization
|
||||
--oss-lib path to OSS library
|
||||
--cpu=CPU Build for host CPU [$cpu]
|
||||
|
@ -100,7 +100,7 @@ In meson.build::
|
||||
# Detect dependency
|
||||
sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
|
||||
method: 'pkg-config',
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
|
||||
# Create config-host.h (if applicable)
|
||||
config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
|
||||
|
@ -119,7 +119,7 @@ Adding a new fuzzer
|
||||
|
||||
Coverage over virtual devices can be improved by adding additional fuzzers.
|
||||
Fuzzers are kept in ``tests/qtest/fuzz/`` and should be added to
|
||||
``tests/qtest/fuzz/Makefile.include``
|
||||
``tests/qtest/fuzz/meson.build``
|
||||
|
||||
Fuzzers can rely on both qtest and libqos to communicate with virtual devices.
|
||||
|
||||
@ -128,8 +128,7 @@ Fuzzers can rely on both qtest and libqos to communicate with virtual devices.
|
||||
2. Write the fuzzing code using the libqtest/libqos API. See existing fuzzers
|
||||
for reference.
|
||||
|
||||
3. Register the fuzzer in ``tests/fuzz/Makefile.include`` by appending the
|
||||
corresponding object to fuzz-obj-y
|
||||
3. Add the fuzzer to ``tests/qtest/fuzz/meson.build``.
|
||||
|
||||
Fuzzers can be more-or-less thought of as special qtest programs which can
|
||||
modify the qtest commands and/or qtest command arguments based on inputs
|
||||
@ -181,6 +180,36 @@ To ensure that these env variables have been configured correctly, we can use::
|
||||
|
||||
The output should contain a complete list of matched MemoryRegions.
|
||||
|
||||
OSS-Fuzz
|
||||
--------
|
||||
QEMU is continuously fuzzed on `OSS-Fuzz` __(https://github.com/google/oss-fuzz).
|
||||
By default, the OSS-Fuzz build will try to fuzz every fuzz-target. Since the
|
||||
generic-fuzz target requires additional information provided in environment
|
||||
variables, we pre-define some generic-fuzz configs in
|
||||
``tests/qtest/fuzz/generic_fuzz_configs.h``. Each config must specify:
|
||||
|
||||
- ``.name``: To identify the fuzzer config
|
||||
|
||||
- ``.args`` OR ``.argfunc``: A string or pointer to a function returning a
|
||||
string. These strings are used to specify the ``QEMU_FUZZ_ARGS``
|
||||
environment variable. ``argfunc`` is useful when the config relies on e.g.
|
||||
a dynamically created temp directory, or a free tcp/udp port.
|
||||
|
||||
- ``.objects``: A string that specifies the ``QEMU_FUZZ_OBJECTS`` environment
|
||||
variable.
|
||||
|
||||
To fuzz additional devices/device configuration on OSS-Fuzz, send patches for
|
||||
either a new device-specific fuzzer or a new generic-fuzz config.
|
||||
|
||||
Build details:
|
||||
|
||||
- The Dockerfile that sets up the environment for building QEMU's
|
||||
fuzzers on OSS-Fuzz can be fund in the OSS-Fuzz repository
|
||||
__(https://github.com/google/oss-fuzz/blob/master/projects/qemu/Dockerfile)
|
||||
|
||||
- The script responsible for building the fuzzers can be found in the
|
||||
QEMU source tree at ``scripts/oss-fuzz/build.sh``
|
||||
|
||||
Implementation Details / Fuzzer Lifecycle
|
||||
-----------------------------------------
|
||||
|
||||
|
@ -46,9 +46,11 @@ if build_docs
|
||||
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
|
||||
qapi_gen_depends ]
|
||||
|
||||
have_ga = have_tools and config_host.has_key('CONFIG_GUEST_AGENT')
|
||||
|
||||
man_pages = {
|
||||
'qemu-ga.8': (have_tools ? 'man8' : ''),
|
||||
'qemu-ga-ref.7': 'man7',
|
||||
'qemu-ga.8': (have_ga ? 'man8' : ''),
|
||||
'qemu-ga-ref.7': (have_ga ? 'man7' : ''),
|
||||
'qemu-qmp-ref.7': 'man7',
|
||||
'qemu-storage-daemon-qmp-ref.7': (have_tools ? 'man7' : ''),
|
||||
'qemu-img.1': (have_tools ? 'man1' : ''),
|
||||
|
@ -131,8 +131,16 @@ static const struct MemoryRegionOps imx7_set_clr_tog_ops = {
|
||||
},
|
||||
};
|
||||
|
||||
static void imx7_digprog_write(void *opaque, hwaddr addr,
|
||||
uint64_t data, unsigned size)
|
||||
{
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"Guest write to read-only ANALOG_DIGPROG register\n");
|
||||
}
|
||||
|
||||
static const struct MemoryRegionOps imx7_digprog_ops = {
|
||||
.read = imx7_set_clr_tog_read,
|
||||
.write = imx7_digprog_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.impl = {
|
||||
.min_access_size = 4,
|
||||
|
@ -196,7 +196,21 @@ static bool tz_ppc_dummy_accepts(void *opaque, hwaddr addr,
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static uint64_t tz_ppc_dummy_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static void tz_ppc_dummy_write(void *opaque, hwaddr addr,
|
||||
uint64_t data, unsigned size)
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static const MemoryRegionOps tz_ppc_dummy_ops = {
|
||||
/* define r/w methods to avoid assert failure in memory_region_init_io */
|
||||
.read = tz_ppc_dummy_read,
|
||||
.write = tz_ppc_dummy_write,
|
||||
.valid.accepts = tz_ppc_dummy_accepts,
|
||||
};
|
||||
|
||||
|
@ -273,6 +273,15 @@ static const MemoryRegionOps io_ops = {
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static uint64_t flash_read(void *opaque, hwaddr offset, unsigned size)
|
||||
{
|
||||
/*
|
||||
* This is a rom_device MemoryRegion which is always in
|
||||
* romd_mode (we never put it in MMIO mode), so reads always
|
||||
* go directly to RAM and never come here.
|
||||
*/
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static void flash_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
unsigned int size)
|
||||
@ -300,6 +309,7 @@ static void flash_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
|
||||
|
||||
static const MemoryRegionOps flash_ops = {
|
||||
.read = flash_read,
|
||||
.write = flash_write,
|
||||
.valid.min_access_size = 4,
|
||||
.valid.max_access_size = 4,
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/pci/pci_bridge.h"
|
||||
#include "hw/pci/pci_host.h"
|
||||
@ -63,6 +64,23 @@ designware_pcie_root_to_host(DesignwarePCIERoot *root)
|
||||
return DESIGNWARE_PCIE_HOST(bus->parent);
|
||||
}
|
||||
|
||||
static uint64_t designware_pcie_root_msi_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
/*
|
||||
* Attempts to read from the MSI address are undefined in
|
||||
* the PCI specifications. For this hardware, the datasheet
|
||||
* specifies that a read from the magic address is simply not
|
||||
* intercepted by the MSI controller, and will go out to the
|
||||
* AHB/AXI bus like any other PCI-device-initiated DMA read.
|
||||
* This is not trivial to implement in QEMU, so since
|
||||
* well-behaved guests won't ever ask a PCI device to DMA from
|
||||
* this address we just log the missing functionality.
|
||||
*/
|
||||
qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void designware_pcie_root_msi_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned len)
|
||||
{
|
||||
@ -77,6 +95,7 @@ static void designware_pcie_root_msi_write(void *opaque, hwaddr addr,
|
||||
}
|
||||
|
||||
static const MemoryRegionOps designware_pci_host_msi_ops = {
|
||||
.read = designware_pcie_root_msi_read,
|
||||
.write = designware_pcie_root_msi_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = {
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/datadir.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/pci_bus.h"
|
||||
@ -121,8 +122,15 @@ static uint64_t raven_intack_read(void *opaque, hwaddr addr,
|
||||
return pic_read_irq(isa_pic);
|
||||
}
|
||||
|
||||
static void raven_intack_write(void *opaque, hwaddr addr,
|
||||
uint64_t data, unsigned size)
|
||||
{
|
||||
qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps raven_intack_ops = {
|
||||
.read = raven_intack_read,
|
||||
.write = raven_intack_write,
|
||||
.valid = {
|
||||
.max_access_size = 1,
|
||||
},
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
@ -235,8 +236,15 @@ static uint64_t ppc_parity_error_readl(void *opaque, hwaddr addr,
|
||||
return val;
|
||||
}
|
||||
|
||||
static void ppc_parity_error_writel(void *opaque, hwaddr addr,
|
||||
uint64_t data, unsigned size)
|
||||
{
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid access\n", __func__);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps ppc_parity_error_ops = {
|
||||
.read = ppc_parity_error_readl,
|
||||
.write = ppc_parity_error_writel,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "sysemu/hostmem.h"
|
||||
#include "sysemu/numa.h"
|
||||
#include "hw/ppc/spapr_numa.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
/* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */
|
||||
#define RTAS_QUERY_FN 0
|
||||
@ -739,6 +740,12 @@ static PCIINTxRoute spapr_route_intx_pin_to_irq(void *opaque, int pin)
|
||||
return route;
|
||||
}
|
||||
|
||||
static uint64_t spapr_msi_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid access\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* MSI/MSIX memory region implementation.
|
||||
* The handler handles both MSI and MSIX.
|
||||
@ -756,8 +763,11 @@ static void spapr_msi_write(void *opaque, hwaddr addr,
|
||||
}
|
||||
|
||||
static const MemoryRegionOps spapr_msi_ops = {
|
||||
/* There is no .read as the read result is undefined by PCI spec */
|
||||
.read = NULL,
|
||||
/*
|
||||
* .read result is undefined by PCI spec.
|
||||
* define .read method to avoid assert failure in memory_region_init_io
|
||||
*/
|
||||
.read = spapr_msi_read,
|
||||
.write = spapr_msi_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN
|
||||
};
|
||||
|
@ -126,6 +126,7 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev)
|
||||
{
|
||||
int i;
|
||||
int rc;
|
||||
int vq_init_count = 0;
|
||||
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
|
||||
@ -153,17 +154,22 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev)
|
||||
if (rc) {
|
||||
goto fail_vrings;
|
||||
}
|
||||
|
||||
vq_init_count++;
|
||||
rc = virtio_scsi_vring_init(s, vs->event_vq, 1,
|
||||
virtio_scsi_data_plane_handle_event);
|
||||
if (rc) {
|
||||
goto fail_vrings;
|
||||
}
|
||||
|
||||
vq_init_count++;
|
||||
for (i = 0; i < vs->conf.num_queues; i++) {
|
||||
rc = virtio_scsi_vring_init(s, vs->cmd_vqs[i], i + 2,
|
||||
virtio_scsi_data_plane_handle_cmd);
|
||||
if (rc) {
|
||||
goto fail_vrings;
|
||||
}
|
||||
vq_init_count++;
|
||||
}
|
||||
|
||||
s->dataplane_starting = false;
|
||||
@ -174,7 +180,7 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev)
|
||||
fail_vrings:
|
||||
aio_wait_bh_oneshot(s->ctx, virtio_scsi_dataplane_stop_bh, s);
|
||||
aio_context_release(s->ctx);
|
||||
for (i = 0; i < vs->conf.num_queues + 2; i++) {
|
||||
for (i = 0; i < vq_init_count; i++) {
|
||||
virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
|
||||
virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include CONFIG_DEVICES
|
||||
#include "exec/memop.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
@ -264,8 +265,15 @@ static uint64_t vfio_ati_3c3_quirk_read(void *opaque,
|
||||
return data;
|
||||
}
|
||||
|
||||
static void vfio_ati_3c3_quirk_write(void *opaque, hwaddr addr,
|
||||
uint64_t data, unsigned size)
|
||||
{
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid access\n", __func__);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps vfio_ati_3c3_quirk = {
|
||||
.read = vfio_ati_3c3_quirk_read,
|
||||
.write = vfio_ati_3c3_quirk_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
|
@ -45,13 +45,11 @@ DECLARE_OBJ_CHECKERS(IOMMUMemoryRegion, IOMMUMemoryRegionClass,
|
||||
#ifdef CONFIG_FUZZ
|
||||
void fuzz_dma_read_cb(size_t addr,
|
||||
size_t len,
|
||||
MemoryRegion *mr,
|
||||
bool is_write);
|
||||
MemoryRegion *mr);
|
||||
#else
|
||||
static inline void fuzz_dma_read_cb(size_t addr,
|
||||
size_t len,
|
||||
MemoryRegion *mr,
|
||||
bool is_write)
|
||||
MemoryRegion *mr)
|
||||
{
|
||||
/* Do Nothing */
|
||||
}
|
||||
@ -2514,7 +2512,7 @@ address_space_read_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
void *buf, hwaddr len)
|
||||
{
|
||||
assert(addr < cache->len && len <= cache->len - addr);
|
||||
fuzz_dma_read_cb(cache->xlat + addr, len, cache->mrs.mr, false);
|
||||
fuzz_dma_read_cb(cache->xlat + addr, len, cache->mrs.mr);
|
||||
if (likely(cache->ptr)) {
|
||||
memcpy(buf, cache->ptr + addr, len);
|
||||
return MEMTX_OK;
|
||||
|
@ -28,7 +28,7 @@ static inline uint32_t ADDRESS_SPACE_LD_CACHED(l)(MemoryRegionCache *cache,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
assert(addr < cache->len && 4 <= cache->len - addr);
|
||||
fuzz_dma_read_cb(cache->xlat + addr, 4, cache->mrs.mr, false);
|
||||
fuzz_dma_read_cb(cache->xlat + addr, 4, cache->mrs.mr);
|
||||
if (likely(cache->ptr)) {
|
||||
return LD_P(l)(cache->ptr + addr);
|
||||
} else {
|
||||
@ -40,7 +40,7 @@ static inline uint64_t ADDRESS_SPACE_LD_CACHED(q)(MemoryRegionCache *cache,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
assert(addr < cache->len && 8 <= cache->len - addr);
|
||||
fuzz_dma_read_cb(cache->xlat + addr, 8, cache->mrs.mr, false);
|
||||
fuzz_dma_read_cb(cache->xlat + addr, 8, cache->mrs.mr);
|
||||
if (likely(cache->ptr)) {
|
||||
return LD_P(q)(cache->ptr + addr);
|
||||
} else {
|
||||
@ -52,7 +52,7 @@ static inline uint32_t ADDRESS_SPACE_LD_CACHED(uw)(MemoryRegionCache *cache,
|
||||
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
|
||||
{
|
||||
assert(addr < cache->len && 2 <= cache->len - addr);
|
||||
fuzz_dma_read_cb(cache->xlat + addr, 2, cache->mrs.mr, false);
|
||||
fuzz_dma_read_cb(cache->xlat + addr, 2, cache->mrs.mr);
|
||||
if (likely(cache->ptr)) {
|
||||
return LD_P(uw)(cache->ptr + addr);
|
||||
} else {
|
||||
|
@ -24,6 +24,7 @@ struct EventNotifier {
|
||||
#else
|
||||
int rfd;
|
||||
int wfd;
|
||||
bool initialized;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -42,7 +42,7 @@ static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL,
|
||||
MO_32 | devend_memop(endian), attrs);
|
||||
} else {
|
||||
/* RAM case */
|
||||
fuzz_dma_read_cb(addr, 4, mr, false);
|
||||
fuzz_dma_read_cb(addr, 4, mr);
|
||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
||||
switch (endian) {
|
||||
case DEVICE_LITTLE_ENDIAN:
|
||||
@ -111,7 +111,7 @@ static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL,
|
||||
MO_64 | devend_memop(endian), attrs);
|
||||
} else {
|
||||
/* RAM case */
|
||||
fuzz_dma_read_cb(addr, 8, mr, false);
|
||||
fuzz_dma_read_cb(addr, 8, mr);
|
||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
||||
switch (endian) {
|
||||
case DEVICE_LITTLE_ENDIAN:
|
||||
@ -177,7 +177,7 @@ uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
|
||||
r = memory_region_dispatch_read(mr, addr1, &val, MO_8, attrs);
|
||||
} else {
|
||||
/* RAM case */
|
||||
fuzz_dma_read_cb(addr, 1, mr, false);
|
||||
fuzz_dma_read_cb(addr, 1, mr);
|
||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
||||
val = ldub_p(ptr);
|
||||
r = MEMTX_OK;
|
||||
@ -215,7 +215,7 @@ static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL,
|
||||
MO_16 | devend_memop(endian), attrs);
|
||||
} else {
|
||||
/* RAM case */
|
||||
fuzz_dma_read_cb(addr, 2, mr, false);
|
||||
fuzz_dma_read_cb(addr, 2, mr);
|
||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
||||
switch (endian) {
|
||||
case DEVICE_LITTLE_ENDIAN:
|
||||
|
208
meson.build
208
meson.build
@ -18,6 +18,9 @@ config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
|
||||
enable_modules = 'CONFIG_MODULES' in config_host
|
||||
enable_static = 'CONFIG_STATIC' in config_host
|
||||
|
||||
# Allow both shared and static libraries unless --enable-static
|
||||
static_kwargs = enable_static ? {'static': true} : {}
|
||||
|
||||
# Temporary directory used for files created while
|
||||
# configure runs. Since it is in the build directory
|
||||
# we can safely blow away any previous version of it
|
||||
@ -224,10 +227,17 @@ tcg_arch = config_host['ARCH']
|
||||
if not get_option('tcg').disabled()
|
||||
if cpu not in supported_cpus
|
||||
if get_option('tcg_interpreter')
|
||||
warning('Unsupported CPU @0@, will use TCG with TCI (experimental)'.format(cpu))
|
||||
warning('Unsupported CPU @0@, will use TCG with TCI (experimental and slow)'.format(cpu))
|
||||
else
|
||||
error('Unsupported CPU @0@, try --enable-tcg-interpreter'.format(cpu))
|
||||
endif
|
||||
elif get_option('tcg_interpreter')
|
||||
warning('Use of the TCG interpretor is not recommended on this host')
|
||||
warning('architecture. There is a native TCG execution backend available')
|
||||
warning('which provides substantially better performance and reliability.')
|
||||
warning('It is strongly recommended to remove the --enable-tcg-interpreter')
|
||||
warning('configuration option on this architecture to use the native')
|
||||
warning('backend.')
|
||||
endif
|
||||
if get_option('tcg_interpreter')
|
||||
tcg_arch = 'tci'
|
||||
@ -311,14 +321,14 @@ endif
|
||||
pixman = not_found
|
||||
if have_system or have_tools
|
||||
pixman = dependency('pixman-1', required: have_system, version:'>=0.21.8',
|
||||
method: 'pkg-config', static: enable_static)
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
endif
|
||||
pam = not_found
|
||||
if 'CONFIG_AUTH_PAM' in config_host
|
||||
pam = cc.find_library('pam')
|
||||
endif
|
||||
libaio = cc.find_library('aio', required: false)
|
||||
zlib = dependency('zlib', required: true, static: enable_static)
|
||||
zlib = dependency('zlib', required: true, kwargs: static_kwargs)
|
||||
linux_io_uring = not_found
|
||||
if 'CONFIG_LINUX_IO_URING' in config_host
|
||||
linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(),
|
||||
@ -333,7 +343,7 @@ libnfs = not_found
|
||||
if not get_option('libnfs').auto() or have_block
|
||||
libnfs = dependency('libnfs', version: '>=1.9.3',
|
||||
required: get_option('libnfs'),
|
||||
method: 'pkg-config', static: enable_static)
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
endif
|
||||
|
||||
libattr_test = '''
|
||||
@ -354,7 +364,7 @@ if not get_option('attr').disabled()
|
||||
else
|
||||
libattr = cc.find_library('attr', has_headers: ['attr/xattr.h'],
|
||||
required: get_option('attr'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
if libattr.found() and not \
|
||||
cc.links(libattr_test, dependencies: libattr, args: '-DCONFIG_LIBATTR')
|
||||
libattr = not_found
|
||||
@ -381,14 +391,14 @@ seccomp = not_found
|
||||
if not get_option('seccomp').auto() or have_system or have_tools
|
||||
seccomp = dependency('libseccomp', version: '>=2.3.0',
|
||||
required: get_option('seccomp'),
|
||||
method: 'pkg-config', static: enable_static)
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
endif
|
||||
|
||||
libcap_ng = not_found
|
||||
if not get_option('cap_ng').auto() or have_system or have_tools
|
||||
libcap_ng = cc.find_library('cap-ng', has_headers: ['cap-ng.h'],
|
||||
required: get_option('cap_ng'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
endif
|
||||
if libcap_ng.found() and not cc.links('''
|
||||
#include <cap-ng.h>
|
||||
@ -409,7 +419,7 @@ if get_option('xkbcommon').auto() and not have_system and not have_tools
|
||||
xkbcommon = not_found
|
||||
else
|
||||
xkbcommon = dependency('xkbcommon', required: get_option('xkbcommon'),
|
||||
method: 'pkg-config', static: enable_static)
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
endif
|
||||
vde = not_found
|
||||
if config_host.has_key('CONFIG_VDE')
|
||||
@ -445,13 +455,13 @@ libiscsi = not_found
|
||||
if not get_option('libiscsi').auto() or have_block
|
||||
libiscsi = dependency('libiscsi', version: '>=1.9.0',
|
||||
required: get_option('libiscsi'),
|
||||
method: 'pkg-config', static: enable_static)
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
endif
|
||||
zstd = not_found
|
||||
if not get_option('zstd').auto() or have_block
|
||||
zstd = dependency('libzstd', version: '>=1.4.0',
|
||||
required: get_option('zstd'),
|
||||
method: 'pkg-config', static: enable_static)
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
endif
|
||||
gbm = not_found
|
||||
if 'CONFIG_GBM' in config_host
|
||||
@ -468,14 +478,14 @@ if not get_option('curl').auto() or have_block
|
||||
curl = dependency('libcurl', version: '>=7.29.0',
|
||||
method: 'pkg-config',
|
||||
required: get_option('curl'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
endif
|
||||
libudev = not_found
|
||||
if targetos == 'linux' and (have_system or have_tools)
|
||||
libudev = dependency('libudev',
|
||||
method: 'pkg-config',
|
||||
required: get_option('libudev'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
endif
|
||||
|
||||
mpathlibs = [libudev]
|
||||
@ -511,17 +521,17 @@ if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
|
||||
}'''
|
||||
libmpathpersist = cc.find_library('mpathpersist',
|
||||
required: get_option('mpath'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
if libmpathpersist.found()
|
||||
mpathlibs += libmpathpersist
|
||||
if enable_static
|
||||
mpathlibs += cc.find_library('devmapper',
|
||||
required: get_option('mpath'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
endif
|
||||
mpathlibs += cc.find_library('multipath',
|
||||
required: get_option('mpath'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
foreach lib: mpathlibs
|
||||
if not lib.found()
|
||||
mpathlibs = []
|
||||
@ -571,7 +581,7 @@ if have_system and not get_option('curses').disabled()
|
||||
curses = dependency(curses_dep,
|
||||
required: false,
|
||||
method: 'pkg-config',
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
endif
|
||||
endforeach
|
||||
msg = get_option('curses').enabled() ? 'curses library not found' : ''
|
||||
@ -596,7 +606,7 @@ if have_system and not get_option('curses').disabled()
|
||||
foreach curses_libname : curses_libname_list
|
||||
libcurses = cc.find_library(curses_libname,
|
||||
required: false,
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
if libcurses.found()
|
||||
if cc.links(curses_test, args: curses_compile_args, dependencies: libcurses)
|
||||
curses = declare_dependency(compile_args: curses_compile_args,
|
||||
@ -647,7 +657,7 @@ brlapi = not_found
|
||||
if not get_option('brlapi').auto() or have_system
|
||||
brlapi = cc.find_library('brlapi', has_headers: ['brlapi.h'],
|
||||
required: get_option('brlapi'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
if brlapi.found() and not cc.links('''
|
||||
#include <brlapi.h>
|
||||
#include <stddef.h>
|
||||
@ -663,7 +673,7 @@ endif
|
||||
|
||||
sdl = not_found
|
||||
if not get_option('sdl').auto() or (have_system and not cocoa.found())
|
||||
sdl = dependency('sdl2', required: get_option('sdl'), static: enable_static)
|
||||
sdl = dependency('sdl2', required: get_option('sdl'), kwargs: static_kwargs)
|
||||
sdl_image = not_found
|
||||
endif
|
||||
if sdl.found()
|
||||
@ -671,7 +681,7 @@ if sdl.found()
|
||||
sdl = declare_dependency(compile_args: '-Wno-undef',
|
||||
dependencies: sdl)
|
||||
sdl_image = dependency('SDL2_image', required: get_option('sdl_image'),
|
||||
method: 'pkg-config', static: enable_static)
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
else
|
||||
if get_option('sdl_image').enabled()
|
||||
error('sdl-image required, but SDL was @0@'.format(
|
||||
@ -683,19 +693,25 @@ endif
|
||||
rbd = not_found
|
||||
if not get_option('rbd').auto() or have_block
|
||||
librados = cc.find_library('rados', required: get_option('rbd'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
librbd = cc.find_library('rbd', has_headers: ['rbd/librbd.h'],
|
||||
required: get_option('rbd'),
|
||||
static: enable_static)
|
||||
if librados.found() and librbd.found() and cc.links('''
|
||||
#include <stdio.h>
|
||||
#include <rbd/librbd.h>
|
||||
int main(void) {
|
||||
rados_t cluster;
|
||||
rados_create(&cluster, NULL);
|
||||
return 0;
|
||||
}''', dependencies: [librbd, librados])
|
||||
rbd = declare_dependency(dependencies: [librbd, librados])
|
||||
kwargs: static_kwargs)
|
||||
if librados.found() and librbd.found()
|
||||
if cc.links('''
|
||||
#include <stdio.h>
|
||||
#include <rbd/librbd.h>
|
||||
int main(void) {
|
||||
rados_t cluster;
|
||||
rados_create(&cluster, NULL);
|
||||
return 0;
|
||||
}''', dependencies: [librbd, librados])
|
||||
rbd = declare_dependency(dependencies: [librbd, librados])
|
||||
elif get_option('rbd').enabled()
|
||||
error('could not link librados')
|
||||
else
|
||||
warning('could not link librados, disabling')
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -705,7 +721,7 @@ glusterfs_iocb_has_stat = false
|
||||
if not get_option('glusterfs').auto() or have_block
|
||||
glusterfs = dependency('glusterfs-api', version: '>=3',
|
||||
required: get_option('glusterfs'),
|
||||
method: 'pkg-config', static: enable_static)
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
if glusterfs.found()
|
||||
glusterfs_ftruncate_has_stat = cc.links('''
|
||||
#include <glusterfs/api/glfs.h>
|
||||
@ -744,7 +760,7 @@ libbzip2 = not_found
|
||||
if not get_option('bzip2').auto() or have_block
|
||||
libbzip2 = cc.find_library('bz2', has_headers: ['bzlib.h'],
|
||||
required: get_option('bzip2'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
if libbzip2.found() and not cc.links('''
|
||||
#include <bzlib.h>
|
||||
int main(void) { BZ2_bzlibVersion(); return 0; }''', dependencies: libbzip2)
|
||||
@ -761,7 +777,7 @@ liblzfse = not_found
|
||||
if not get_option('lzfse').auto() or have_block
|
||||
liblzfse = cc.find_library('lzfse', has_headers: ['lzfse.h'],
|
||||
required: get_option('lzfse'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
endif
|
||||
if liblzfse.found() and not cc.links('''
|
||||
#include <lzfse.h>
|
||||
@ -798,12 +814,12 @@ if not get_option('gtk').auto() or (have_system and not cocoa.found())
|
||||
gtk = dependency('gtk+-3.0', version: '>=3.22.0',
|
||||
method: 'pkg-config',
|
||||
required: get_option('gtk'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
if gtk.found()
|
||||
gtkx11 = dependency('gtk+-x11-3.0', version: '>=3.22.0',
|
||||
method: 'pkg-config',
|
||||
required: false,
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
gtk = declare_dependency(dependencies: [gtk, gtkx11])
|
||||
endif
|
||||
endif
|
||||
@ -816,7 +832,7 @@ endif
|
||||
x11 = not_found
|
||||
if gtkx11.found() or 'lm32-softmmu' in target_dirs
|
||||
x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
endif
|
||||
vnc = not_found
|
||||
png = not_found
|
||||
@ -825,12 +841,12 @@ sasl = not_found
|
||||
if get_option('vnc').enabled()
|
||||
vnc = declare_dependency() # dummy dependency
|
||||
png = dependency('libpng', required: get_option('vnc_png'),
|
||||
method: 'pkg-config', static: enable_static)
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
|
||||
method: 'pkg-config', static: enable_static)
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
|
||||
required: get_option('vnc_sasl'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
if sasl.found()
|
||||
sasl = declare_dependency(dependencies: sasl,
|
||||
compile_args: '-DSTRUCT_IOVEC_DEFINED')
|
||||
@ -841,7 +857,7 @@ snappy = not_found
|
||||
if not get_option('snappy').auto() or have_system
|
||||
snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'],
|
||||
required: get_option('snappy'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
endif
|
||||
if snappy.found() and not cc.links('''
|
||||
#include <snappy-c.h>
|
||||
@ -858,7 +874,7 @@ lzo = not_found
|
||||
if not get_option('lzo').auto() or have_system
|
||||
lzo = cc.find_library('lzo2', has_headers: ['lzo/lzo1x.h'],
|
||||
required: get_option('lzo'),
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
endif
|
||||
if lzo.found() and not cc.links('''
|
||||
#include <lzo/lzo1x.h>
|
||||
@ -893,7 +909,7 @@ u2f = not_found
|
||||
if have_system
|
||||
u2f = dependency('u2f-emu', required: get_option('u2f'),
|
||||
method: 'pkg-config',
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
endif
|
||||
usbredir = not_found
|
||||
if 'CONFIG_USB_REDIR' in config_host
|
||||
@ -920,7 +936,7 @@ if 'CONFIG_TASN1' in config_host
|
||||
link_args: config_host['TASN1_LIBS'].split())
|
||||
endif
|
||||
keyutils = dependency('libkeyutils', required: false,
|
||||
method: 'pkg-config', static: enable_static)
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
|
||||
has_gettid = cc.has_function('gettid')
|
||||
|
||||
@ -979,7 +995,7 @@ endif
|
||||
|
||||
fuse = dependency('fuse3', required: get_option('fuse'),
|
||||
version: '>=3.1', method: 'pkg-config',
|
||||
static: enable_static)
|
||||
kwargs: static_kwargs)
|
||||
|
||||
fuse_lseek = not_found
|
||||
if not get_option('fuse_lseek').disabled()
|
||||
@ -1367,7 +1383,7 @@ capstone_opt = get_option('capstone')
|
||||
if capstone_opt in ['enabled', 'auto', 'system']
|
||||
have_internal = fs.exists(meson.current_source_dir() / 'capstone/Makefile')
|
||||
capstone = dependency('capstone', version: '>=4.0',
|
||||
static: enable_static, method: 'pkg-config',
|
||||
kwargs: static_kwargs, method: 'pkg-config',
|
||||
required: capstone_opt == 'system' or
|
||||
capstone_opt == 'enabled' and not have_internal)
|
||||
if capstone.found()
|
||||
@ -1477,7 +1493,7 @@ if have_system
|
||||
slirp_opt = get_option('slirp')
|
||||
if slirp_opt in ['enabled', 'auto', 'system']
|
||||
have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build')
|
||||
slirp = dependency('slirp', static: enable_static,
|
||||
slirp = dependency('slirp', kwargs: static_kwargs,
|
||||
method: 'pkg-config',
|
||||
required: slirp_opt == 'system' or
|
||||
slirp_opt == 'enabled' and not have_internal)
|
||||
@ -1556,7 +1572,7 @@ fdt_opt = get_option('fdt')
|
||||
if have_system
|
||||
if fdt_opt in ['enabled', 'auto', 'system']
|
||||
have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
|
||||
fdt = cc.find_library('fdt', static: enable_static,
|
||||
fdt = cc.find_library('fdt', kwargs: static_kwargs,
|
||||
required: fdt_opt == 'system' or
|
||||
fdt_opt == 'enabled' and not have_internal)
|
||||
if fdt.found() and cc.links('''
|
||||
@ -1725,10 +1741,11 @@ target_softmmu_arch = {}
|
||||
# TODO: add each directory to the subdirs from its own meson.build, once
|
||||
# we have those
|
||||
trace_events_subdirs = [
|
||||
'accel/kvm',
|
||||
'accel/tcg',
|
||||
'crypto',
|
||||
'qapi',
|
||||
'qom',
|
||||
'monitor',
|
||||
'util',
|
||||
]
|
||||
if have_user
|
||||
trace_events_subdirs += [ 'linux-user' ]
|
||||
@ -1744,6 +1761,7 @@ if have_block
|
||||
endif
|
||||
if have_system
|
||||
trace_events_subdirs += [
|
||||
'accel/kvm',
|
||||
'audio',
|
||||
'backends',
|
||||
'backends/tpm',
|
||||
@ -1801,21 +1819,21 @@ if have_system
|
||||
'ui',
|
||||
]
|
||||
endif
|
||||
trace_events_subdirs += [
|
||||
'hw/core',
|
||||
'qapi',
|
||||
'qom',
|
||||
'target/arm',
|
||||
'target/hppa',
|
||||
'target/i386',
|
||||
'target/i386/kvm',
|
||||
'target/mips',
|
||||
'target/ppc',
|
||||
'target/riscv',
|
||||
'target/s390x',
|
||||
'target/sparc',
|
||||
'util',
|
||||
]
|
||||
if have_system or have_user
|
||||
trace_events_subdirs += [
|
||||
'accel/tcg',
|
||||
'hw/core',
|
||||
'target/arm',
|
||||
'target/hppa',
|
||||
'target/i386',
|
||||
'target/i386/kvm',
|
||||
'target/mips',
|
||||
'target/ppc',
|
||||
'target/riscv',
|
||||
'target/s390x',
|
||||
'target/sparc',
|
||||
]
|
||||
endif
|
||||
|
||||
vhost_user = not_found
|
||||
if 'CONFIG_VHOST_USER' in config_host
|
||||
@ -1849,41 +1867,45 @@ libqemuutil = static_library('qemuutil',
|
||||
qemuutil = declare_dependency(link_with: libqemuutil,
|
||||
sources: genh + version_res)
|
||||
|
||||
decodetree = generator(find_program('scripts/decodetree.py'),
|
||||
output: 'decode-@BASENAME@.c.inc',
|
||||
arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
|
||||
if have_system or have_user
|
||||
decodetree = generator(find_program('scripts/decodetree.py'),
|
||||
output: 'decode-@BASENAME@.c.inc',
|
||||
arguments: ['@INPUT@', '@EXTRA_ARGS@', '-o', '@OUTPUT@'])
|
||||
subdir('libdecnumber')
|
||||
subdir('target')
|
||||
endif
|
||||
|
||||
subdir('audio')
|
||||
subdir('io')
|
||||
subdir('chardev')
|
||||
subdir('fsdev')
|
||||
subdir('libdecnumber')
|
||||
subdir('target')
|
||||
subdir('dump')
|
||||
|
||||
block_ss.add(files(
|
||||
'block.c',
|
||||
'blockjob.c',
|
||||
'job.c',
|
||||
'qemu-io-cmds.c',
|
||||
))
|
||||
block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
|
||||
if have_block
|
||||
block_ss.add(files(
|
||||
'block.c',
|
||||
'blockjob.c',
|
||||
'job.c',
|
||||
'qemu-io-cmds.c',
|
||||
))
|
||||
block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
|
||||
|
||||
subdir('nbd')
|
||||
subdir('scsi')
|
||||
subdir('block')
|
||||
subdir('nbd')
|
||||
subdir('scsi')
|
||||
subdir('block')
|
||||
|
||||
blockdev_ss.add(files(
|
||||
'blockdev.c',
|
||||
'blockdev-nbd.c',
|
||||
'iothread.c',
|
||||
'job-qmp.c',
|
||||
), gnutls)
|
||||
blockdev_ss.add(files(
|
||||
'blockdev.c',
|
||||
'blockdev-nbd.c',
|
||||
'iothread.c',
|
||||
'job-qmp.c',
|
||||
), gnutls)
|
||||
|
||||
# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
|
||||
# os-win32.c does not
|
||||
blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
|
||||
# os-posix.c contains POSIX-specific functions used by qemu-storage-daemon,
|
||||
# os-win32.c does not
|
||||
blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')])
|
||||
endif
|
||||
|
||||
common_ss.add(files('cpus-common.c'))
|
||||
|
||||
@ -2500,8 +2522,12 @@ if have_system
|
||||
endif
|
||||
summary_info += {'TCG support': config_all.has_key('CONFIG_TCG')}
|
||||
if config_all.has_key('CONFIG_TCG')
|
||||
if get_option('tcg_interpreter')
|
||||
summary_info += {'TCG backend': 'TCI (TCG with bytecode interpreter, experimental and slow)'}
|
||||
else
|
||||
summary_info += {'TCG backend': 'native (@0@)'.format(cpu)}
|
||||
endif
|
||||
summary_info += {'TCG debug enabled': config_host.has_key('CONFIG_DEBUG_TCG')}
|
||||
summary_info += {'TCG interpreter': tcg_arch == 'tci'}
|
||||
endif
|
||||
summary_info += {'target list': ' '.join(target_dirs)}
|
||||
if have_system
|
||||
|
@ -40,7 +40,7 @@ option('xen_pci_passthrough', type: 'feature', value: 'auto',
|
||||
option('tcg', type: 'feature', value: 'auto',
|
||||
description: 'TCG support')
|
||||
option('tcg_interpreter', type: 'boolean', value: false,
|
||||
description: 'TCG bytecode interpreter (TCI)')
|
||||
description: 'TCG with bytecode interpreter (experimental and slow)')
|
||||
option('cfi', type: 'boolean', value: 'false',
|
||||
description: 'Control-Flow Integrity (CFI)')
|
||||
option('cfi_debug', type: 'boolean', value: 'false',
|
||||
|
@ -9,7 +9,7 @@ if install_edk2_blobs
|
||||
]
|
||||
configure_file(input: files(f),
|
||||
output: f,
|
||||
configuration: {'DATADIR': qemu_datadir},
|
||||
configuration: {'DATADIR': get_option('prefix') / qemu_datadir},
|
||||
install: get_option('install_blobs'),
|
||||
install_dir: qemu_datadir / 'firmware')
|
||||
endforeach
|
||||
|
@ -12,6 +12,7 @@ if install_edk2_blobs
|
||||
|
||||
foreach f : fds
|
||||
custom_target(f,
|
||||
build_by_default: have_system,
|
||||
output: f,
|
||||
input: '@0@.bz2'.format(f),
|
||||
capture: true,
|
||||
|
@ -4,18 +4,20 @@ util_ss.add(files(
|
||||
'qapi-dealloc-visitor.c',
|
||||
'qapi-util.c',
|
||||
'qapi-visit-core.c',
|
||||
'qmp-dispatch.c',
|
||||
'qmp-event.c',
|
||||
'qmp-registry.c',
|
||||
'qobject-input-visitor.c',
|
||||
'qobject-output-visitor.c',
|
||||
'string-input-visitor.c',
|
||||
'string-output-visitor.c',
|
||||
))
|
||||
if have_system or have_tools
|
||||
util_ss.add(files(
|
||||
'qmp-dispatch.c',
|
||||
'qmp-event.c',
|
||||
'qmp-registry.c',
|
||||
))
|
||||
endif
|
||||
|
||||
qapi_all_modules = [
|
||||
'acpi',
|
||||
'audio',
|
||||
'authz',
|
||||
'block',
|
||||
'block-core',
|
||||
@ -35,20 +37,30 @@ qapi_all_modules = [
|
||||
'misc-target',
|
||||
'net',
|
||||
'pragma',
|
||||
'qdev',
|
||||
'pci',
|
||||
'qom',
|
||||
'rdma',
|
||||
'replay',
|
||||
'rocker',
|
||||
'run-state',
|
||||
'sockets',
|
||||
'tpm',
|
||||
'trace',
|
||||
'transaction',
|
||||
'ui',
|
||||
'yank',
|
||||
]
|
||||
if have_system
|
||||
qapi_all_modules += [
|
||||
'acpi',
|
||||
'audio',
|
||||
'qdev',
|
||||
'pci',
|
||||
'rdma',
|
||||
'rocker',
|
||||
'tpm',
|
||||
]
|
||||
endif
|
||||
if have_system or have_tools
|
||||
qapi_all_modules += [
|
||||
'ui',
|
||||
]
|
||||
endif
|
||||
|
||||
qapi_storage_daemon_modules = [
|
||||
'block-core',
|
||||
|
@ -35,7 +35,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
|
||||
" suppress-vmdesc=on|off disables self-describing migration (default=off)\n"
|
||||
" nvdimm=on|off controls NVDIMM support (default=off)\n"
|
||||
" memory-encryption=@var{} memory encryption object to use (default=none)\n"
|
||||
" hmat=on|off controls ACPI HMAT support (default=off)\n",
|
||||
" hmat=on|off controls ACPI HMAT support (default=off)\n"
|
||||
" memory-backend='backend-id' specifies explicitly provided backend for main RAM (default=none)\n",
|
||||
QEMU_ARCH_ALL)
|
||||
SRST
|
||||
``-machine [type=]name[,prop=value[,...]]``
|
||||
@ -96,6 +97,29 @@ SRST
|
||||
``hmat=on|off``
|
||||
Enables or disables ACPI Heterogeneous Memory Attribute Table
|
||||
(HMAT) support. The default is off.
|
||||
|
||||
``memory-backend='id'``
|
||||
An alternative to legacy ``-mem-path`` and ``mem-prealloc`` options.
|
||||
Allows to use a memory backend as main RAM.
|
||||
|
||||
For example:
|
||||
::
|
||||
-object memory-backend-file,id=pc.ram,size=512M,mem-path=/hugetlbfs,prealloc=on,share=on
|
||||
-machine memory-backend=pc.ram
|
||||
-m 512M
|
||||
|
||||
Migration compatibility note:
|
||||
a) as backend id one shall use value of 'default-ram-id', advertised by
|
||||
machine type (available via ``query-machines`` QMP command), if migration
|
||||
to/from old QEMU (<5.0) is expected.
|
||||
b) for machine types 4.0 and older, user shall
|
||||
use ``x-use-canonical-path-for-ramblock-id=off`` backend option
|
||||
if migration to/from old QEMU (<5.0) is expected.
|
||||
For example:
|
||||
::
|
||||
-object memory-backend-ram,id=pc.ram,size=512M,x-use-canonical-path-for-ramblock-id=off
|
||||
-machine memory-backend=pc.ram
|
||||
-m 512M
|
||||
ERST
|
||||
|
||||
HXCOMM Deprecated by -machine
|
||||
|
@ -261,7 +261,7 @@ def clear_bits(newtrace, outpath):
|
||||
data_try = hex(int("".join(data_bin_list), 2))
|
||||
# It seems qtest only accepts padded hex-values.
|
||||
if len(data_try) % 2 == 1:
|
||||
data_try = data_try[:2] + "0" + data_try[2:-1]
|
||||
data_try = data_try[:2] + "0" + data_try[2:]
|
||||
|
||||
newtrace[i] = "{prefix} {data_try}\n".format(
|
||||
prefix=prefix,
|
||||
|
@ -90,14 +90,21 @@ static void cpu_throttle_timer_tick(void *opaque)
|
||||
|
||||
void cpu_throttle_set(int new_throttle_pct)
|
||||
{
|
||||
/*
|
||||
* boolean to store whether throttle is already active or not,
|
||||
* before modifying throttle_percentage
|
||||
*/
|
||||
bool throttle_active = cpu_throttle_active();
|
||||
|
||||
/* Ensure throttle percentage is within valid range */
|
||||
new_throttle_pct = MIN(new_throttle_pct, CPU_THROTTLE_PCT_MAX);
|
||||
new_throttle_pct = MAX(new_throttle_pct, CPU_THROTTLE_PCT_MIN);
|
||||
|
||||
qatomic_set(&throttle_percentage, new_throttle_pct);
|
||||
|
||||
timer_mod(throttle_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT) +
|
||||
CPU_THROTTLE_TIMESLICE_NS);
|
||||
if (!throttle_active) {
|
||||
cpu_throttle_timer_tick(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_throttle_stop(void)
|
||||
|
@ -1440,7 +1440,7 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
|
||||
unsigned size = memop_size(op);
|
||||
MemTxResult r;
|
||||
|
||||
fuzz_dma_read_cb(addr, size, mr, false);
|
||||
fuzz_dma_read_cb(addr, size, mr);
|
||||
if (!memory_region_access_valid(mr, addr, size, false, attrs)) {
|
||||
*pval = unassigned_mem_read(mr, addr, size);
|
||||
return MEMTX_DECODE_ERROR;
|
||||
@ -3285,8 +3285,7 @@ void memory_region_init_rom_device(MemoryRegion *mr,
|
||||
#ifdef CONFIG_FUZZ
|
||||
void __attribute__((weak)) fuzz_dma_read_cb(size_t addr,
|
||||
size_t len,
|
||||
MemoryRegion *mr,
|
||||
bool is_write)
|
||||
MemoryRegion *mr)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
@ -2839,7 +2839,7 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
|
||||
stn_he_p(buf, l, val);
|
||||
} else {
|
||||
/* RAM case */
|
||||
fuzz_dma_read_cb(addr, len, mr, false);
|
||||
fuzz_dma_read_cb(addr, len, mr);
|
||||
ram_ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
|
||||
memcpy(buf, ram_ptr, l);
|
||||
}
|
||||
@ -3200,7 +3200,7 @@ void *address_space_map(AddressSpace *as,
|
||||
memory_region_ref(mr);
|
||||
*plen = flatview_extend_translation(fv, addr, len, mr, xlat,
|
||||
l, is_write, attrs);
|
||||
fuzz_dma_read_cb(addr, *plen, mr, is_write);
|
||||
fuzz_dma_read_cb(addr, *plen, mr);
|
||||
ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen, true);
|
||||
|
||||
return ptr;
|
||||
|
@ -53,4 +53,6 @@ endif
|
||||
if have_system
|
||||
stub_ss.add(files('semihost.c'))
|
||||
stub_ss.add(files('xen-hw-stub.c'))
|
||||
else
|
||||
stub_ss.add(files('qdev.c'))
|
||||
endif
|
||||
|
23
stubs/qdev.c
Normal file
23
stubs/qdev.c
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* QOM stubs
|
||||
*
|
||||
* Copyright (c) 2021 Red Hat, Inc.
|
||||
*
|
||||
* Author:
|
||||
* Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* 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 "qapi/qapi-events-qdev.h"
|
||||
|
||||
void qapi_event_send_device_deleted(bool has_device,
|
||||
const char *device,
|
||||
const char *path)
|
||||
{
|
||||
/* Nothing to do. */
|
||||
}
|
@ -667,7 +667,7 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
|
||||
CPUID_7_0_EBX_RDSEED */
|
||||
#define TCG_7_0_ECX_FEATURES (CPUID_7_0_ECX_PKU | \
|
||||
/* CPUID_7_0_ECX_OSPKE is dynamic */ \
|
||||
CPUID_7_0_ECX_LA57)
|
||||
CPUID_7_0_ECX_LA57 | CPUID_7_0_ECX_PKS)
|
||||
#define TCG_7_0_EDX_FEATURES 0
|
||||
#define TCG_7_1_EAX_FEATURES 0
|
||||
#define TCG_APM_FEATURES 0
|
||||
@ -926,11 +926,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||
"npt", "lbrv", "svm-lock", "nrip-save",
|
||||
"tsc-scale", "vmcb-clean", "flushbyasid", "decodeassists",
|
||||
NULL, NULL, "pause-filter", NULL,
|
||||
"pfthreshold", NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
"pfthreshold", "avic", NULL, "v-vmsave-vmload",
|
||||
"vgif", NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
"svme-addr-chk", NULL, NULL, NULL,
|
||||
},
|
||||
.cpuid = { .eax = 0x8000000A, .reg = R_EDX, },
|
||||
.tcg_features = TCG_SVM_FEATURES,
|
||||
@ -964,7 +964,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||
"la57", NULL, NULL, NULL,
|
||||
NULL, NULL, "rdpid", NULL,
|
||||
NULL, "cldemote", NULL, "movdiri",
|
||||
"movdir64b", NULL, NULL, NULL,
|
||||
"movdir64b", NULL, NULL, "pks",
|
||||
},
|
||||
.cpuid = {
|
||||
.eax = 7,
|
||||
@ -1215,7 +1215,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||
"vmx-exit-save-efer", "vmx-exit-load-efer",
|
||||
"vmx-exit-save-preemption-timer", "vmx-exit-clear-bndcfgs",
|
||||
NULL, "vmx-exit-clear-rtit-ctl", NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, "vmx-exit-load-pkrs", NULL, NULL,
|
||||
},
|
||||
.msr = {
|
||||
.index = MSR_IA32_VMX_TRUE_EXIT_CTLS,
|
||||
@ -1230,7 +1230,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||
NULL, "vmx-entry-ia32e-mode", NULL, NULL,
|
||||
NULL, "vmx-entry-load-perf-global-ctrl", "vmx-entry-load-pat", "vmx-entry-load-efer",
|
||||
"vmx-entry-load-bndcfgs", NULL, "vmx-entry-load-rtit-ctl", NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, "vmx-entry-load-pkrs", NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
},
|
||||
@ -5073,6 +5073,11 @@ static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
||||
} else {
|
||||
return ~0;
|
||||
}
|
||||
#ifndef TARGET_X86_64
|
||||
if (w == FEAT_8000_0001_EDX) {
|
||||
r &= ~CPUID_EXT2_LM;
|
||||
}
|
||||
#endif
|
||||
if (migratable_only) {
|
||||
r &= x86_cpu_get_migratable_flags(w);
|
||||
}
|
||||
|
@ -247,6 +247,7 @@ typedef enum X86Seg {
|
||||
#define CR4_SMEP_MASK (1U << 20)
|
||||
#define CR4_SMAP_MASK (1U << 21)
|
||||
#define CR4_PKE_MASK (1U << 22)
|
||||
#define CR4_PKS_MASK (1U << 24)
|
||||
|
||||
#define DR6_BD (1 << 13)
|
||||
#define DR6_BS (1 << 14)
|
||||
@ -357,6 +358,7 @@ typedef enum X86Seg {
|
||||
|
||||
#define MSR_IA32_TSX_CTRL 0x122
|
||||
#define MSR_IA32_TSCDEADLINE 0x6e0
|
||||
#define MSR_IA32_PKRS 0x6e1
|
||||
|
||||
#define FEATURE_CONTROL_LOCKED (1<<0)
|
||||
#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1<<2)
|
||||
@ -670,16 +672,20 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
|
||||
#define CPUID_EXT3_PERFCORE (1U << 23)
|
||||
#define CPUID_EXT3_PERFNB (1U << 24)
|
||||
|
||||
#define CPUID_SVM_NPT (1U << 0)
|
||||
#define CPUID_SVM_LBRV (1U << 1)
|
||||
#define CPUID_SVM_SVMLOCK (1U << 2)
|
||||
#define CPUID_SVM_NRIPSAVE (1U << 3)
|
||||
#define CPUID_SVM_TSCSCALE (1U << 4)
|
||||
#define CPUID_SVM_VMCBCLEAN (1U << 5)
|
||||
#define CPUID_SVM_FLUSHASID (1U << 6)
|
||||
#define CPUID_SVM_DECODEASSIST (1U << 7)
|
||||
#define CPUID_SVM_PAUSEFILTER (1U << 10)
|
||||
#define CPUID_SVM_PFTHRESHOLD (1U << 12)
|
||||
#define CPUID_SVM_NPT (1U << 0)
|
||||
#define CPUID_SVM_LBRV (1U << 1)
|
||||
#define CPUID_SVM_SVMLOCK (1U << 2)
|
||||
#define CPUID_SVM_NRIPSAVE (1U << 3)
|
||||
#define CPUID_SVM_TSCSCALE (1U << 4)
|
||||
#define CPUID_SVM_VMCBCLEAN (1U << 5)
|
||||
#define CPUID_SVM_FLUSHASID (1U << 6)
|
||||
#define CPUID_SVM_DECODEASSIST (1U << 7)
|
||||
#define CPUID_SVM_PAUSEFILTER (1U << 10)
|
||||
#define CPUID_SVM_PFTHRESHOLD (1U << 12)
|
||||
#define CPUID_SVM_AVIC (1U << 13)
|
||||
#define CPUID_SVM_V_VMSAVE_VMLOAD (1U << 15)
|
||||
#define CPUID_SVM_VGIF (1U << 16)
|
||||
#define CPUID_SVM_SVME_ADDR_CHK (1U << 28)
|
||||
|
||||
/* Support RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE */
|
||||
#define CPUID_7_0_EBX_FSGSBASE (1U << 0)
|
||||
@ -768,6 +774,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
|
||||
#define CPUID_7_0_ECX_MOVDIRI (1U << 27)
|
||||
/* Move 64 Bytes as Direct Store Instruction */
|
||||
#define CPUID_7_0_ECX_MOVDIR64B (1U << 28)
|
||||
/* Protection Keys for Supervisor-mode Pages */
|
||||
#define CPUID_7_0_ECX_PKS (1U << 31)
|
||||
|
||||
/* AVX512 Neural Network Instructions */
|
||||
#define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2)
|
||||
@ -965,6 +973,7 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
|
||||
#define VMX_VM_EXIT_CLEAR_BNDCFGS 0x00800000
|
||||
#define VMX_VM_EXIT_PT_CONCEAL_PIP 0x01000000
|
||||
#define VMX_VM_EXIT_CLEAR_IA32_RTIT_CTL 0x02000000
|
||||
#define VMX_VM_EXIT_LOAD_IA32_PKRS 0x20000000
|
||||
|
||||
#define VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS 0x00000004
|
||||
#define VMX_VM_ENTRY_IA32E_MODE 0x00000200
|
||||
@ -976,6 +985,7 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
|
||||
#define VMX_VM_ENTRY_LOAD_BNDCFGS 0x00010000
|
||||
#define VMX_VM_ENTRY_PT_CONCEAL_PIP 0x00020000
|
||||
#define VMX_VM_ENTRY_LOAD_IA32_RTIT_CTL 0x00040000
|
||||
#define VMX_VM_ENTRY_LOAD_IA32_PKRS 0x00400000
|
||||
|
||||
/* Supported Hyper-V Enlightenments */
|
||||
#define HYPERV_FEAT_RELAXED 0
|
||||
@ -1483,6 +1493,7 @@ typedef struct CPUX86State {
|
||||
uint64_t msr_smi_count;
|
||||
|
||||
uint32_t pkru;
|
||||
uint32_t pkrs;
|
||||
uint32_t tsx_ctrl;
|
||||
|
||||
uint64_t spec_ctrl;
|
||||
|
@ -194,6 +194,9 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
|
||||
if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKU)) {
|
||||
new_cr4 &= ~CR4_PKE_MASK;
|
||||
}
|
||||
if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKS)) {
|
||||
new_cr4 &= ~CR4_PKS_MASK;
|
||||
}
|
||||
|
||||
env->cr[4] = new_cr4;
|
||||
env->hflags = hflags;
|
||||
|
@ -113,6 +113,7 @@ static bool has_msr_vmx_vmfunc;
|
||||
static bool has_msr_ucode_rev;
|
||||
static bool has_msr_vmx_procbased_ctls2;
|
||||
static bool has_msr_perf_capabs;
|
||||
static bool has_msr_pkrs;
|
||||
|
||||
static uint32_t has_architectural_pmu_version;
|
||||
static uint32_t num_architectural_pmu_gp_counters;
|
||||
@ -2087,6 +2088,9 @@ static int kvm_get_supported_msrs(KVMState *s)
|
||||
case MSR_IA32_VMX_PROCBASED_CTLS2:
|
||||
has_msr_vmx_procbased_ctls2 = true;
|
||||
break;
|
||||
case MSR_IA32_PKRS:
|
||||
has_msr_pkrs = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2814,6 +2818,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
if (has_msr_smi_count) {
|
||||
kvm_msr_entry_add(cpu, MSR_SMI_COUNT, env->msr_smi_count);
|
||||
}
|
||||
if (has_msr_pkrs) {
|
||||
kvm_msr_entry_add(cpu, MSR_IA32_PKRS, env->pkrs);
|
||||
}
|
||||
if (has_msr_bndcfgs) {
|
||||
kvm_msr_entry_add(cpu, MSR_IA32_BNDCFGS, env->msr_bndcfgs);
|
||||
}
|
||||
@ -3205,6 +3212,9 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
if (has_msr_feature_control) {
|
||||
kvm_msr_entry_add(cpu, MSR_IA32_FEATURE_CONTROL, 0);
|
||||
}
|
||||
if (has_msr_pkrs) {
|
||||
kvm_msr_entry_add(cpu, MSR_IA32_PKRS, 0);
|
||||
}
|
||||
if (has_msr_bndcfgs) {
|
||||
kvm_msr_entry_add(cpu, MSR_IA32_BNDCFGS, 0);
|
||||
}
|
||||
@ -3475,6 +3485,9 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
case MSR_IA32_UMWAIT_CONTROL:
|
||||
env->umwait = msrs[i].data;
|
||||
break;
|
||||
case MSR_IA32_PKRS:
|
||||
env->pkrs = msrs[i].data;
|
||||
break;
|
||||
default:
|
||||
if (msrs[i].index >= MSR_MC0_CTL &&
|
||||
msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) {
|
||||
|
@ -980,7 +980,6 @@ static const VMStateDescription vmstate_umwait = {
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef TARGET_X86_64
|
||||
static bool pkru_needed(void *opaque)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
@ -999,7 +998,25 @@ static const VMStateDescription vmstate_pkru = {
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
static bool pkrs_needed(void *opaque)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
return env->pkrs != 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pkrs = {
|
||||
.name = "cpu/pkrs",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = pkrs_needed,
|
||||
.fields = (VMStateField[]){
|
||||
VMSTATE_UINT32(env.pkrs, X86CPU),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static bool tsc_khz_needed(void *opaque)
|
||||
{
|
||||
@ -1480,9 +1497,8 @@ VMStateDescription vmstate_x86_cpu = {
|
||||
&vmstate_umwait,
|
||||
&vmstate_tsc_khz,
|
||||
&vmstate_msr_smi_count,
|
||||
#ifdef TARGET_X86_64
|
||||
&vmstate_pkru,
|
||||
#endif
|
||||
&vmstate_pkrs,
|
||||
&vmstate_spec_ctrl,
|
||||
&vmstate_mcg_ext_ctl,
|
||||
&vmstate_msr_intel_pt,
|
||||
|
@ -361,6 +361,7 @@ static int handle_mmu_fault(CPUState *cs, vaddr addr, int size,
|
||||
uint64_t rsvd_mask = PG_HI_RSVD_MASK;
|
||||
uint32_t page_offset;
|
||||
target_ulong vaddr;
|
||||
uint32_t pkr;
|
||||
|
||||
is_user = mmu_idx == MMU_USER_IDX;
|
||||
#if defined(DEBUG_MMU)
|
||||
@ -588,21 +589,28 @@ do_check_protect_pse36:
|
||||
!((env->cr[4] & CR4_SMEP_MASK) && (ptep & PG_USER_MASK)))) {
|
||||
prot |= PAGE_EXEC;
|
||||
}
|
||||
if ((env->cr[4] & CR4_PKE_MASK) && (env->hflags & HF_LMA_MASK) &&
|
||||
(ptep & PG_USER_MASK) && env->pkru) {
|
||||
uint32_t pk = (pte & PG_PKRU_MASK) >> PG_PKRU_BIT;
|
||||
uint32_t pkru_ad = (env->pkru >> pk * 2) & 1;
|
||||
uint32_t pkru_wd = (env->pkru >> pk * 2) & 2;
|
||||
uint32_t pkru_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
|
||||
if (pkru_ad) {
|
||||
pkru_prot &= ~(PAGE_READ | PAGE_WRITE);
|
||||
} else if (pkru_wd && (is_user || env->cr[0] & CR0_WP_MASK)) {
|
||||
pkru_prot &= ~PAGE_WRITE;
|
||||
if (!(env->hflags & HF_LMA_MASK)) {
|
||||
pkr = 0;
|
||||
} else if (ptep & PG_USER_MASK) {
|
||||
pkr = env->cr[4] & CR4_PKE_MASK ? env->pkru : 0;
|
||||
} else {
|
||||
pkr = env->cr[4] & CR4_PKS_MASK ? env->pkrs : 0;
|
||||
}
|
||||
if (pkr) {
|
||||
uint32_t pk = (pte & PG_PKRU_MASK) >> PG_PKRU_BIT;
|
||||
uint32_t pkr_ad = (pkr >> pk * 2) & 1;
|
||||
uint32_t pkr_wd = (pkr >> pk * 2) & 2;
|
||||
uint32_t pkr_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
|
||||
if (pkr_ad) {
|
||||
pkr_prot &= ~(PAGE_READ | PAGE_WRITE);
|
||||
} else if (pkr_wd && (is_user || env->cr[0] & CR0_WP_MASK)) {
|
||||
pkr_prot &= ~PAGE_WRITE;
|
||||
}
|
||||
|
||||
prot &= pkru_prot;
|
||||
if ((pkru_prot & (1 << is_write1)) == 0) {
|
||||
prot &= pkr_prot;
|
||||
if ((pkr_prot & (1 << is_write1)) == 0) {
|
||||
assert(is_write1 != 2);
|
||||
error_code |= PG_ERROR_PK_MASK;
|
||||
goto do_fault_protect;
|
||||
|
@ -244,6 +244,7 @@ void helper_rdmsr(CPUX86State *env)
|
||||
void helper_wrmsr(CPUX86State *env)
|
||||
{
|
||||
uint64_t val;
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
|
||||
|
||||
@ -296,6 +297,13 @@ void helper_wrmsr(CPUX86State *env)
|
||||
case MSR_PAT:
|
||||
env->pat = val;
|
||||
break;
|
||||
case MSR_IA32_PKRS:
|
||||
if (val & 0xFFFFFFFF00000000ull) {
|
||||
goto error;
|
||||
}
|
||||
env->pkrs = val;
|
||||
tlb_flush(cs);
|
||||
break;
|
||||
case MSR_VM_HSAVE_PA:
|
||||
env->vm_hsave = val;
|
||||
break;
|
||||
@ -399,6 +407,9 @@ void helper_wrmsr(CPUX86State *env)
|
||||
/* XXX: exception? */
|
||||
break;
|
||||
}
|
||||
return;
|
||||
error:
|
||||
raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
|
||||
}
|
||||
|
||||
void helper_rdmsr(CPUX86State *env)
|
||||
@ -430,6 +441,9 @@ void helper_rdmsr(CPUX86State *env)
|
||||
case MSR_PAT:
|
||||
val = env->pat;
|
||||
break;
|
||||
case MSR_IA32_PKRS:
|
||||
val = env->pkrs;
|
||||
break;
|
||||
case MSR_VM_HSAVE_PA:
|
||||
val = env->vm_hsave;
|
||||
break;
|
||||
|
@ -3075,7 +3075,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
|
||||
}
|
||||
if (is_xmm
|
||||
&& !(s->flags & HF_OSFXSR_MASK)
|
||||
&& ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))) {
|
||||
&& (b != 0x38 && b != 0x3a)) {
|
||||
goto unknown_op;
|
||||
}
|
||||
if (b == 0x0e) {
|
||||
|
@ -86,7 +86,6 @@ tests = {
|
||||
'test-qobject-input-visitor': [testqapi],
|
||||
'test-string-input-visitor': [testqapi],
|
||||
'test-string-output-visitor': [testqapi],
|
||||
'test-qmp-event': [testqapi],
|
||||
'test-opts-visitor': [testqapi],
|
||||
'test-visitor-serialization': [testqapi],
|
||||
'test-bitmap': [],
|
||||
@ -117,6 +116,12 @@ tests = {
|
||||
'test-qapi-util': [],
|
||||
}
|
||||
|
||||
if have_system or have_tools
|
||||
tests += {
|
||||
'test-qmp-event': [testqapi],
|
||||
}
|
||||
endif
|
||||
|
||||
test_deps = {
|
||||
'test-qht-par': qht_bench,
|
||||
}
|
||||
@ -276,7 +281,9 @@ test('decodetree', sh,
|
||||
workdir: meson.current_source_dir() / 'decode',
|
||||
suite: 'decodetree')
|
||||
|
||||
subdir('fp')
|
||||
if 'CONFIG_TCG' in config_all
|
||||
subdir('fp')
|
||||
endif
|
||||
|
||||
if not get_option('tcg').disabled()
|
||||
if 'CONFIG_PLUGIN' in config_host
|
||||
|
@ -159,6 +159,8 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
|
||||
char *target_name;
|
||||
const char *bindir;
|
||||
char *datadir;
|
||||
GString *cmd_line;
|
||||
gchar *pretty_cmd_line;
|
||||
bool serialize = false;
|
||||
|
||||
/* Initialize qgraph and modules */
|
||||
@ -217,7 +219,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
|
||||
}
|
||||
|
||||
/* Run QEMU's softmmu main with the fuzz-target dependent arguments */
|
||||
GString *cmd_line = fuzz_target->get_init_cmdline(fuzz_target);
|
||||
cmd_line = fuzz_target->get_init_cmdline(fuzz_target);
|
||||
g_string_append_printf(cmd_line, " %s -qtest /dev/null ",
|
||||
getenv("QTEST_LOG") ? "" : "-qtest-log none");
|
||||
|
||||
@ -226,6 +228,13 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
|
||||
wordexp(cmd_line->str, &result, 0);
|
||||
g_string_free(cmd_line, true);
|
||||
|
||||
if (getenv("QTEST_LOG")) {
|
||||
pretty_cmd_line = g_strjoinv(" ", result.we_wordv + 1);
|
||||
printf("Starting %s with Arguments: %s\n",
|
||||
result.we_wordv[0], pretty_cmd_line);
|
||||
g_free(pretty_cmd_line);
|
||||
}
|
||||
|
||||
qemu_init(result.we_wordc, result.we_wordv, NULL);
|
||||
|
||||
/* re-enable the rcu atfork, which was previously disabled in qemu_init */
|
||||
|
@ -175,7 +175,7 @@ static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
|
||||
* generic_fuzz(), avoiding potential race-conditions, which we don't have
|
||||
* a good way for reproducing right now.
|
||||
*/
|
||||
void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr, bool is_write)
|
||||
void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr)
|
||||
{
|
||||
/* Are we in the generic-fuzzer or are we using another fuzz-target? */
|
||||
if (!qts_global) {
|
||||
@ -187,14 +187,11 @@ void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr, bool is_write)
|
||||
* - We have no DMA patterns defined
|
||||
* - The length of the DMA read request is zero
|
||||
* - The DMA read is hitting an MR other than the machine's main RAM
|
||||
* - The DMA request is not a read (what happens for a address_space_map
|
||||
* with is_write=True? Can the device use the same pointer to do reads?)
|
||||
* - The DMA request hits past the bounds of our RAM
|
||||
*/
|
||||
if (dma_patterns->len == 0
|
||||
|| len == 0
|
||||
|| mr != current_machine->ram
|
||||
|| is_write
|
||||
|| addr > current_machine->ram_size) {
|
||||
return;
|
||||
}
|
||||
@ -213,12 +210,12 @@ void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr, bool is_write)
|
||||
double_fetch = true;
|
||||
if (addr < region.addr
|
||||
&& avoid_double_fetches) {
|
||||
fuzz_dma_read_cb(addr, region.addr - addr, mr, is_write);
|
||||
fuzz_dma_read_cb(addr, region.addr - addr, mr);
|
||||
}
|
||||
if (addr + len > region.addr + region.size
|
||||
&& avoid_double_fetches) {
|
||||
fuzz_dma_read_cb(region.addr + region.size,
|
||||
addr + len - (region.addr + region.size), mr, is_write);
|
||||
addr + len - (region.addr + region.size), mr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -936,12 +933,20 @@ static GString *generic_fuzz_cmdline(FuzzTarget *t)
|
||||
|
||||
static GString *generic_fuzz_predefined_config_cmdline(FuzzTarget *t)
|
||||
{
|
||||
gchar *args;
|
||||
const generic_fuzz_config *config;
|
||||
g_assert(t->opaque);
|
||||
|
||||
config = t->opaque;
|
||||
setenv("QEMU_AVOID_DOUBLE_FETCH", "1", 1);
|
||||
setenv("QEMU_FUZZ_ARGS", config->args, 1);
|
||||
if (config->argfunc) {
|
||||
args = config->argfunc();
|
||||
setenv("QEMU_FUZZ_ARGS", args, 1);
|
||||
g_free(args);
|
||||
} else {
|
||||
g_assert_nonnull(config->args);
|
||||
setenv("QEMU_FUZZ_ARGS", config->args, 1);
|
||||
}
|
||||
setenv("QEMU_FUZZ_OBJECTS", config->objects, 1);
|
||||
return generic_fuzz_cmdline(t);
|
||||
}
|
||||
|
@ -16,8 +16,19 @@
|
||||
|
||||
typedef struct generic_fuzz_config {
|
||||
const char *name, *args, *objects;
|
||||
gchar* (*argfunc)(void); /* Result must be freeable by g_free() */
|
||||
} generic_fuzz_config;
|
||||
|
||||
static inline gchar *generic_fuzzer_virtio_9p_args(void){
|
||||
char tmpdir[] = "/tmp/qemu-fuzz.XXXXXX";
|
||||
g_assert_nonnull(mkdtemp(tmpdir));
|
||||
|
||||
return g_strdup_printf("-machine q35 -nodefaults "
|
||||
"-device virtio-9p,fsdev=hshare,mount_tag=hshare "
|
||||
"-fsdev local,id=hshare,path=%s,security_model=mapped-xattr,"
|
||||
"writeout=immediate,fmode=0600,dmode=0700", tmpdir);
|
||||
}
|
||||
|
||||
const generic_fuzz_config predefined_configs[] = {
|
||||
{
|
||||
.name = "virtio-net-pci-slirp",
|
||||
@ -59,6 +70,16 @@ const generic_fuzz_config predefined_configs[] = {
|
||||
.name = "virtio-mouse",
|
||||
.args = "-machine q35 -nodefaults -device virtio-mouse",
|
||||
.objects = "virtio*",
|
||||
},{
|
||||
.name = "virtio-9p",
|
||||
.argfunc = generic_fuzzer_virtio_9p_args,
|
||||
.objects = "virtio*",
|
||||
},{
|
||||
.name = "virtio-9p-synth",
|
||||
.args = "-machine q35 -nodefaults "
|
||||
"-device virtio-9p,fsdev=hshare,mount_tag=hshare "
|
||||
"-fsdev synth,id=hshare",
|
||||
.objects = "virtio*",
|
||||
},{
|
||||
.name = "e1000",
|
||||
.args = "-M q35 -nodefaults "
|
||||
@ -85,10 +106,28 @@ const generic_fuzz_config predefined_configs[] = {
|
||||
.objects = "intel-hda",
|
||||
},{
|
||||
.name = "ide-hd",
|
||||
.args = "-machine pc -nodefaults "
|
||||
"-drive file=null-co://,if=none,format=raw,id=disk0 "
|
||||
"-device ide-hd,drive=disk0",
|
||||
.objects = "*ide*",
|
||||
},{
|
||||
.name = "ide-atapi",
|
||||
.args = "-machine pc -nodefaults "
|
||||
"-drive file=null-co://,if=none,format=raw,id=disk0 "
|
||||
"-device ide-cd,drive=disk0",
|
||||
.objects = "*ide*",
|
||||
},{
|
||||
.name = "ahci-hd",
|
||||
.args = "-machine q35 -nodefaults "
|
||||
"-drive file=null-co://,if=none,format=raw,id=disk0 "
|
||||
"-device ide-hd,drive=disk0",
|
||||
.objects = "ahci*",
|
||||
.objects = "*ahci*",
|
||||
},{
|
||||
.name = "ahci-atapi",
|
||||
.args = "-machine q35 -nodefaults "
|
||||
"-drive file=null-co://,if=none,format=raw,id=disk0 "
|
||||
"-device ide-cd,drive=disk0",
|
||||
.objects = "*ahci*",
|
||||
},{
|
||||
.name = "floppy",
|
||||
.args = "-machine pc -nodefaults -device floppy,id=floppy0 "
|
||||
|
@ -29,6 +29,7 @@ void event_notifier_init_fd(EventNotifier *e, int fd)
|
||||
{
|
||||
e->rfd = fd;
|
||||
e->wfd = fd;
|
||||
e->initialized = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -68,6 +69,7 @@ int event_notifier_init(EventNotifier *e, int active)
|
||||
if (active) {
|
||||
event_notifier_set(e);
|
||||
}
|
||||
e->initialized = true;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@ -78,12 +80,18 @@ fail:
|
||||
|
||||
void event_notifier_cleanup(EventNotifier *e)
|
||||
{
|
||||
if (!e->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e->rfd != e->wfd) {
|
||||
close(e->rfd);
|
||||
}
|
||||
|
||||
e->rfd = -1;
|
||||
close(e->wfd);
|
||||
e->wfd = -1;
|
||||
e->initialized = false;
|
||||
}
|
||||
|
||||
int event_notifier_get_fd(const EventNotifier *e)
|
||||
@ -96,6 +104,10 @@ int event_notifier_set(EventNotifier *e)
|
||||
static const uint64_t value = 1;
|
||||
ssize_t ret;
|
||||
|
||||
if (!e->initialized) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
ret = write(e->wfd, &value, sizeof(value));
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
@ -113,6 +125,10 @@ int event_notifier_test_and_clear(EventNotifier *e)
|
||||
ssize_t len;
|
||||
char buffer[512];
|
||||
|
||||
if (!e->initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Drain the notify pipe. For eventfd, only 8 bytes will be read. */
|
||||
value = 0;
|
||||
do {
|
||||
|
Loading…
Reference in New Issue
Block a user